import { action } from 'storybook/actions';
import { Meta, StoryObj } from '@storybook/react-webpack5';
import { expect, userEvent, within } from 'storybook/test';
import { ScreenMode, ThemeProvider } from '@wise/components-theming';
import { useState } from 'react';
import { Button, Modal, ModalProps } from '..';
import { CommonProps, Scroll } from '../common';
import { lorem10, lorem100, lorem1000 } from '../test-utils';
import { withVariantConfig } from '../../.storybook/helpers';

const meta: Meta<typeof Modal> = {
  component: Modal,
  tags: ['!autodocs', '!manifest'],
  title: 'Dialogs/Modal/Tests',
  args: {
    size: 'md',
    position: 'center',
    open: false,
  },
  parameters: {
    chromatic: {
      delay: 2000,
    },
  },
};
export default meta;

type Story = StoryObj<typeof Modal>;

export interface StoryContentProps {
  args: CommonProps & ModalProps;
  screenMode?: ScreenMode;
  viewMode?: string;
}

const StoryContent = ({ args, screenMode, viewMode }: StoryContentProps) => {
  const [open, setOpen] = useState(viewMode !== 'docs');

  return (
    <>
      <Button v2 onClick={() => setOpen(true)}>
        Open Modal
      </Button>
      <Modal
        {...args}
        body={
          !screenMode ? (
            args.body
          ) : (
            <ThemeProvider theme="personal" screenMode={screenMode}>
              {lorem100}
            </ThemeProvider>
          )
        }
        open={open}
        disableDimmerClickToClose={args.disableDimmerClickToClose}
        onClose={() => {
          setOpen(false);
          action('Modal closed')();
        }}
      />
    </>
  );
};

export const BasicMobile: Story = {
  args: {
    title: 'Title',
    body: lorem10,
    scroll: Scroll.VIEWPORT,
    footer: (
      <Button v2 block>
        Action
      </Button>
    ),
  },
  render: (args, context) => <StoryContent args={args} viewMode={context.viewMode} />,
  ...withVariantConfig(['mobile']),
};

export const ContentScrollMobile: Story = {
  args: {
    title: lorem10,
    body: lorem1000,
    scroll: Scroll.CONTENT,
  },
  render: (args, context) => <StoryContent args={args} viewMode={context.viewMode} />,
  ...withVariantConfig(['mobile']),
};

export const ViewportScrollMobile: Story = {
  args: {
    title: lorem10,
    body: lorem1000,
    scroll: Scroll.VIEWPORT,
  },
  render: (args, context) => <StoryContent args={args} viewMode={context.viewMode} />,
  ...withVariantConfig(['mobile']),
};

export const WithoutTitleMobile: Story = {
  args: {
    body: lorem1000,
    scroll: Scroll.CONTENT,
  },
  render: (args, context) => <StoryContent args={args} viewMode={context.viewMode} />,
  ...withVariantConfig(['mobile']),
};

export const WithThemeProviderInContentMobile: Story = {
  args: {
    title: lorem10,
    body: lorem100,
    scroll: Scroll.VIEWPORT,
    footer: (
      <Button v2 block>
        Action
      </Button>
    ),
  },
  render: (args, { globals: { screenMode }, viewMode }) => (
    // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
    <StoryContent args={args} screenMode={screenMode} viewMode={viewMode} />
  ),
  ...withVariantConfig(['mobile']),
};

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

/**
 * This test insures that there's no unintended page scroll after the modal
 * is closed without selecting an option (e.g. clicking outside).
 */
export const NoScrollAfterClose: Story = {
  args: {
    title: 'Modal Title',
    body: lorem100,
    scroll: Scroll.VIEWPORT,
  },
  render: function Render(args) {
    const [open, setOpen] = useState(false);

    return (
      <div>
        <style>
          {`
            .storybook-container{
              min-height: unset;
              height: unset;
            }
          `}
        </style>
        <p style={{ height: '70vh', background: 'blanchedalmond' }} />

        <Button v2 onClick={() => setOpen(true)}>
          Open Modal
        </Button>
        <Modal {...args} open={open} onClose={() => setOpen(false)} />

        <p style={{ margin: '1rem 0', height: '150vh', background: 'blanchedalmond' }} />
      </div>
    );
  },
  play: async ({ canvasElement, step }) => {
    const canvas = within(canvasElement);
    const trigger = canvas.getByRole('button', { name: /Open Modal/i });

    await step('Open the modal', async () => {
      await userEvent.click(trigger);
      await wait();
    });

    await step('Close the modal with Escape', async () => {
      await userEvent.keyboard('{Escape}');
      await wait();
    });

    await step('Verify the page has not scrolled', async () => {
      const scrollParent = canvasElement.ownerDocument.documentElement;
      await expect(scrollParent.scrollTop).toBe(0);
    });
  },
};
