import React, { useState } from 'react'
import { type Meta, type StoryObj } from '@storybook/react-vite'

import { DocsTemplate } from '../../../.storybook'
import Button from '../Button/Button'
import FormFooter from '../Form/FormFooter'
import MultiSelect from '../MultiSelect/MultiSelect'
import { SideDrawer } from './SideDrawer'
import { toast } from '../Toast/Toast'

const meta: Meta<typeof SideDrawer> = {
  title: 'Components/SideDrawer/Exposed MultiSelect',
  component: SideDrawer,
  parameters: {
    design: {
      type: 'figma',
      url: 'https://www.figma.com/design/RvhKD82948FMQnh5MyCi0o/Web-Design-System?node-id=121-346&t=jsd8kEmb1sJfCa2m-0',
    },
    docs: {
      page: () => (
        <DocsTemplate
          figmaLink='https://www.figma.com/design/RvhKD82948FMQnh5MyCi0o/Web-Design-System?node-id=121-346&t=jsd8kEmb1sJfCa2m-0'
          description={
            <span>
              The <code>SideDrawer</code> should be used to contain all forms
              that were previously handled in popovers. These drawers can be
              used for information, help, and will be in place of popovers that
              are otherwise too large to comfortably fit the screen.
            </span>
          }
          infoBullets={[
            'Many instances of forms that could comfortably fit in a drawer. These would not include very large forms that may need their own page.',
            'In mobile when the popover content cannot easily fit on the screen.',
          ]}
        />
      ),
    },
  },
}

export default meta

type Story = StoryObj<typeof SideDrawer>

const Template: Story = {
  render: function Render(args) {
    const [isOpen, setIsOpen] = useState(false)

    const toggleDrawer = () => {
      setIsOpen(!isOpen)
    }
    return (
      <>
        <Button onClick={toggleDrawer}>Open Side Drawer</Button>
        <SideDrawer
          {...args}
          isOpen={isOpen}
          closeCallout={toggleDrawer}
          noGradient
        >
          {(props: { height; close }) =>
            args.children ? (
              typeof args.children === 'function' ? (
                args.children(props)
              ) : (
                (args.children as React.ReactElement)
              )
            ) : (
              <p>Side Drawer Content Goes here</p>
            )
          }
        </SideDrawer>
      </>
    )
  },
}

const resetButtonProps = {
  onClick: () => {
    toast({
      type: 'success',
      message: 'You clicked the Reset button!',
    })
  },
}
const cancelButtonProps = (close) => {
  return {
    onClick: () => {
      toast({
        type: 'success',
        message: 'You clicked the Cancel button!',
      })
      close()
    },
  }
}
const saveButtonProps = (close) => {
  return {
    onClick: () => {
      toast({
        type: 'success',
        message: 'You clicked the Save button!',
      })
      close()
    },
  }
}

const ShowForm = ({
  selectedOptions,
  options,
  maxHeight,
}: {
  selectedOptions: Array<string>
  options: Array<string>
  maxHeight?: number | string
}): React.JSX.Element => {
  const [selected, setSelected] = useState(selectedOptions)

  return (
    <MultiSelect
      options={options.map((option) => ({ label: option }))}
      selectedOptions={selected.map((option) => ({ label: option }))}
      callout={(selectedList) => {
        setSelected(selectedList.map((option) => option.label))
      }}
      searchBarProps={{
        placeholder: 'Name',
        value: '',
      }}
      emptyStateProps={{ primaryText: 'No Names Found' }}
      maxHeight={maxHeight}
      formLabelProps={{ label: 'Select a Name' }}
      labelKey={'label'}
      exposed
    />
  )
}

const options = [
  `D'Artagnan`,
  'Dave',
  'Ethan',
  'Gavin',
  'Jason',
  'Joe',
  'Josh',
  'Khayyam',
  'Matt',
  'Nate',
  'Russell',
]

const generateUniqueNames = () => {
  const names: Array<string> = []
  for (let i = 0; i < 50; i++) {
    const randomName = Math.floor(Math.random() * options.length)
    names.push(`#${i + 1} - ${options[randomName]}`)
  }
  return names
}

export const FewOptions: Story = {
  ...Template,
  args: {
    headerContent: 'Exposed MultiSelect',
    children: <ShowForm selectedOptions={[]} options={options.slice(0, 4)} />,
    footerContent: ({ close }) => (
      <FormFooter
        resetButtonProps={resetButtonProps}
        cancelButtonProps={cancelButtonProps(close)}
        saveButtonProps={{
          ...saveButtonProps(close),
          children: 'Save Changes',
        }}
      />
    ),
  },
}

export const ManyOptions: Story = {
  ...Template,
  args: {
    headerContent: 'Exposed MultiSelect',
    children: <ShowForm selectedOptions={[]} options={options} />,
    footerContent: ({ close }) => (
      <FormFooter
        resetButtonProps={resetButtonProps}
        cancelButtonProps={cancelButtonProps(close)}
        saveButtonProps={{
          ...saveButtonProps(close),
          children: 'Save Changes',
        }}
      />
    ),
  },
}

export const ManyOptionsWithMaxHeightOverride: Story = {
  ...Template,
  args: {
    headerContent: 'Exposed MultiSelect',
    children: ({ height }) => (
      <ShowForm
        selectedOptions={[]}
        options={generateUniqueNames()}
        maxHeight={height - 38 - 24} // 38px accounts for the height of the gradients above and below the MultiSelect. 24px is the height of the MultiSelect label.
      />
    ),
    footerContent: ({ close }) => (
      <FormFooter
        resetButtonProps={resetButtonProps}
        cancelButtonProps={cancelButtonProps(close)}
        saveButtonProps={{
          ...saveButtonProps(close),
          children: 'Save Changes',
        }}
      />
    ),
  },
}
