import type { Meta, StoryObj } from '@storybook/react';
import React, { useEffect, useRef } from 'react';
import { BiBone, BiDroplet, BiFolder, BiSolidEraser } from 'react-icons/bi';
import { BsFullscreen, BsWindow } from 'react-icons/bs';
import { FaGuitar } from 'react-icons/fa';

import * as AllIcons from '@/icons';
import * as AllFigmaIcons from '@/icons/generated';
import * as AllSpinners from '@/icons/spinners';

type PagePropsAndCustomArgs = Pick<
  React.SVGProps<SVGSVGElement>,
  'className'
> & {
  width?: number | 'auto';
  height?: number | 'auto';
  color?: string;
  background?: string;
};

const meta: Meta<PagePropsAndCustomArgs> = {
  title: 'elements/Icons',
  argTypes: {
    className: {
      control: { type: 'text' },
    },
    width: {
      control: { type: 'number', min: 10, max: 100, step: 1 },
      defaultValue: 10,
    },
    height: {
      control: { type: 'number', min: 10, max: 100, step: 1 },
    },
    color: {
      control: { type: 'color' },
    },
    background: {
      control: { type: 'color' },
    },
  },
};

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

// Wrapper to add `title` for the natural dimensions on hover
const IconWrapper: React.FC<React.HTMLAttributes<HTMLDivElement>> = (props) => {
  const ref = useRef<HTMLDivElement>(null);

  useEffect(() => {
    const svg = ref.current?.querySelector('svg');
    if (ref.current && svg) {
      ref.current.setAttribute(
        'title',
        `SVG size: ${svg.getAttribute('width')}x${svg.getAttribute('height')}`
      );
    }
  }, []);

  return <div ref={ref} {...props} />;
};

function isIconComponentEntry(
  entry: [string, unknown]
): entry is [string, React.FC<React.SVGProps<SVGSVGElement>>] {
  return typeof entry[1] === 'function';
}

export const Default: Story = {
  render: (args) => {
    const {
      width = 48,
      height = width,
      color,
      background,
      ...restProps
    } = args;
    const props: React.SVGProps<SVGSVGElement> = {
      style: {
        width: width || 'auto',
        height: height || 'auto',
        color,
        background,
      },
      ...restProps,
    };
    return (
      <div
        className='grid gap-1 p-2'
        style={{
          gridTemplateColumns: width
            ? 'repeat(auto-fill, minmax(100px, 1fr))'
            : '',
        }}
      >
        {Object.entries(AllIcons)
          .filter(isIconComponentEntry)
          .map(([key, Icon]) => (
            <figure
              key={key}
              className='group flex flex-col items-center justify-end rounded-md bg-background-primary p-2 text-foreground-primary'
              title={key}
            >
              <IconWrapper className='group-hover:bg-overlay-on-primary'>
                <Icon {...props} />
              </IconWrapper>
              <figcaption className='mt-1 w-full text-center font-sans text-xs text-ellipsis whitespace-nowrap text-foreground-secondary'>
                {key}
              </figcaption>
            </figure>
          ))}
      </div>
    );
  },
  args: {
    color: '',
  },
};

export const FigmaGenerated: Story = {
  render: (args) => {
    const {
      width = 48,
      height = width,
      color,
      background,
      ...restProps
    } = args;
    const props: React.SVGProps<SVGSVGElement> = {
      style: {
        width: width || 'auto',
        height: height || 'auto',
        color,
        background,
      },
      ...restProps,
    };
    return (
      <div
        className='grid gap-1 p-2'
        style={{
          gridTemplateColumns: width
            ? 'repeat(auto-fill, minmax(100px, 1fr))'
            : '',
        }}
      >
        {Object.entries(AllFigmaIcons)
          .filter(isIconComponentEntry)
          .map(([key, Icon]) => (
            <figure
              key={key}
              className='group flex flex-col items-center justify-end rounded-md bg-background-primary p-2 text-foreground-primary'
              title={key}
            >
              <IconWrapper className='group-hover:bg-overlay-on-primary'>
                <Icon {...props} />
              </IconWrapper>
              <figcaption className='mt-1 w-full text-center font-sans text-xs text-ellipsis whitespace-nowrap text-foreground-secondary'>
                {key}
              </figcaption>
            </figure>
          ))}
      </div>
    );
  },
  args: {
    color: '',
  },
};

export const Spinners: Story = {
  render: (args) => {
    const {
      width = 48,
      height = width,
      color,
      background,
      ...restProps
    } = args;
    const props: React.SVGProps<SVGSVGElement> = {
      style: {
        width: width || 'auto',
        height: height || 'auto',
        color,
        background,
      },
      ...restProps,
    };
    return (
      <div
        className='grid gap-1 p-2'
        style={{
          gridTemplateColumns: width
            ? 'repeat(auto-fill, minmax(100px, 1fr))'
            : '',
        }}
      >
        {Object.entries(AllSpinners)
          .filter(isIconComponentEntry)
          .map(([key, Icon]) => (
            <figure
              key={key}
              className='group flex flex-col items-center justify-end rounded-md bg-background-primary p-2 text-foreground-primary'
              title={key}
            >
              <IconWrapper className='group-hover:bg-overlay-on-primary'>
                <Icon {...props} />
              </IconWrapper>
              <figcaption className='mt-1 w-full text-center font-sans text-xs text-ellipsis whitespace-nowrap text-foreground-secondary'>
                {key}
              </figcaption>
            </figure>
          ))}
      </div>
    );
  },
  args: {
    color: '',
  },
};

/**
 * We ultimately want to remove all of these and delete this forever
 */
export const Stragglers = () => {
  const lineProps = { className: 'flex flex-row items-center gap-2' };
  const iconProps = { className: 'w-8 h-8' };
  return (
    <ul className='flex flex-col gap-2'>
      <li {...lineProps}>
        <div>
          <BiBone {...iconProps} title='react-icons/bi: BiBone' />
        </div>
        <div>Dry (SelectedTrackSidebar.tsx)</div>
      </li>
      <li {...lineProps}>
        <div>
          <BiDroplet {...iconProps} title='react-icons/bi: BiDroplet' />
        </div>
        <div>Wet (SelectedTrackSidebar.tsx)</div>
      </li>
      <li {...lineProps}>
        <div>
          <BiFolder {...iconProps} title='react-icons/bi: BiFolder' />
        </div>
        <div>Download ZIP (MulitrackTimeline.tsx)</div>
      </li>
      <li {...lineProps}>
        <div>
          <BiSolidEraser {...iconProps} title='react-icons/bi: BiSolidEraser' />
        </div>
        <div>
          Remove (AddTracksModal.tsx, MultiTrackTimeline.tsx,
          StudioStemsForm.tsx)
        </div>
      </li>
      <li {...lineProps}>
        <div>
          <BsFullscreen {...iconProps} title='react-icons/bs: BsFullscreen' />
        </div>
        <div>Reset Zoom (Transport.tsx)</div>
      </li>
      <li {...lineProps}>
        <div>
          <BsWindow {...iconProps} title='react-icons/bs: BsWindow' />
        </div>
        <div>Advanced Mode (EditHeader.tsx)</div>
      </li>
      <li {...lineProps}>
        <div>
          <FaGuitar {...iconProps} title='react-icons/fa: FaGuitar' />
        </div>
        <div>Bass stem (StemInteractionUI.tx)</div>
      </li>
    </ul>
  );
};
