import type { Meta, StoryObj } from '@storybook/react-webpack5';
import { expect, userEvent, within } from 'storybook/test';
import { useState } from 'react';

import { withVariantConfig } from '../../.storybook/helpers';
import { Field } from '../field/Field';
import Switch from './Switch';

export default {
  component: Switch,
  title: 'Actions/Switch/Tests',
  tags: ['!autodocs', '!manifest'],
} satisfies Meta<typeof Switch>;

type Story = StoryObj<typeof Switch>;

/** All switch states across all themes. */
export const Variants: Story = {
  render: function Render() {
    const [unchecked, setUnchecked] = useState(false);
    const [checked, setChecked] = useState(true);

    return (
      <div style={{ display: 'flex', flexDirection: 'column', gap: '16px', padding: '16px' }}>
        <Field label="Unchecked">
          <Switch checked={unchecked} onClick={() => setUnchecked((v) => !v)} />
        </Field>
        <Field label="Checked">
          <Switch checked={checked} onClick={() => setChecked((v) => !v)} />
        </Field>
        <Field label="Disabled (off)">
          <Switch checked={false} disabled onClick={() => {}} />
        </Field>
        <Field label="Disabled (on)">
          <Switch checked disabled onClick={() => {}} />
        </Field>
      </div>
    );
  },
  ...withVariantConfig(['default', 'dark', 'bright-green', 'forest-green']),
};

/**
 * Tests keyboard navigation and interaction:
 * - Tab focuses the switch
 * - Space toggles the switch on and off
 */
export const KeyboardInteraction: Story = {
  render: function Render() {
    const [checked, setChecked] = useState(false);
    return (
      <Field id="notif-field" label="Email notifications">
        <Switch checked={checked} onClick={() => setChecked((v) => !v)} />
      </Field>
    );
  },
  play: async ({ canvasElement, step }) => {
    const wait = async (ms: number) =>
      new Promise<void>((resolve) => {
        setTimeout(resolve, ms);
      });
    const canvas = within(canvasElement);
    const switchEl = canvas.getByRole('switch');

    await step('tab focuses the switch', async () => {
      await userEvent.tab();
      await expect(switchEl).toHaveFocus();
    });

    await wait(400);

    await step('space toggles the switch on', async () => {
      await userEvent.keyboard(' ');
      await expect(switchEl).toHaveAttribute('aria-checked', 'true');
    });

    await wait(400);

    await step('space toggles the switch off', async () => {
      await userEvent.keyboard(' ');
      await expect(switchEl).toHaveAttribute('aria-checked', 'false');
    });
  },
};

/** Switch rendered in RTL mode. */
export const RTL: Story = {
  render: function Render() {
    const [unchecked, setUnchecked] = useState(false);
    const [checked, setChecked] = useState(true);

    return (
      <div style={{ display: 'flex', flexDirection: 'column', gap: '16px', padding: '16px' }}>
        <Field label="Unchecked">
          <Switch checked={unchecked} onClick={() => setUnchecked((v) => !v)} />
        </Field>
        <Field label="Checked">
          <Switch checked={checked} onClick={() => setChecked((v) => !v)} />
        </Field>
        <Field label="Disabled (off)">
          <Switch checked={false} disabled onClick={() => {}} />
        </Field>
        <Field label="Disabled (on)">
          <Switch checked disabled onClick={() => {}} />
        </Field>
      </div>
    );
  },
  ...withVariantConfig(['rtl']),
};

/** Switch at 400% zoom for accessibility testing. */
export const Zoom400: Story = {
  render: function Render() {
    const [checked, setChecked] = useState(false);
    return (
      <Field label="Email notifications">
        <Switch checked={checked} onClick={() => setChecked((v) => !v)} />
      </Field>
    );
  },
  ...withVariantConfig(['400%']),
};
