import type { Meta, StoryObj } from '@storybook/react';
import clsx from 'clsx';
import React, { useMemo } from 'react';
import { twMerge } from 'tailwind-merge';

import { MoreVerticalIcon } from '@/icons';
import { formatRatioAsPercent } from '@/utils/utils';

import {
  HorizontalSplitGroup,
  SplitPanel,
  VerticalSplitGroup,
} from './SplitPanel';

type PagePropsAndCustomArgs = {
  className?: string;
  barClassName?: string;
  panelClassName?: string;
  numPanels?: number;
};

const meta: Meta<PagePropsAndCustomArgs> = {
  title: 'components/SplitPanel',
  argTypes: {
    className: {
      control: { type: 'text' },
    },
    barClassName: {
      control: { type: 'text' },
    },
    panelClassName: {
      control: { type: 'text' },
    },
    numPanels: {
      control: { type: 'number', min: 2 },
    },
  },
};

export default meta;
type Story = StoryObj<PagePropsAndCustomArgs>;

const LOREM_IPSUM = [
  'Sint molestiae ipsam cupiditate occaecati animi nam eum. Officia consectetur numquam corrupti. Iure expedita et modi dolore ea et rerum quia. Et nihil cumque itaque saepe quia ex quia nobis.',
  'Qui ducimus est nihil sit ullam accusantium. Aliquid qui inventore labore et dolorum nam iusto. Nemo cum porro et non repellendus sint perspiciatis inventore. At aut saepe sed ad id velit nihil et. Quia aut aspernatur eaque eius eveniet assumenda. Deserunt id similique natus.',
  'Natus asperiores enim saepe mollitia nihil occaecati. Labore ex ea magnam consequuntur qui saepe officiis sunt. Quos quia eligendi iure. Officia nobis magni debitis doloribus. Accusantium omnis et odio ad.',
  'Voluptatem at ducimus totam nisi. Veritatis repudiandae officia nemo. Eum ea dolore magnam iure eveniet.',
  'Et ullam quas repellat quo deleniti optio. Ea impedit possimus qui voluptatibus qui deleniti minus. Sed rerum sed maxime delectus temporibus iste.',
];

function generateLoremIpsum(numParagraphs = 1 + Math.floor(Math.random() * 5)) {
  return new Array(numParagraphs)
    .fill('')
    .map(() => LOREM_IPSUM[Math.floor(Math.random() * LOREM_IPSUM.length)]);
}

const ContainerSizeMeter: React.FC<React.HTMLAttributes<HTMLDivElement>> = (
  props
) => (
  <div {...props} className={twMerge('flex flex-row gap-2', props.className)}>
    <span
      className='hidden h-2 w-2 rounded-full bg-current @sm:inline'
      title='sm'
    />
    <span
      className='hidden h-2 w-2 rounded-full bg-current @md:inline'
      title='md'
    />
    <span
      className='hidden h-2 w-2 rounded-full bg-current @lg:inline'
      title='lg'
    />
    <span
      className='hidden h-2 w-2 rounded-full bg-current @xl:inline'
      title='xl'
    />
    <span
      className='hidden h-2 w-2 rounded-full bg-current @2xl:inline'
      title='2xl'
    />
    <span
      className='hidden h-2 w-2 rounded-full bg-current @3xl:inline'
      title='3xl'
    />
    <span
      className='hidden h-2 w-2 rounded-full bg-current @4xl:inline'
      title='4xl'
    />
    <span
      className='hidden h-2 w-2 rounded-full bg-current @5xl:inline'
      title='5xl'
    />
    <span
      className='hidden h-2 w-2 rounded-full bg-current @6xl:inline'
      title='6xl'
    />
    <span
      className='hidden h-2 w-2 rounded-full bg-current @7xl:inline'
      title='7xl'
    />
  </div>
);

const LoremIpsum: React.FC<{ numParagraphs?: number }> = (props) => {
  const paragraphs = useMemo(
    () => generateLoremIpsum(props.numParagraphs),
    [props.numParagraphs]
  );
  return paragraphs.map((paragraph, i) => <p key={i}>{paragraph}</p>);
};

export const VerticalSplit: Story = {
  render: (args) => {
    const {
      numPanels = 2,
      className,
      barClassName,
      panelClassName,
      ...restProps
    } = args;
    const primaryPanel = Math.ceil(numPanels / 2) - 1;
    return (
      <VerticalSplitGroup
        {...restProps}
        className={twMerge('@container', className)}
        barClassName={barClassName}
      >
        {new Array(numPanels).fill(10).map((numParagraphs, i) => (
          <SplitPanel
            className={clsx({ 'flex-1': i === primaryPanel }, panelClassName)}
            style={{ width: formatRatioAsPercent(1, numPanels) }}
            key={i}
          >
            <div className='p-4'>
              <ContainerSizeMeter className='mb-2 h-4' />
              <LoremIpsum numParagraphs={numParagraphs} />
            </div>
          </SplitPanel>
        ))}
      </VerticalSplitGroup>
    );
  },
  args: {
    className: 'fixed inset-0 absolute w-full h-full',
    barClassName: '',
    panelClassName: '',
    numPanels: 2,
  },
};

export const HorizontalSplit: Story = {
  render: (args) => {
    const {
      numPanels = 2,
      className,
      barClassName,
      panelClassName,
      ...restProps
    } = args;
    const primaryPanel = Math.ceil(numPanels / 2) - 1;
    return (
      <HorizontalSplitGroup
        {...restProps}
        className={twMerge('@container', className)}
        barClassName={barClassName}
      >
        {new Array(numPanels).fill(10).map((numParagraphs, i) => (
          <SplitPanel
            className={clsx({ 'flex-1': i === primaryPanel }, panelClassName)}
            style={{ height: formatRatioAsPercent(1, numPanels) }}
            key={i}
          >
            <div className='p-4'>
              <LoremIpsum numParagraphs={numParagraphs} />
            </div>
          </SplitPanel>
        ))}
      </HorizontalSplitGroup>
    );
  },
  args: {
    className: 'fixed inset-0 w-full h-full',
    barClassName: '',
    panelClassName: '',
    numPanels: 2,
  },
};

export const CustomizedBar: Story = {
  render: (args) => {
    const { numPanels = 2, className, panelClassName, ...restProps } = args;
    const primaryPanel = Math.ceil(numPanels / 2) - 1;
    return (
      <VerticalSplitGroup
        {...restProps}
        className={twMerge('@container', className)}
        barClassName='flex justify-center items-center opacity-100 bg-white text-accent-pink'
        barChildren={<MoreVerticalIcon className='text-inherit' />}
      >
        {new Array(numPanels).fill(10).map((numParagraphs, i) => (
          <SplitPanel
            className={clsx({ 'flex-1': i === primaryPanel }, panelClassName)}
            style={{ width: formatRatioAsPercent(1, numPanels) }}
            key={i}
          >
            <div className='p-4'>
              <ContainerSizeMeter className='mb-2 h-4' />
              <LoremIpsum numParagraphs={numParagraphs} />
            </div>
          </SplitPanel>
        ))}
      </VerticalSplitGroup>
    );
  },
  args: {
    className: 'fixed inset-0 absolute w-full h-full',
    panelClassName: '',
    numPanels: 2,
  },
  argTypes: {
    barClassName: { table: { disable: true } },
  },
};
