import { Meta, StoryObj } from '@storybook/react-webpack5';
import {
  Menu,
  Plus,
  Settings,
  Star,
  Travel,
  Cross,
  Edit,
  Briefcase,
  Bank,
  Freeze,
} from '@transferwise/icons';
import { expect, fn, userEvent, within } from 'storybook/test';
import IconButton from './IconButton';
import { withVariantConfig } from '../../.storybook/helpers';
import SentimentSurface from '../sentimentSurface';

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

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

type Story = StoryObj<typeof IconButton>;

/**
 * IconButton displayed across all themes and sentiments for visual regression testing.
 */
export const Variants: Story = {
  render: () => {
    const size = 32;
    const priorities = [
      { key: 'primary', label: 'primary' },
      { key: 'secondary', label: 'secondary' },
      { key: 'tertiary', label: 'tertiary' },
      { key: 'minimal', label: 'minimal' },
      { key: 'neg-primary', label: 'negative\nprimary' },
      { key: 'neg-secondary', label: 'negative\nsecondary' },
      { key: 'disabled', label: 'disabled' },
    ] as const;
    const sentiments = ['success', 'warning', 'negative', 'neutral', 'proposition'] as const;

    return (
      <div style={{ display: 'flex', flexDirection: 'column' }}>
        {/* Header row with priority labels */}
        <div style={{ display: 'flex', alignItems: 'flex-end', marginBottom: '4px', gap: '8px' }}>
          <div style={{ width: '82px', paddingLeft: '8px' }} />
          {priorities.map((priority) => (
            <div
              key={priority.key}
              style={{
                width: `${size}px`,
                textAlign: 'center',
                fontSize: '11px',
                fontWeight: 'bold',
                writingMode: 'vertical-rl',
                transform: 'rotate(180deg)',
                height: '80px',
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
                whiteSpace: 'pre',
                lineHeight: '1',
              }}
            >
              {priority.label}
            </div>
          ))}
        </div>

        {/* Rows for each sentiment with base and elevated emphasis */}
        {sentiments.flatMap((sentiment) => [
          <SentimentSurface
            key={`${sentiment}-base`}
            sentiment={sentiment}
            emphasis="base"
            style={{ display: 'flex', alignItems: 'center', padding: '8px 0', gap: '8px' }}
          >
            <div
              style={{
                width: '82px',
                fontSize: '11px',
                fontWeight: 'bold',
                textAlign: 'left',
                paddingLeft: '8px',
              }}
            >
              {sentiment} (base)
            </div>
            <IconButton
              size={size}
              aria-label="Primary action"
              priority="primary"
              type="default"
              onClick={fn()}
            >
              <Plus />
            </IconButton>
            <IconButton
              size={size}
              aria-label="Secondary action"
              priority="secondary"
              type="default"
              onClick={fn()}
            >
              <Settings />
            </IconButton>
            <IconButton
              size={size}
              aria-label="Tertiary action"
              priority="tertiary"
              type="default"
              onClick={fn()}
            >
              <Star />
            </IconButton>
            <IconButton
              size={size}
              aria-label="Minimal action"
              priority="minimal"
              type="default"
              onClick={fn()}
            >
              <Travel />
            </IconButton>
            <IconButton
              size={size}
              aria-label="Negative primary action"
              priority="primary"
              type="negative"
              onClick={fn()}
            >
              <Cross />
            </IconButton>
            <IconButton
              size={size}
              aria-label="Negative secondary action"
              priority="secondary"
              type="negative"
              onClick={fn()}
            >
              <Edit />
            </IconButton>
            <IconButton
              size={size}
              aria-label="Disabled action"
              priority="primary"
              type="default"
              disabled
              onClick={fn()}
            >
              <Menu />
            </IconButton>
          </SentimentSurface>,
          <SentimentSurface
            key={`${sentiment}-elevated`}
            sentiment={sentiment}
            emphasis="elevated"
            style={{ display: 'flex', alignItems: 'center', padding: '8px 0', gap: '8px' }}
          >
            <div
              style={{
                width: '82px',
                fontSize: '11px',
                fontWeight: 'bold',
                textAlign: 'left',
                paddingLeft: '8px',
              }}
            >
              {sentiment} (elevated)
            </div>
            <IconButton
              size={size}
              aria-label="Primary action"
              priority="primary"
              type="default"
              onClick={fn()}
            >
              <Briefcase />
            </IconButton>
            <IconButton
              size={size}
              aria-label="Secondary action"
              priority="secondary"
              type="default"
              onClick={fn()}
            >
              <Bank />
            </IconButton>
            <IconButton
              size={size}
              aria-label="Tertiary action"
              priority="tertiary"
              type="default"
              onClick={fn()}
            >
              <Freeze />
            </IconButton>
            <IconButton
              size={size}
              aria-label="Minimal action"
              priority="minimal"
              type="default"
              onClick={fn()}
            >
              <Edit />
            </IconButton>
            <IconButton
              size={size}
              aria-label="Negative primary action"
              priority="primary"
              type="negative"
              onClick={fn()}
            >
              <Cross />
            </IconButton>
            <IconButton
              size={size}
              aria-label="Negative secondary action"
              priority="secondary"
              type="negative"
              onClick={fn()}
            >
              <Edit />
            </IconButton>
            <IconButton
              size={size}
              aria-label="Disabled action"
              priority="primary"
              type="default"
              disabled
              onClick={fn()}
            >
              <Cross />
            </IconButton>
          </SentimentSurface>,
        ])}
      </div>
    );
  },
  ...withVariantConfig(['default', 'dark', 'bright-green', 'forest-green']),
};

/** Tab through each priority variant and activate with Space. */
export const KeyboardInteraction: Story = {
  render: () => (
    <div style={{ display: 'flex', gap: '12px', padding: '16px' }}>
      <IconButton size={48} aria-label="Primary" priority="primary" type="default" onClick={fn()}>
        <Plus />
      </IconButton>
      <IconButton
        size={48}
        aria-label="Secondary"
        priority="secondary"
        type="default"
        onClick={fn()}
      >
        <Settings />
      </IconButton>
      <IconButton size={48} aria-label="Tertiary" priority="tertiary" type="default" onClick={fn()}>
        <Star />
      </IconButton>
      <IconButton size={48} aria-label="Minimal" priority="minimal" type="default" onClick={fn()}>
        <Travel />
      </IconButton>
      <IconButton
        size={48}
        aria-label="Disabled"
        priority="primary"
        type="default"
        disabled
        onClick={fn()}
      >
        <Menu />
      </IconButton>
    </div>
  ),
  play: async ({ canvasElement, step }) => {
    const canvas = within(canvasElement);
    const buttons = canvas.getAllByRole('button');

    await step('tab to Primary 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 Secondary 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 Tertiary and press Space', async () => {
      await userEvent.tab();
      await expect(buttons[2]).toHaveFocus();
      await wait(400);
      await userEvent.keyboard(' ');
    });

    await wait(400);

    await step('tab to Minimal and press Space', async () => {
      await userEvent.tab();
      await expect(buttons[3]).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
      await expect(buttons[4]).not.toHaveFocus();
    });
  },
};

/** IconButton at 400% zoom for accessibility testing. */
export const Zoom400: Story = {
  render: () => (
    <div style={{ display: 'flex', gap: '8px', padding: '16px', flexWrap: 'wrap' }}>
      <IconButton size={40} aria-label="Primary" priority="primary" type="default" onClick={fn()}>
        <Plus />
      </IconButton>
      <IconButton
        size={40}
        aria-label="Secondary"
        priority="secondary"
        type="default"
        onClick={fn()}
      >
        <Settings />
      </IconButton>
      <IconButton size={40} aria-label="Tertiary" priority="tertiary" type="default" onClick={fn()}>
        <Star />
      </IconButton>
      <IconButton size={40} aria-label="Minimal" priority="minimal" type="default" onClick={fn()}>
        <Travel />
      </IconButton>
      <IconButton
        size={40}
        aria-label="Disabled"
        disabled
        priority="primary"
        type="default"
        onClick={fn()}
      >
        <Menu />
      </IconButton>
    </div>
  ),
  ...withVariantConfig(['400%']),
};
