import { Freeze, Plus, Send, Convert, Card } from '@transferwise/icons';

import { Meta, StoryObj } from '@storybook/react-webpack5';
import { expect, fn, userEvent, within } from 'storybook/test';
import { useState } from 'react';
import CircularButton from './CircularButton';
import Title from '../title';
import Body from '../body';
import { withVariantConfig } from '../../.storybook/helpers';

const wait = async (ms: number) =>
  new Promise<void>((resolve) => {
    setTimeout(resolve, ms);
  });

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

type Story = StoryObj<typeof CircularButton>;

/** All priorities, types, and states across all themes. */
export const Variants: Story = {
  render: () => {
    const rowStyle = {
      display: 'grid',
      gridTemplateColumns: 'repeat(4, minmax(0, 100px))',
      gap: '16px',
      textAlign: 'center' as const,
    };

    return (
      <div style={{ display: 'flex', flexDirection: 'column', gap: '24px' }}>
        <div style={rowStyle}>
          <CircularButton priority="primary" type="default" icon={<Send />} onClick={fn()}>
            Primary
          </CircularButton>
          <CircularButton priority="secondary" type="default" icon={<Plus />} onClick={fn()}>
            Secondary
          </CircularButton>
          <CircularButton disabled priority="primary" type="default" icon={<Card />}>
            Primary disabled
          </CircularButton>
          <CircularButton disabled priority="secondary" type="default" icon={<Card />}>
            Secondary disabled
          </CircularButton>
        </div>
        <div style={rowStyle}>
          <CircularButton priority="primary" type="negative" icon={<Send />} onClick={fn()}>
            Primary
          </CircularButton>
          <CircularButton priority="secondary" type="negative" icon={<Convert />} onClick={fn()}>
            Secondary
          </CircularButton>
          <CircularButton disabled priority="primary" type="negative" icon={<Card />}>
            Primary disabled
          </CircularButton>
          <CircularButton disabled priority="secondary" type="negative" icon={<Card />}>
            Secondary disabled
          </CircularButton>
        </div>
      </div>
    );
  },
  ...withVariantConfig(['default', 'dark', 'bright-green', 'forest-green']),
};

/**
 * `Space` or `Enter` activates when focused. Tab skips disabled buttons.
 */
export const KeyboardInteraction: Story = {
  render: () => {
    const onClick = fn();
    return (
      <div style={{ display: 'flex', gap: '24px', padding: '16px' }}>
        <CircularButton priority="primary" type="default" icon={<Send />} onClick={onClick}>
          Send
        </CircularButton>
        <CircularButton priority="secondary" type="default" icon={<Plus />} onClick={onClick}>
          Add funds
        </CircularButton>
        <CircularButton priority="primary" type="negative" icon={<Convert />} onClick={onClick}>
          Convert
        </CircularButton>
        <CircularButton
          priority="primary"
          type="default"
          icon={<Card />}
          disabled
          onClick={onClick}
        >
          Disabled
        </CircularButton>
      </div>
    );
  },
  play: async ({ canvasElement, step }) => {
    const canvas = within(canvasElement);
    const buttons = canvas.getAllByRole('button');

    await step('tab to Send and press Space', async () => {
      await userEvent.tab();
      await expect(buttons[0]).toHaveFocus();
      await wait(400);
      await userEvent.keyboard(' ');
    });

    await wait(400);

    await step('tab to Add funds and press Space', async () => {
      await userEvent.tab();
      await expect(buttons[1]).toHaveFocus();
      await wait(400);
      await userEvent.keyboard(' ');
    });

    await wait(400);

    await step('tab to Convert and press Space', async () => {
      await userEvent.tab();
      await expect(buttons[2]).toHaveFocus();
      await wait(400);
      await userEvent.keyboard(' ');
    });

    await wait(400);

    await step('tab skips Disabled button', async () => {
      await userEvent.tab();
      // Disabled button should be skipped, focus leaves the component
      await expect(buttons[3]).not.toHaveFocus();
    });
  },
};

/** Base variants in right-to-left layout. */
export const RTL: Story = {
  render: function Render() {
    const [clicks, setClicks] = useState(0);
    const rowStyle = {
      display: 'grid',
      gridTemplateColumns: 'repeat(4, minmax(0, 100px))',
      gap: '16px',
      textAlign: 'center' as const,
    };

    return (
      <div style={{ display: 'flex', flexDirection: 'column', gap: '24px', padding: '16px' }}>
        <div style={rowStyle}>
          <CircularButton
            priority="primary"
            type="default"
            icon={<Send />}
            onClick={() => setClicks((c) => c + 1)}
          >
            Primary
          </CircularButton>
          <CircularButton
            priority="secondary"
            type="default"
            icon={<Plus />}
            onClick={() => setClicks((c) => c + 1)}
          >
            Secondary
          </CircularButton>
          <CircularButton disabled priority="primary" type="default" icon={<Card />}>
            Primary disabled
          </CircularButton>
          <CircularButton disabled priority="secondary" type="default" icon={<Card />}>
            Secondary disabled
          </CircularButton>
        </div>
        <div style={rowStyle}>
          <CircularButton
            priority="primary"
            type="negative"
            icon={<Send />}
            onClick={() => setClicks((c) => c + 1)}
          >
            Primary
          </CircularButton>
          <CircularButton
            priority="secondary"
            type="negative"
            icon={<Convert />}
            onClick={() => setClicks((c) => c + 1)}
          >
            Secondary
          </CircularButton>
          <CircularButton disabled priority="primary" type="negative" icon={<Card />}>
            Primary disabled
          </CircularButton>
          <CircularButton disabled priority="secondary" type="negative" icon={<Card />}>
            Secondary disabled
          </CircularButton>
        </div>
      </div>
    );
  },
  ...withVariantConfig(['rtl']),
};

/** Long labels are centered beneath the icon. */
export const CenteredText: Story = {
  render: () => {
    return (
      <div style={{ maxWidth: '100px' }}>
        <CircularButton priority="primary" type="default" icon={<Freeze />}>
          Very long text for a circular button that will be centered
        </CircularButton>
      </div>
    );
  },
};

const All: Story = {
  args: {
    children: 'Button text',
    icon: <Freeze />,
    className: 'm-r-2',
  },
  render: (props) => {
    return (
      <>
        <Title type="title-subsection" className="m-y-2">
          Default (Primary and secondary)
        </Title>
        <Body>
          <CircularButton {...props} priority="primary" type="default" />
          <CircularButton {...props} priority="secondary" type="default" />
          <CircularButton {...props} priority="primary" type="default" disabled />
          <CircularButton {...props} priority="secondary" type="default" disabled />
        </Body>

        <Title type="title-subsection" className="m-y-2">
          Negative (Primary and secondary)
        </Title>
        <Body>
          <CircularButton {...props} priority="primary" type="negative" />
          <CircularButton {...props} priority="secondary" type="negative" />
          <CircularButton {...props} priority="primary" type="negative" disabled />
          <CircularButton {...props} priority="secondary" type="negative" disabled />
        </Body>

        <Title type="title-body" className="m-y-2">
          Accent (Deprecated)
        </Title>
        <Body>
          <CircularButton {...props} priority="primary" type="accent" />
          <CircularButton {...props} priority="secondary" type="accent" />
          <CircularButton {...props} priority="primary" type="accent" disabled />
          <CircularButton {...props} priority="secondary" type="accent" disabled />
        </Body>

        <Title type="title-body" className="m-y-2">
          Positive (Deprecated)
        </Title>
        <Body>
          <CircularButton {...props} priority="primary" type="positive" />
          <CircularButton {...props} priority="secondary" type="positive" />
          <CircularButton {...props} priority="primary" type="positive" disabled />
          <CircularButton {...props} priority="secondary" type="positive" disabled />
        </Body>
      </>
    );
  },
};

/** All variants at 400% zoom for accessibility testing. */
export const Zoom400: Story = {
  ...All,
  ...withVariantConfig(['400%'], All),
};
