import { Title, Subtitle, Description, Stories } from '@storybook/addon-docs/blocks';
import { Meta, StoryObj } from '@storybook/react-webpack5';
import { MultiCurrency, Plus } from '@transferwise/icons';
import { lorem10, lorem5 } from '../../test-utils';
import List from '../../list';
import Link from '../../link';
import { ListItem, type ListItemProps } from '../ListItem';
import type { ListItemPromptProps } from '../Prompt';
import { disableControls, withoutKey } from './helpers';
import {
  SB_LIST_ITEM_TEXT as TEXT,
  SB_LIST_ITEM_ADDITIONAL_INFO as INFO,
  SB_LIST_ITEM_CONTROLS as CONTROLS,
  SB_LIST_ITEM_MEDIA as MEDIA,
} from './subcomponents';

const hideControls = disableControls([
  'title',
  'subtitle',
  'valueTitle',
  'valueSubtitle',
  'media',
  'additionalInfo',
  'prompt',
  'control',
  'as',
  'inverted',
  'className',
  'id',
  'valueColumnWidth',
]);

const renderPrompt = (sentiment: ListItemPromptProps['sentiment']) => (
  <ListItem.Prompt sentiment={sentiment}>
    This prompt contains an <Link href="#target">external link</Link> too.
  </ListItem.Prompt>
);
const disabledPromptMessage = (
  <>
    This item is disabled because <Link href="#target">some reason</Link> has not been satisfied.
  </>
);

/**
 * Please refer to the [design documentation](https://wise.design/components/list-item#accessibility:~:text=-,Disabled%20states,-) for more details
 */
export default {
  component: ListItem,
  title: 'Content/ListItem/Disabled State',
  tags: ['autodocs'],
  decorators: [withoutKey],
  argTypes: hideControls(),
  args: {
    disabled: true,
    subtitle: TEXT.subtitle,
    valueTitle: TEXT.valueTitle,
    valueSubtitle: TEXT.valueSubtitle,
    media: MEDIA.avatarFlag,
  },
  parameters: {
    docs: {
      canvas: {
        sourceState: 'hidden',
      },
      page: () => (
        <>
          <Title>Disabled state</Title>
          <Subtitle />
          <Description />
          <Stories />
        </>
      ),
    },
  },
} satisfies Meta<ListItemProps>;
type Story = StoryObj<ListItemProps>;

/**
 * When dealing with dynamic content, e.g. BFFs or general form submissions, it's a common practice
 * to stop the users from making changes to the inputs while the form is being processed.
 *
 * Because these form states are usually short-lived, and would take at most few seconds to
 * complete, we don't want to introduce any major content changes that could distract
 * the user or, even worse, cause layout shift. That's why, by default, toggling the `disabled`
 * prop will not show any additional visual indicators, apart from the luminosity and opacity
 * changes.
 */
export const ShortLived: Story = {
  name: 'Short-lived: fully interactive',
  args: {
    control: CONTROLS.button,
  },
  argTypes: hideControls(['disabledPromptMessage']),
  render: function Render(args) {
    return (
      <List>
        <ListItem {...args} title="No prompt" control={CONTROLS.navigation} />
        <ListItem
          {...args}
          title="Neutral prompt"
          prompt={renderPrompt('neutral')}
          control={CONTROLS.navigation}
        />
        <ListItem {...args} title="Positive prompt" prompt={renderPrompt('positive')} />
        <ListItem {...args} title="Warning prompt" prompt={renderPrompt('warning')} />
        <ListItem {...args} title="Negative prompt" prompt={renderPrompt('negative')} />
      </List>
    );
  },
};

/**
 * There's a difference between fully and partially interactive ListItems. While setting `disabled`
 * prop on the former applies the visual treatment to the whole item, on the latter ones it only
 * affects the control element (`ListItem.Button` or `ListItem.IconButton`).
 *
 * That way, the inline link or button in the additional info section remains interactive and
 * accessible.
 */
export const ShortLivedPartially: Story = {
  name: 'Short-lived: partially interactive',
  args: {
    additionalInfo: INFO.interactive,
  },
  argTypes: hideControls(['spotlight', 'disabledPromptMessage']),
  render: function Render(args) {
    return (
      <List>
        <ListItem
          {...args}
          title="No prompt and disabled control"
          control={CONTROLS.partialButton}
        />
        <ListItem
          {...args}
          title="Prompt and disabled Button control"
          prompt={renderPrompt('warning')}
          control={CONTROLS.partialButton}
        />
        <ListItem
          {...args}
          title="Prompt and disabled IconButton control"
          prompt={renderPrompt('positive')}
          control={CONTROLS.partialIconButton}
        />
      </List>
    );
  },
};

/**
 * On the other hand, instances of ListItems that are disabled for longer periods of time and
 * remain in such state until some user interaction or event occur, can and should offer extended
 * affordances to the user, so they are aware of the current state of the item and the reason why
 * it's not available to them.
 *
 * To achieve that, we're introducing additional prop `disabledPromptMessage` – it's a
 * prompt content override only used when ListItem is in the disabled state, and it's expected to
 * offer reasoning for why given list item has been disabled.
 *
 * If set, it will render a variant of the `ListItem.Prompt` component with an icon and colour
 * scheme designed specifically for this scenario.
 *
 * Similarly to the short-lived scenario, fully interactive items will apply the visual treatment
 * to the whole item. Prompts will remain interactive.
 */
export const LongLived: Story = {
  name: 'Long-lived: fully interactive',
  args: {
    disabledPromptMessage,
    control: CONTROLS.button,
  },
  argTypes: hideControls(['disabledPromptMessage']),
  render: function Render(args) {
    return (
      <List>
        <ListItem
          {...args}
          title="No prompt, no disabledPromptMessage"
          disabledPromptMessage={undefined}
          control={CONTROLS.navigation}
        />
        <ListItem
          {...args}
          title="No prompt, disabledPromptMessage set"
          control={CONTROLS.navigation}
        />
        <ListItem
          {...args}
          title="Neutral prompt, disabledPromptMessage set"
          prompt={renderPrompt('neutral')}
          control={CONTROLS.navigation}
        />
        <ListItem
          {...args}
          title="Positive prompt, disabledPromptMessage set"
          prompt={renderPrompt('positive')}
        />
        <ListItem
          {...args}
          title="Warning prompt, disabledPromptMessage set"
          prompt={renderPrompt('warning')}
        />
        <ListItem
          {...args}
          title="Negative prompt, disabledPromptMessage set"
          prompt={renderPrompt('negative')}
        />
      </List>
    );
  },
};

/**
 * Similarly to the short-lived scenario, partially interactive items will only apply the visual
 * treatment to the control element, leaving the additional info section fully interactive and
 * accessible.
 *
 * While programmatically not required, you will be expected to use the `disabledPromptMessage`
 * prop to offer an explanation to the user on why the item was disabled.
 */
export const LongLivedPartially: Story = {
  name: 'Long-lived: partially interactive',
  args: {
    disabledPromptMessage,
    additionalInfo: INFO.interactive,
  },
  argTypes: hideControls(['spotlight', 'disabledPromptMessage']),
  render: function Render(args) {
    return (
      <List>
        <ListItem
          {...args}
          disabledPromptMessage={undefined}
          title="No prompt, no disabledPromptMessage"
          control={CONTROLS.partialButton}
        />
        <ListItem
          {...args}
          title="No prompt, disabledPromptMessage set"
          control={CONTROLS.partialButton}
        />
        <ListItem
          {...args}
          title="Prompt set, disabledPromptMessage set"
          prompt={renderPrompt('warning')}
          control={CONTROLS.partialIconButton}
        />
        <ListItem
          {...args}
          title="Prompt set, disabledPromptMessage set"
          prompt={renderPrompt('positive')}
          control={CONTROLS.partialIconButton}
        />
      </List>
    );
  },
};

export const AllControls: Story = {
  parameters: {
    docs: {
      canvas: {
        sourceState: 'hidden',
      },
    },
    controls: { disable: true },
    knobs: { disable: true },
  },
  render: (args) => (
    <List>
      <ListItem
        disabled
        media={
          <ListItem.AvatarView>
            <MultiCurrency />
          </ListItem.AvatarView>
        }
        title="Navigation"
        subtitle={lorem5}
        control={<ListItem.Navigation onClick={() => {}} />}
      />
      <ListItem
        disabled
        media={
          <ListItem.AvatarView>
            <MultiCurrency />
          </ListItem.AvatarView>
        }
        title="Button primary"
        subtitle={lorem5}
        control={<ListItem.Button priority="primary">Primary</ListItem.Button>}
      />
      <ListItem
        disabled
        media={
          <ListItem.AvatarView>
            <MultiCurrency />
          </ListItem.AvatarView>
        }
        title="Button secondary neutral"
        subtitle={lorem5}
        control={<ListItem.Button>Secondary</ListItem.Button>}
      />
      <ListItem
        disabled
        media={
          <ListItem.AvatarView>
            <MultiCurrency />
          </ListItem.AvatarView>
        }
        title="Button secondary neutral"
        subtitle={lorem5}
        control={<ListItem.Button priority="secondary-neutral">Secondary Neutral</ListItem.Button>}
      />
      <ListItem
        disabled
        media={
          <ListItem.AvatarView>
            <MultiCurrency />
          </ListItem.AvatarView>
        }
        title="Button tertiary"
        subtitle={lorem5}
        control={<ListItem.Button priority="tertiary">Tertiary</ListItem.Button>}
      />
      <ListItem
        disabled
        media={
          <ListItem.AvatarView>
            <MultiCurrency />
          </ListItem.AvatarView>
        }
        title="Icon Button"
        subtitle={lorem5}
        control={
          <ListItem.IconButton>
            <Plus />
          </ListItem.IconButton>
        }
      />
      <ListItem
        disabled
        media={
          <ListItem.AvatarView>
            <MultiCurrency />
          </ListItem.AvatarView>
        }
        title="Checkbox"
        subtitle={lorem5}
        control={<ListItem.Checkbox />}
      />
      <ListItem
        disabled
        media={
          <ListItem.AvatarView>
            <MultiCurrency />
          </ListItem.AvatarView>
        }
        title="Checkbox checked"
        subtitle={lorem5}
        control={<ListItem.Checkbox checked />}
      />
      <ListItem
        disabled
        media={
          <ListItem.AvatarView>
            <MultiCurrency />
          </ListItem.AvatarView>
        }
        title="Checkbox indeterminate"
        subtitle={lorem5}
        control={<ListItem.Checkbox indeterminate />}
      />
      <ListItem
        disabled
        media={
          <ListItem.AvatarView>
            <MultiCurrency />
          </ListItem.AvatarView>
        }
        title="Switch on"
        subtitle={lorem5}
        control={<ListItem.Switch checked onClick={() => {}} />}
      />
      <ListItem
        disabled
        media={
          <ListItem.AvatarView>
            <MultiCurrency />
          </ListItem.AvatarView>
        }
        title="Switch off"
        subtitle={lorem5}
        control={<ListItem.Switch onClick={() => {}} />}
      />
      <ListItem
        disabled
        media={
          <ListItem.AvatarView>
            <MultiCurrency />
          </ListItem.AvatarView>
        }
        title="Switch off"
        subtitle={lorem5}
        control={<ListItem.Radio name="radio" checked />}
      />
      <ListItem
        disabled
        media={
          <ListItem.AvatarView>
            <MultiCurrency />
          </ListItem.AvatarView>
        }
        title="Switch off"
        subtitle={lorem5}
        control={<ListItem.Radio name="radios" />}
      />
      <ListItem
        disabled
        media={
          <ListItem.AvatarView>
            <MultiCurrency />
          </ListItem.AvatarView>
        }
        title="Non-interactive"
        subtitle={lorem10}
        additionalInfo={
          <ListItem.AdditionalInfo>
            Which has <b>bold,</b> <strong>strong,</strong> <em>emphasis</em>
          </ListItem.AdditionalInfo>
        }
      />
    </List>
  ),
};
