import { Fragment } from 'react';
import { Meta, StoryObj } from '@storybook/react-webpack5';
import List from '../../list';
import { ListItem, type ListItemProps } from '../ListItem';
import { lorem10, lorem20, lorem5 } from '../../test-utils';
import portraitImage from '../../test-utils/assets/placeholder-landscape.svg';
import landscapeImage from '../../test-utils/assets/placeholder-portrait.svg';
import { SB_LIST_ITEM_CONTROLS as CONTROLS, SB_LIST_ITEM_MEDIA as MEDIA } from './subcomponents';
import { ListItemMediaSize } from '../ListItemContext';
import { withSizedContainer } from './helpers';
import { LISTITEM_CQ } from '../constants';

export default {
  title: 'Content/ListItem/Tests/layout',
  tags: ['!autodocs', '!manifest'],
  parameters: {
    controls: { disable: true },
    actions: { disable: true },
    a11y: { disable: true },
    knobs: { disable: true },
  },
} satisfies Meta<ListItemProps>;
type Story = StoryObj<ListItemProps>;

export const LongButton: Story = {
  render: () => (
    <ListItem
      title="Additional info button better align left"
      additionalInfo={
        <ListItem.AdditionalInfo
          action={{
            label: 'Additional info Additional info Additional info (as button)',
            onClick: () => {},
          }}
        />
      }
      control={
        <ListItem.Button onClick={() => {}}>Click me Click me Click me Click me</ListItem.Button>
      }
    />
  ),
  decorators: [withSizedContainer(400, false)],
};

export const GapsBetweenItems: Story = {
  render: () => {
    const props = {
      title: lorem5,
      subtitle: lorem10,
      media: MEDIA.image,
      control: CONTROLS.switch,
    };
    return (
      <List>
        <ListItem {...props} />
        <ListItem {...props} spotlight="active" />
        <ListItem {...props} spotlight="inactive" />
        <ListItem {...props} />
      </List>
    );
  },
};

type PreviewStoryArgs = ListItemProps & {
  previewImageSize: ListItemMediaSize;
  previewWithLineGuides: boolean;
  previewPrompt: boolean | ListItemProps['prompt'];
};

const previewArgGroup = {
  category: 'Preview options',
  type: {
    summary: undefined,
  },
};

const previewArgTypes = {
  previewImageSize: {
    options: [24, 32, 40, 48, 56, 72],
    control: {
      type: 'inline-radio',
    },
    name: 'Preview with image size',
    table: previewArgGroup,
  },
  previewWithLineGuides: {
    control: {
      type: 'boolean',
    },
    name: 'Preview with line guides',
    table: previewArgGroup,
  },
  previewPrompt: {
    control: {
      type: 'boolean',
    },
    mapping: {
      true: <ListItem.Prompt sentiment="positive">This is a prompt</ListItem.Prompt>,
      false: null,
    },
    name: 'Preview with `prompt`',
    table: previewArgGroup,
  },
} as const;

const getPropsForPreview = (args: PreviewStoryArgs) => {
  const { previewImageSize, previewWithLineGuides, previewPrompt, ...props } = args as {
    previewImageSize: ListItemMediaSize;
    previewWithLineGuides: boolean;
    previewPrompt: boolean | ListItemProps['prompt'];
    title: ListItemProps['title'];
    subtitle: ListItemProps['subtitle'];
    [key: string]: any;
  };

  return [
    {
      ...props,
      prompt: previewPrompt,
    },
    {
      previewImageSize,
      previewWithLineGuides,
    },
  ] as const;
};

// Create a completely untyped story object
export const ImageAlignment: StoryObj<PreviewStoryArgs> = {
  parameters: {
    controls: { disable: false },
  },
  args: {
    title: lorem5,
    subtitle: lorem10,
    previewImageSize: 48,
    previewWithLineGuides: true,
    previewPrompt: false,
  },
  argTypes: previewArgTypes,
  decorators: [
    (Story: any, { args }: { args: PreviewStoryArgs }) => (
      <>
        {args.previewWithLineGuides && (
          <style
            dangerouslySetInnerHTML={{
              __html: `
                .wds-list-item-media-image-wrapper::before{
                  content: '';
                  border: 1px dashed blue;
                  position: absolute;
                  width: ${args.previewImageSize}px;
                  height: ${args.previewImageSize}px;
                }
                .wds-list-item-media-image-wrapper::after {
                  content: '';
                  border: 1px dashed red;
                  position: absolute;
                  left: 0;
                  width: 100%;
                  height: ${args.previewImageSize}px;
                }
              `,
            }}
          />
        )}
        <List
          className="list-unstyled"
          style={{
            display: 'grid',
            gridTemplateColumns: [LISTITEM_CQ.MAX, LISTITEM_CQ.MAX + 10]
              .map((size) => `${size}px`)
              .join(' '),
            gap: '16px',
          }}
        >
          <Story />
        </List>
      </>
    ),
  ],
  render: (args: PreviewStoryArgs) => {
    const [{ title, subtitle, ...props }, previewProps] = getPropsForPreview(args);

    const additionalInfo = <ListItem.AdditionalInfo>{lorem20}</ListItem.AdditionalInfo>;
    const control = CONTROLS.button;
    const size = previewProps.previewImageSize;

    const instances = [
      { title, ...props },
      { title, subtitle, ...props },
      { title, subtitle, additionalInfo, ...props },
      { title, control, ...props },
      { title, subtitle, control, ...props },
      { title, subtitle, additionalInfo, control, ...props },
    ] as const;

    return (
      <>
        {instances.map((itemProps, index) => (
          <Fragment key={`landscape-${index}`}>
            <ListItem
              {...itemProps}
              media={<ListItem.Image size={size} src={landscapeImage} alt="landscape image" />}
            />
            <ListItem
              {...itemProps}
              media={<ListItem.Image size={size} src={landscapeImage} alt="landscape image" />}
            />
          </Fragment>
        ))}
        {instances.map((itemProps, index) => (
          <Fragment key={`portrait-${index}`}>
            <ListItem
              {...itemProps}
              media={<ListItem.Image size={size} src={portraitImage} alt="portrait image" />}
            />
            <ListItem
              {...itemProps}
              media={<ListItem.Image size={size} src={portraitImage} alt="portrait image" />}
            />
          </Fragment>
        ))}
      </>
    );
  },
};

// Our container queries left 1px gap between breakpoint definitions.
// This test makes sure that LI placed in a parent of {width} still
// works fine, where: {breakpoint} < {width} < {breakpoint} + 1px
export const SubPixelWidths: StoryObj<PreviewStoryArgs> = {
  parameters: {
    controls: { disable: false },
  },
  args: {
    title: lorem5,
    subtitle: lorem10,
    previewImageSize: 48,
    previewWithLineGuides: true,
    previewPrompt: false,
  },
  argTypes: previewArgTypes,
  render: (args: PreviewStoryArgs) => {
    const [props] = getPropsForPreview(args);

    return (
      <>
        <List
          style={{
            display: 'grid',
            gridTemplateColumns: '1fr 1fr',
            width: `${2 * LISTITEM_CQ.MIN + 1}px`,
          }}
        >
          <ListItem
            {...props}
            title={`This list item is ${LISTITEM_CQ.MIN + 0.5}px wide`}
            subtitle="this translates to '@wds-list-item-cq-min + 0.5px'"
            media={<ListItem.Image src={portraitImage} alt="portrait image" />}
          />
          <li />
        </List>
        <List
          style={{
            display: 'grid',
            gridTemplateColumns: '1fr 1fr',
            width: `${2 * LISTITEM_CQ.MAX + 1}px`,
          }}
        >
          <ListItem
            {...props}
            title={`This list item is ${LISTITEM_CQ.MAX + 0.5}px wide`}
            subtitle="this translates to '@wds-list-item-cq-max + 0.5px'"
            media={<ListItem.Image src={portraitImage} alt="portrait image" />}
          />
          <li />
        </List>
      </>
    );
  },
};
