import { useState } from 'react';
import { userEvent, within, expect } from '@storybook/test';
import { Meta, StoryObj } from '@storybook/react';
import PrimitiveAnchor from '../src';

const meta = {
  title: 'Primitives/Anchor/Tests',
  component: PrimitiveAnchor,
  args: {
    children: 'Click me',
    href: 'https://example.com',
  },
} satisfies Meta<typeof PrimitiveAnchor>;

export default meta;

type Story = StoryObj<typeof meta>;

const wait = async (duration = 500) =>
  new Promise<void>((resolve) => {
    setTimeout(resolve, duration);
  });

export const ClickInteraction: Story = {
  play: async ({ canvasElement }) => {
    const canvas = within(canvasElement);
    const link = canvas.getByRole('link');
    await userEvent.click(link);
    await expect(link).toHaveTextContent('Clicked!');
  },
  render: function Render(args) {
    const [clicked, setClicked] = useState(false);

    return (
      <PrimitiveAnchor
        {...args}
        onClick={(event) => {
          event.preventDefault();
          setClicked(true);
        }}
      >
        {clicked ? 'Clicked!' : 'Click me'}
      </PrimitiveAnchor>
    );
  },
};

export const FocusInteraction: Story = {
  play: async ({ canvasElement }) => {
    const canvas = within(canvasElement);
    const link = canvas.getByRole('link');
    await userEvent.tab();
    await expect(link).toHaveFocus();
    await expect(link).toHaveTextContent('Focused!');
  },
  render: function Render(args) {
    const [focused, setFocused] = useState(false);

    return (
      <PrimitiveAnchor {...args} onFocus={() => setFocused(true)}>
        {focused ? 'Focused!' : 'Click me'}
      </PrimitiveAnchor>
    );
  },
};

export const BlurInteraction: Story = {
  play: async ({ canvasElement }) => {
    const canvas = within(canvasElement);
    const link = canvas.getByRole('link');
    await userEvent.tab();
    await expect(link).toHaveFocus();
    await userEvent.tab();
    await expect(link).not.toHaveFocus();
    await expect(link).toHaveTextContent('Blurred!');
  },
  render: function Render(args) {
    const [blurred, setBlurred] = useState(false);

    return (
      <PrimitiveAnchor {...args} onBlur={() => setBlurred(true)}>
        {blurred ? 'Blurred!' : 'Click me'}
      </PrimitiveAnchor>
    );
  },
};

export const MouseEnterInteraction: Story = {
  play: async ({ canvasElement }) => {
    const canvas = within(canvasElement);
    const link = canvas.getByRole('link');
    await expect(link).toHaveTextContent('Click me');
    await userEvent.hover(link);
    await expect(link).toHaveTextContent('Hovered!');
  },
  render: function Render(args) {
    const [hovered, setHovered] = useState(false);

    return (
      <PrimitiveAnchor {...args} onMouseEnter={() => setHovered(true)}>
        {hovered ? 'Hovered!' : 'Click me'}
      </PrimitiveAnchor>
    );
  },
};

export const MouseLeaveInteraction: Story = {
  play: async ({ canvasElement }) => {
    const canvas = within(canvasElement);
    const link = canvas.getByRole('link');
    await expect(link).toHaveTextContent('Click me');
    await userEvent.unhover(link);
    await expect(link).toHaveTextContent('Left!');
  },
  render: function Render(args) {
    const [left, setLeft] = useState(false);

    return (
      <PrimitiveAnchor {...args} onMouseLeave={() => setLeft(true)}>
        {left ? 'Left!' : 'Click me'}
      </PrimitiveAnchor>
    );
  },
};

export const KeyDownInteraction: Story = {
  play: async ({ canvasElement }) => {
    const canvas = within(canvasElement);
    const link = canvas.getByRole('link');
    await expect(link).toHaveTextContent('Click me');
    await userEvent.tab();
    await wait();
    await userEvent.keyboard('{ArrowDown}');
    await expect(link).toHaveTextContent('Key Pressed!');
  },
  render: function Render(args) {
    const [keyPressed, setKeyPressed] = useState(false);

    return (
      <PrimitiveAnchor
        {...args}
        onKeyDown={(event) => {
          if (event.key === 'ArrowDown') {
            event.preventDefault();
            setKeyPressed(true);
          }
        }}
      >
        {keyPressed ? 'Key Pressed!' : 'Click me'}
      </PrimitiveAnchor>
    );
  },
};

export const TabIndexBehavior: Story = {
  play: async ({ canvasElement }) => {
    const canvas = within(canvasElement);
    const link = canvas.getByRole('link');
    await userEvent.tab();
    await expect(link).not.toHaveFocus();
  },
  render: function Render(args) {
    return (
      <PrimitiveAnchor {...args} disabled tabIndex={-1}>
        Click me
      </PrimitiveAnchor>
    );
  },
};
