import { faker } from '@faker-js/faker';
import { Meta, StoryObj } from '@storybook/react';
import { shuffle } from 'lodash';
import { default as React, ReactNode, useEffect, useState } from 'react';
import { createGroups, generateItemArray } from '../../helpers/storybook';
import { TextButton } from '../Buttons/TextButton/TextButton';
import { Divider } from '../FormElements';
import { List } from '../List';
import { Accordion } from './Accordion';
import { AccordionItem } from './AccordionItem/AccordionItem';

const groups = createGroups({
  Behavior: ['expandedByDefault', 'alignAccordionItem', 'stickyRows'],
  Content: ['header', 'children'],
  Styling: ['className'],
});

const generateItems = (
  startIndex?: number,
  sticky?: boolean,
  children?: JSX.Element,
): JSX.Element[] => {
  return generateItemArray(10, (index) => {
    const key = index + (startIndex ?? 1);
    return (
      <AccordionItem key={key} header={<b>Item {key}</b>} sticky={sticky}>
        {children ?? <p>{faker.lorem.paragraph(20)}</p>}
      </AccordionItem>
    );
  });
};

const meta: Meta<typeof Accordion> = {
  title: 'Other Components/Accordion',
  component: Accordion,
  argTypes: {
    ...groups,
    header: {
      ...groups.header,
      control: 'text',
      defaultValue: 'Header',
    },
    children: {
      ...groups.children,
      mapping: {
        'No items': undefined,
        '10 Items': generateItems(),
      },
      options: ['No items', '10 Items'],
      defaultValue: '10 Items',
      control: 'select',
    },
  },
};
export default meta;

export const Default: StoryObj<typeof Accordion> = {
  render: (args) => <Accordion {...args} header={<b>{args.header}</b>} />,
  args: {
    children: generateItems(),
    header: 'Header' as unknown as JSX.Element,
  },
  name: 'Default',
};

export const NoHeader: StoryObj<typeof Accordion> = {
  args: {
    ...Default.args,
    header: undefined,
  },
  name: 'No header',
};

export const AddingAndShuffling: StoryObj<typeof Accordion> = {
  render: (args) =>
    React.createElement(() => {
      useEffect(() => {
        setItems(args.children as ReactNode[]);
      }, []);

      const [items, setItems] = useState<ReactNode[]>([]);

      return (
        <>
          <div style={{ display: 'grid', marginBottom: '10px' }}>
            <TextButton
              onButtonClicked={() => setItems(shuffle(items))}
              text="Shuffle children"
            />
            <TextButton
              onButtonClicked={() =>
                setItems([...items, ...generateItems(items.length)])
              }
              text="Add more children"
            />
          </div>
          <Divider />
          <Accordion {...args}>{items}</Accordion>
        </>
      );
    }),
  args: {
    ...Default.args,
    expandedByDefault: true,
  },
  name: 'Adding and shuffling',
};

export const NestedSticky: StoryObj<typeof Accordion> = {
  args: {
    ...Default.args,
    children: generateItems(
      1,
      true,
      <div style={{ height: '350px' }}>
        <List
          columns={[
            {
              propertyName: 'id',
              label: 'Id',
              size: '50px',
            },
            {
              propertyName: 'title',
              label: 'Title',
            },
            {
              propertyName: 'desc',
              label: 'Description',
            },
          ]}
          data={generateItemArray(10, (index) => ({
            id: index + 1,
            desc: `Description ${index + 1}: ${faker.lorem.words(
              faker.datatype.number({ min: 10, max: 50 }),
            )}`,
            title: `Item ${index + 1}: ${faker.random.words(
              faker.datatype.number({ min: 1, max: 3 }),
            )}`,
          }))}
        />
      </div>,
    ),
    stickyRows: true,
  },
  name: 'Nested Sticky',
};

export const NoChildren: StoryObj<typeof Accordion> = {
  args: {
    ...Default.args,
    children: undefined,
  },
  name: 'No children',
};
