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

import { DocsTemplate } from '../../../.storybook'
import ExposedFilterGroupComponent from './ExposedFilterGroup'
import { type MultiSelectDataItemBase } from '../MultiSelect/MultiSelect'
import { type MinMaxRange } from '../RangeFilter/RangeFilter'
import {
  type ExposedFilterNameType,
  type ExposedFilterProps,
} from '../ExposedFilter/ExposedFilter.models'
import {
  CheckboxState,
  type DateCheckState,
  getFlattenNestedTreeList,
} from '../Form/NestedCheckboxHelper'
import { generateDummyNestedMultiSelectData } from '../MultiSelect/MultiSelectStoryHelpers'
import FormFooter from '../Form/FormFooter'
import { type ModalProps } from '../Modal/Modal'
import Checkbox from '../Form/Checkbox'
interface FilterType extends MultiSelectDataItemBase, ExposedFilterNameType {}

const meta: Meta<typeof ExposedFilterGroup> = {
  title: 'Components/ExposedFilter/ExposedFilterGroup',
  component: ExposedFilterGroupComponent,
  parameters: {
    docs: {
      page: () => (
        <DocsTemplate
          description={
            <span>
              The <code>ExposedFilterGroup</code> component can be used to
              display multiple filters directly on the page.
            </span>
          }
          infoBullets={[
            <span key='first-bullet'>
              Utilize the <strong>ExposedFilterGroup</strong> component to
              display multiple exposed filters without a SideDrawer
            </span>,
          ]}
        />
      ),
    },
  },
}

export default meta

type Story = StoryObj<typeof ExposedFilterGroup>

const Template: Story = {
  render: ({ ...args }) => {
    return <ExposedFilterGroup {...args} />
  },
}

interface FilterStateType {
  status: FilterType[]
  category: FilterType[]
  date?: Date
  dateRange?: DateRange
  priority?: FilterType
  search?: string
  amount?: MinMaxRange
  nestedItemStates?: {
    id: string | number
    state: CheckboxState
  }[]
  modal?: string[]
}

const ExposedFilterGroup = (args) => {
  const [filtersState, setFiltersState] = useState<FilterStateType>({
    status: [
      { id: 1, name: 'Created' },
      { id: 2, name: 'Arrived' },
      { id: 3, name: 'Processed' },
    ],
    category: [],
    date: undefined,
    dateRange: undefined,
    priority: undefined,
    search: '',
    amount: { min: undefined, max: undefined },
    nestedItemStates: [],
  })

  const resetCallout = () => {
    setFiltersState({
      status: [],
      category: [],
      date: undefined,
      dateRange: undefined,
      priority: undefined,
      amount: { min: undefined, max: undefined },
      nestedItemStates: [],
    })
  }

  const [tempModalSelection, setTempModalSelection] = useState<string[]>(
    filtersState?.modal || [],
  )
  const [isModalOpen, setIsModalOpen] = useState(false)

  const onChangeCallout: ExposedFilterProps<FilterType>['onChangeCallout'] = (
    filterName,
    value,
  ) => {
    setFiltersState((prevState) => ({
      ...prevState,
      [filterName]: value,
    }))
    if (filterName === 'modal') {
      setTempModalSelection((value as string[]) || [])
    }
  }

  const nestedMultiSelectData = generateDummyNestedMultiSelectData()

  const flattenData = useMemo(
    () =>
      getFlattenNestedTreeList({
        nestedData: nestedMultiSelectData ?? [],
        childrenKey: 'children',
        parentKey: 'parent_category_id',
        idKey: 'id',
      }),
    [nestedMultiSelectData],
  )
  const defaultItemStates = useMemo(
    () =>
      flattenData.map((i) => ({
        id: i['id'] as string | number,
        state: CheckboxState.UNCHECKED,
      })),
    [flattenData],
  )
  const identifierKeys = {
    displayKey: 'name',
    idKey: 'id',
    parentKey: 'parent_category_id',
  }

  const tableConfig = [
    {
      label: '',
      dataKey: 'name',
      children: (data) => <span className='text-xs'>{data.name}</span>,
    },
  ]

  const [itemStates, setItemStates] =
    useState<DateCheckState[]>(defaultItemStates)

  const statuses = [
    { id: 1, name: 'Created' },
    { id: 2, name: 'Arrived' },
    { id: 3, name: 'Processed' },
    { id: 4, name: 'Receiving' },
    { id: 5, name: 'Canceled' },
  ]

  const categories = [
    { id: 1, name: 'Electronics' },
    { id: 2, name: 'Clothing' },
    { id: 3, name: 'Food' },
    { id: 4, name: 'Home' },
    { id: 5, name: 'Beauty' },
  ]

  const priorities = [
    { id: 1, name: 'High' },
    { id: 2, name: 'Medium' },
    { id: 3, name: 'Low' },
  ]

  const statusMultiSelectProps = {
    options: statuses,
    searchBarProps: {
      placeholder: 'Search',
    },
    emptyStateProps: {
      primaryText: 'No Status Found',
      secondaryText: 'Try searching for a different status',
    },
    labelKey: 'name',
    hideSelectAll: true,
    selectedOptions: filtersState.status,
  }

  const categoryMultiSelectProps = {
    options: categories,
    searchBarProps: {
      placeholder: 'Search categories',
    },
    emptyStateProps: {
      primaryText: 'No Category Found',
      secondaryText: 'Try searching for a different category',
    },
    labelKey: 'name',
    hideSelectAll: true,
    selectedOptions: filtersState.category,
  }

  const prioritySelectProps = {
    options: priorities,
    searchBarProps: {
      placeholder: 'Search priorities',
    },
    emptyStateProps: {
      primaryText: 'No Priority Found',
      secondaryText: 'Try searching for a different priority',
    },
    labelKey: 'name',
    selectedOption: filtersState.priority,
  }

  const dateProps = {
    type: 'single',
    selectedDate: filtersState.date,
  }

  const dateRangeProps = {
    type: 'range',
    selectedDateRange: filtersState.dateRange,
  }

  const withSearch = {
    type: 'search',
    stateName: 'search',
    searchBarProps: {
      value: filtersState.search,
      placeholder: 'Search',
    },
  }

  const amountRangeProps = {
    selectedValues: filtersState.amount,
  }

  const nestedProps = {
    selectedOptions: filtersState.nestedItemStates,
    options: nestedMultiSelectData,
    labelKey: 'name',
    nestedConfig: {
      data: flattenData,
      itemStates,
      setItemStates,
      identifierKeys,
      tableConfig,
    },
  }

  const modalProps: ModalProps = {
    isOpen: isModalOpen,
    closeCallout: () => setIsModalOpen(false),
    size: 'sm',
    headerContent: 'Item Filter',
    footerContent: (
      <FormFooter
        saveButtonProps={{
          onClick: () => {
            setFiltersState((prevState) => ({
              ...prevState,
              modal: tempModalSelection,
            }))
            setIsModalOpen(false)
          },
          children: 'filter',
          styleType: 'primary',
        }}
        cancelButtonProps={{
          onClick: () => {
            setIsModalOpen(false)
          },
        }}
      />
    ),
    children: (
      <div className='flex flex-col gap-4'>
        <div className='flex flex-col gap-2'>
          <Checkbox
            label='P0NEIWB5'
            checked={tempModalSelection.includes('P0NEIWB5')}
            callout={() => {
              setTempModalSelection((prev) =>
                prev.includes('P0NEIWB5')
                  ? prev.filter((item) => item !== 'P0NEIWB5')
                  : [...prev, 'P0NEIWB5'],
              )
            }}
            checkboxColor='blue'
            type='checkbox'
          />
          <Checkbox
            label='P0OGSJWM'
            checked={tempModalSelection.includes('P0OGSJWM')}
            callout={() => {
              setTempModalSelection((prev) =>
                prev.includes('P0OGSJWM')
                  ? prev.filter((item) => item !== 'P0OGSJWM')
                  : [...prev, 'P0OGSJWM'],
              )
            }}
            checkboxColor='blue'
            type='checkbox'
          />
        </div>
      </div>
    ),
  }

  const filters = [
    {
      type: 'multi-select',
      stateName: 'status',
      labelName: 'Status',
      multiSelectProps: statusMultiSelectProps,
    },
    {
      type: 'multi-select',
      stateName: 'category',
      labelName: 'Category',
      multiSelectProps: categoryMultiSelectProps,
    },
    {
      type: 'date',
      dateProps: dateProps,
      stateName: 'date',
      labelName: 'Date',
    },
    {
      type: 'date',
      dateProps: dateRangeProps,
      stateName: 'dateRange',
      labelName: 'Date Range',
    },
    {
      type: 'select',
      stateName: 'priority',
      labelName: 'Priority',
      selectProps: prioritySelectProps,
    },
    {
      type: 'range',
      rangeProps: amountRangeProps,
      labelName: 'Amount',
      stateName: 'amount',
    },
    {
      type: 'multi-select',
      labelName: 'Nested',
      stateName: 'nestedItemStates',
      multiSelectProps: nestedProps,
    },
    {
      type: 'modal',
      labelName: 'Modal',
      stateName: 'modal',
      openCallout: () => setIsModalOpen(true),
      selectedOption: filtersState.modal,
      modalProps: modalProps,
    },
  ]

  return args.type === 'search' ? (
    <ExposedFilterGroupComponent
      {...args}
      filters={[withSearch, ...filters]}
      resetCallout={resetCallout}
      onChangeCallout={onChangeCallout}
    />
  ) : (
    <ExposedFilterGroupComponent
      {...args}
      filters={filters}
      resetCallout={resetCallout}
      onChangeCallout={onChangeCallout}
    />
  )
}

export const Basic: Story = {
  ...Template,
}

export const WithSearchBar: Story = {
  ...Template,
  args: {
    type: 'search',
  },
}
