import { StoryFn, StoryObj } from '@storybook/react-webpack5';
import { expect, userEvent, within } from 'storybook/test';
import { action } from 'storybook/actions';
import { useState } from 'react';

import DateLookup, { type DateLookupProps } from './DateLookup';
import { Size } from '../common';
import { withVariantConfig } from '../../.storybook/helpers';

export default {
  component: DateLookup,
  title: 'Forms/DateLookup/Tests',
  tags: ['!manifest'],
};

const props: DateLookupProps = {
  value: new Date(1987, 0, 10, 12, 0, 0),
  onChange: (value: Date | null) => {
    action(value?.toString() || 'null');
  },
};
type Story = StoryFn<typeof DateLookup>;

const Template: Story = (args: DateLookupProps) => {
  const { value: initialValue } = args;
  const [value, setValue] = useState<Date | null>(initialValue);

  return (
    <DateLookup
      {...args}
      value={value}
      clearable
      placeholder="placeholder"
      onChange={(v) => {
        setValue(v);
      }}
    />
  );
};

export const ClearSpace = Template.bind({});
ClearSpace.args = { ...props };
ClearSpace.play = async ({ canvasElement, step }) => {
  const canvas = within(canvasElement);

  await step('space can activate clear button', async () => {
    // focus on clear button
    const date = await canvas.findByText('January 10, 1987');
    await expect(date).toBeInTheDocument();
    await userEvent.tab();
    await userEvent.tab();

    // clear with space
    await userEvent.keyboard(' ');
    const placeholder = canvas.getByText('placeholder');
    await expect(placeholder).toBeInTheDocument();
  });
};

export const ClearEnter = Template.bind({});
ClearEnter.args = { ...props };
ClearEnter.play = async ({ canvasElement, step }) => {
  const canvas = within(canvasElement);

  await step('enter can activate clear button', async () => {
    // focus on clear button
    const date = await canvas.findByText('January 10, 1987');
    await expect(date).toBeInTheDocument();
    await userEvent.tab();
    await userEvent.tab();

    // clear with space
    await userEvent.keyboard('{enter}');
    const placeholder = canvas.getByText('placeholder');
    await expect(placeholder).toBeInTheDocument();
  });
};

export const FocusOnSelectedDay = Template.bind({});
FocusOnSelectedDay.args = { ...props };
FocusOnSelectedDay.play = async () => {
  await userEvent.tab();
  await userEvent.keyboard(' ');
};

export const FocusOnFirstNonDisabledDate = Template.bind({});
FocusOnFirstNonDisabledDate.args = {
  ...props,
  value: null,
  min: new Date(1987, 0, 10, 12, 0, 0),
  max: new Date(1987, 0, 12, 12, 0, 0),
};
FocusOnFirstNonDisabledDate.play = async () => {
  await userEvent.tab();
  await userEvent.keyboard(' ');
};

const epoch = new Date('2011-01-01');
const theFuture = new Date(epoch);
theFuture.setUTCDate(epoch.getUTCDate() + 10);
const thePast = new Date(epoch);
thePast.setUTCDate(epoch.getUTCDate() - 10);

const Basic: StoryObj<typeof DateLookup> = {
  render: (args: DateLookupProps) => {
    const [value, setValue] = useState<Date | null>(epoch);
    return (
      <DateLookup
        {...args}
        min={args.min ? new Date(args.min) : thePast}
        max={args.max ? new Date(args.max) : theFuture}
        value={value}
        onChange={(v) => setValue(v)}
      />
    );
  },
  args: {
    size: Size.MEDIUM,
    disabled: false,
    label: 'label',
    monthFormat: 'long',
    placeholder: 'placeholder',
    id: 'date-lookup',
    clearable: true,
    min: thePast,
    max: theFuture,
  },
  play: async () => {
    await userEvent.tab();
    await userEvent.keyboard(' ');
  },
};

export const Basic400Zoom: StoryObj<typeof DateLookup> = {
  ...Basic,
  ...withVariantConfig(['400%'], {
    ...Basic,
    parameters: {
      chromatic: {
        delay: 2000,
      },
    },
  }),
};
