/* eslint-disable react-hooks/rules-of-hooks */
import { faker } from '@faker-js/faker';
import { useArgs } from '@storybook/preview-api';
import { Meta, StoryObj } from '@storybook/react';
import React, { useMemo } from 'react';
import { TabsProps } from 'react-tabs';
import { Tab, TabList, TabPanel, Tabs } from '.';
import { createGroups } from '../../helpers/storybook';

const groups = createGroups({
  Storybook: ['amount', 'disabled'],
});

type TabsStoryComponentProps = React.FC<
  typeof Tabs & {
    amount: number;
    selectedIndex?: number;
    disabled?: boolean;
  }
>;

/**
 * This component can be used to structure the elements of a `FormStation`.
 *
 * When designing a station using this component, please consider the following guidelines:
 * - **Contextual Relevance**: Only group contextually related content within tabs.
 *   Use separate stations for unrelated information.
 * - **Information Placement**: Prioritize essential information in the first tab for immediate user access.
 *   Arrange content to avoid the need for simultaneous multi-tab viewing.
 * - **Saving Mechanism**: Understand that all tabs share a single saving action.
 *   This makes it hard for users to understand why a save operation was not successful
 *   if e.g. a validation error on an inactive tab occurs. Plan workflows carefully and
 *   prevent complex workflows across multiple tabs.
 */
const meta: Meta<TabsStoryComponentProps> = {
  title: 'Other Components/Tabs',
  component: Tabs,
  argTypes: {
    ...groups,
    amount: {
      ...groups.amount,
      description: '<b>[Storybook only]</b> The amount of tabs to render.',
      type: 'number',
      control: { type: 'number', min: 0, max: 30 },
    },
    disabled: {
      ...groups.disabled,
      description: '<b>[Storybook only]</b> Disable the tabs.',
      type: 'boolean',
    },
    children: {
      table: {
        disable: true,
      },
    },
  },
  args: {
    amount: 3,
  },
};

const generateItems = (
  count: number,
  disabled?: boolean,
): [JSX.Element[], JSX.Element[]] => {
  const tabs: JSX.Element[] = [];
  const panels: JSX.Element[] = [];

  for (let i = 0; i < count; i++) {
    const title = faker.random.words(faker.datatype.number({ min: 1, max: 3 }));
    tabs.push(
      <Tab key={i} disabled={disabled}>
        {title}
      </Tab>,
    );
    panels.push(
      <TabPanel key={i}>
        <h2>{title}</h2>
        <p>{faker.lorem.paragraph(20)}</p>
      </TabPanel>,
    );
  }

  return [tabs, panels];
};

export default meta;

export const Default: StoryObj<TabsStoryComponentProps> = {
  render: (props) => {
    const [tabs, panels] = generateItems(props.amount, props.disabled);

    return (
      <Tabs>
        <TabList>{tabs}</TabList>
        {panels}
      </Tabs>
    );
  },
};

export const Controlled: StoryObj<TabsStoryComponentProps> = {
  argTypes: {
    ...meta.argTypes,
    selectedIndex: {
      ...groups.amount,
      description: '<b>[Storybook only]</b> Index of the selected Tab.',
      type: 'number',
      control: { type: 'number', min: 0, max: 30 },
    },
  },
  args: {
    ...meta.args,
    selectedIndex: 0,
  },
  render: (props) => {
    const [tabs, panels] = useMemo(
      () => generateItems(props.amount),
      [props.amount],
    );
    const [{ selectedIndex }, updateArgs] = useArgs();

    const onSelect: TabsProps['onSelect'] = (index) => {
      updateArgs({ selectedIndex: index });
    };

    return (
      <Tabs selectedIndex={selectedIndex} onSelect={onSelect}>
        <TabList>{tabs}</TabList>
        {panels}
      </Tabs>
    );
  },
};
