import { userEvent, within } from '@storybook/test';
import { action } from '@storybook/addon-actions';
import { Mobile as MobileIcon, Theme, Switch, Bulb, Info, Coins, Team } from '@transferwise/icons';
import { Snackbar, type SnackbarProps } from './Snackbar';
import { SnackbarConsumer } from './SnackbarContext';
import SnackbarProvider from './SnackbarProvider';
import Button from '../button';
import CheckboxOption from '../checkboxOption';
import { storyConfig } from '../test-utils';
import { wait } from '../test-utils/wait';

export default {
  title: 'Dialogs/Snackbar/Tests',
  component: Snackbar,
  argTypes: {},
};

const launchSnackbar = async (canvasElement: HTMLElement) => {
  await wait(0);
  const canvas = within(canvasElement);
  await userEvent.click(canvas.getByRole('button'));
};

type Args = Partial<SnackbarProps> & {
  extraContext: React.ReactNode;
  timeout: number;
};

const TIMEOUT = 10000000;

const Default = {
  args: {
    timeout: TIMEOUT,
  } as Args,
  play: async ({ canvasElement }: { canvasElement: HTMLElement }) => {
    await launchSnackbar(canvasElement);
  },
  render: (args: Args) => {
    return (
      <SnackbarProvider timeout={args.timeout}>
        <SnackbarConsumer>
          {({ createSnackbar }) => (
            <>
              <Button
                block
                onClick={() => {
                  createSnackbar({
                    action: {
                      label: 'View',
                      onClick: () => action('View button clicked.'),
                    },
                    text: <span>Some text</span>,
                  });
                }}
              >
                Show Snackbar
              </Button>
              {args.extraContext}
            </>
          )}
        </SnackbarConsumer>
      </SnackbarProvider>
    );
  },
};

export const Basic = {
  args: {
    ...Default.args,
    extraContext: (
      <div className="p-t-3">
        <CheckboxOption
          title="In light mode, snackbar has drop shadow"
          content={
            <a
              href="https://transferwise.atlassian.net/browse/DS-4477"
              target="_blank"
              rel="noreferrer"
            >
              Bug DS-4477
            </a>
          }
          media={<Bulb />}
        />
        <CheckboxOption
          title="Font size is 14 px, not 16px"
          content={
            <a
              href="https://transferwise.atlassian.net/browse/DS-3716"
              target="_blank"
              rel="noreferrer"
            >
              Bug DS-3716
            </a>
          }
          media={<Info size="16" />}
        />
      </div>
    ) as React.ReactNode,
  },
  play: Default.play,
  render: Default.render,
};

export const Mobile = storyConfig(
  {
    args: {
      ...Default.args,
      extraContext: (
        <div className="p-t-3">
          <CheckboxOption
            title="In mobile view, snackbar is full-width, not centered"
            media={<MobileIcon />}
          />
        </div>
      ) as React.ReactNode,
    },
    play: Default.play,
    render: Default.render,
  },
  {
    variants: ['mobile'],
  },
);

const switchToDarkMode = async (context: { canvasElement: HTMLElement }) => {
  await Default.play(context);

  // the snackbar is outside the storybook dom so dark mode doesn't apply
  const body = document.querySelector('div.np-theme-personal');
  if (body) {
    body.setAttribute('class', 'np-theme-personal--dark');
  }
  const snackbar = document.querySelector('div.snackbar');
  if (snackbar) {
    snackbar.setAttribute('class', 'snackbar np-theme-personal--dark');
  }
};

export const DarkMode = storyConfig(
  {
    args: {
      ...Default.args,
      extraContext: (
        <div className="p-t-3">
          <CheckboxOption title="In dark mode, snackbar has no drop shadow" media={<Theme />} />
          <CheckboxOption
            title="In dark mode, snackbar is inverted and has light background"
            media={<Theme />}
          />
        </div>
      ) as React.ReactNode,
    },
    play: switchToDarkMode,
    render: Default.render,
  },
  {
    variants: ['dark'],
  },
);

const switchToRTL = async (context: { canvasElement: HTMLElement }) => {
  await Default.play(context);
  // the snackbar is outside the storybook dom so the RTL variant doesn't apply
  const body = document.querySelector('div.storybook-container');
  if (body) {
    body.setAttribute('dir', 'rtl');
  }
  const snackbar = document.querySelector('div.snackbar');
  if (snackbar) {
    snackbar.setAttribute('dir', 'rtl');
  }
};

export const RTL = storyConfig(
  {
    args: {
      ...Default.args,
      extraContext: (
        <div className="p-t-3">
          <CheckboxOption
            title="In RTL, snackbar is not left aligned"
            content={
              <a
                href="https://transferwise.atlassian.net/browse/DS-4642"
                target="_blank"
                rel="noreferrer"
              >
                Bug DS-4642
              </a>
            }
            media={<Switch />}
          />
          <CheckboxOption
            title="In RTL, snackbar has proper padding on left and right of button"
            content={
              <a
                href="https://transferwise.atlassian.net/browse/DS-4643"
                target="_blank"
                rel="noreferrer"
              >
                Bug DS-4643
              </a>
            }
            media={<Switch />}
          />
        </div>
      ) as React.ReactNode,
    },
    play: switchToRTL,
    render: Default.render,
  },
  {
    variants: ['rtl'],
  },
);

export const RTLMobile = storyConfig(
  {
    args: {
      ...RTL.args,
    },
    play: switchToRTL,
    render: Default.render,
  },
  {
    variants: ['rtl', 'mobile'],
  },
);

export const Zoom400 = storyConfig(
  {
    args: {
      ...Default.args,
      extraContext: (
        <div className="p-t-3">
          <CheckboxOption
            content="Snackbar isn't transparent (I'm going to make this text very long so that it will fill up the entire page and go behind the snackbar. This way, when you look at it you will easily be able to tell if the snackbar is transparent and recognize the bug because we don't want it to be transparent. Transparent is bad. When we first did rebrand we had a lot of problems with transparencies. I don't know what happened to them. I don't see them a lot anymore but I also don't remember anybody fixing them.)"
            title={
              <a
                href="https://transferwise.atlassian.net/browse/DS-3716"
                target="_blank"
                rel="noreferrer"
              >
                Bug DS-3716
              </a>
            }
            media={<Coins />}
          />
        </div>
      ),
    },

    play: Default.play,
    render: Default.render,
  },
  {
    variants: ['400%'],
  },
);

export const MultipleClicks = {
  args: {
    ...Default.args,
    extraContext: (
      <div className="p-t-3">
        <CheckboxOption
          title="Snackbar is only shown once even if clicked many times"
          media={<Team />}
        />
      </div>
    ),
  },
  play: async ({ canvasElement }: { canvasElement: HTMLElement }) => {
    const canvas = within(canvasElement);
    for (let i = 0; i < 8; i += 1) {
      await userEvent.click(canvas.getByRole('button'));
    }
  },
  render: Default.render,
};
