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

import { DocsTemplate } from '../../../.storybook'
import { type ActiveFilterProps } from '../SortColumn/SortColumn'
import FormLabel from '../FormLabel/FormLabel'
import { hasValue, notEmpty } from '../../services/HelperServiceTyped'
import Picker from '../Picker/Picker'
import Switch from '../Switch/Switch'
import Tag from '../Tag/Tag'
import Tiles from '../Tiles/Tiles/Tiles'
import Tooltip from '../Tooltip/Tooltip'
import MdashCheck from '../Mdash/MdashCheck'
import { toast } from '../Toast/Toast'
import StandardTable from './StandardTable'
import { TableDocs } from './TableStoryHelper'
import { tableHeaderStoryArgs } from './TableHeader/TableHeaderStoryHelper'
import {
  extraTableSampleData,
  generateRandomSampleData,
  generateTableConfig,
  groupAccordionSampleData,
  multiNestedTableSampleData,
  nestedRowStylingData,
  nestedTableSampleData,
  standardTableSampleData,
  tableConfig,
  type TableObjectType,
} from './StandardTableStoryHelpers'
import { NESTED_PARENT_KEY } from './helperCheckboxFunctions'
import { type ActiveTableFilterObj } from './TableFilter/TableFilter'
import { generateTiles } from '../Tiles/tile-stories-helper'

const meta: Meta<typeof StandardTable> = {
  title: 'Components/Tables/StandardTable',
  component: StandardTable,
  parameters: {
    layout: 'padded',
    design: {
      type: 'figma',
      url: 'https://www.figma.com/design/RvhKD82948FMQnh5MyCi0o/Web-Design-System?node-id=121-349&t=CdMnrLNv0lNFwXr0-0',
    },
    docs: {
      page: () => (
        <DocsTemplate
          figmaLink='https://www.figma.com/design/RvhKD82948FMQnh5MyCi0o/Web-Design-System?node-id=121-349&t=CdMnrLNv0lNFwXr0-0'
          description={<TableDocs tableName='StandardTable' />}
        />
      ),
    },
  },
}

export default meta

type Story = StoryObj<typeof StandardTable>

// Common sorting hook for the table components
function useSortableData(
  initialData: TableObjectType[],
  initialSort: { prop: string; flip: boolean },
  activeFilter?: ActiveFilterProps,
) {
  const [sort, setSort] = useState(initialSort)

  const setSortBy = (sortObj: { activeColumn: string; direction: boolean }) => {
    setSort({
      prop: sortObj.activeColumn,
      flip: sortObj.direction,
    })
  }

  const data = useMemo(() => {
    let filteredRecords = [...initialData]

    if (activeFilter && Object.keys(activeFilter).length > 0) {
      Object.values(activeFilter).forEach(
        ({ text: symbol, actualValue, value, keyField }) => {
          const filterValue = actualValue
            ? Number(actualValue.toString())
            : Number(value.toString())

          filteredRecords = filteredRecords.filter((record) => {
            const value = record[keyField]
            const finalValue = value.toString().includes('$')
              ? value.replace('$', '').trim()
              : value
            const recordValue = Number(finalValue)

            switch (symbol) {
              case '>':
                return recordValue > filterValue
              case '≥':
                return recordValue >= filterValue
              case '<':
                return recordValue < filterValue
              case '≤':
                return recordValue <= filterValue
              default:
                return true
            }
          })
        },
      )
    }

    filteredRecords.sort((a, b) => {
      const aVal = a[sort.prop]
      const bVal = b[sort.prop]
      if (aVal < bVal) {
        return sort.flip ? -1 : 1
      }
      if (aVal > bVal) {
        return sort.flip ? 1 : -1
      }
      return 0
    })

    return filteredRecords
  }, [activeFilter, initialData, sort.flip, sort.prop])

  return { data, sort, setSortBy }
}

// Common column selection hook for table components
function useSelectionList(defaultColumns: string[]) {
  const [selectionList, setSelectionList] = useState(defaultColumns)

  const resetSelectionList = () => setSelectionList(defaultColumns)

  return { selectionList, setSelectionList, resetSelectionList }
}

// Custom column settings for the table
interface SettingsProps {
  selectionList: string[]
  defaultColumns: string[]
  setSelectionList: (selectionList: string[]) => void
  resetSelectionList: () => void
  topChildren?: React.ReactNode
  bottomChildren?: React.ReactNode
  isColumnsReorderable?: boolean
  getSecondaryOption?: (label: string) => React.ReactNode
}

const tableSettings = ({
  selectionList,
  defaultColumns,
  setSelectionList,
  resetSelectionList,
  topChildren,
  bottomChildren,
  isColumnsReorderable,
  getSecondaryOption,
}: SettingsProps) => ({
  title: 'Table Settings',
  selected: selectionList,
  list: defaultColumns,
  callout: setSelectionList,
  setToDefaultCallout: resetSelectionList,
  topChildren,
  bottomChildren,
  cancelCallout: () =>
    toast({
      type: 'success',
      message: 'Canceled modified settings.',
    }),
  isColumnsReorderable,
  getSecondaryOption,
})

const defaultColumns = [
  'Tag',
  'Number',
  'Decimal',
  'Percent',
  'Currency',
  'String',
  'Availability',
  'Traffic',
  'Conversion',
  'Price',
  'Loyalty',
]

const HandleStandardTable = (args) => {
  const { data, sort, setSortBy } = useSortableData(args.data, {
    prop: 'name',
    flip: true,
  })
  const { selectionList, setSelectionList, resetSelectionList } =
    useSelectionList(defaultColumns)
  const options = [
    {
      id: 1,
      text: 'Option 1',
      value: 'option-1',
    },
    {
      id: 2,
      text: 'Option 2',
      value: 'option-2',
    },
    {
      id: 3,
      text: 'Option 3',
      value: 'option-3',
    },
  ]
  const [toggleState, setToggleState] = useState(false)
  const [active, setActive] = useState(options[0])

  const updateSelected = (value: string) => {
    const activeOption = options.find((item) => item.value === value)
    setActive(activeOption || options[0])
    toast({
      type: 'success',
      message: `${activeOption?.text} Selected`,
    })
  }

  const TopSettings = () => (
    <div className='flex justify-between text-xs'>
      <FormLabel label='Show contribution to change bps' />
      <Switch
        checked={toggleState}
        callout={() => {
          setToggleState(!toggleState)
          toast({
            type: 'success',
            message: `${
              !toggleState ? 'Settings Enabled' : 'Settings Disabled'
            }`,
          })
        }}
      />
    </div>
  )

  const BottomSettings = () => (
    <div className='text-xs'>
      <FormLabel label='Select Option:' />
      <Picker
        callout={(_, value) => {
          updateSelected(value)
        }}
        options={options}
        state={active}
        stateName='value'
      />
    </div>
  )

  // Used to demo the table with expandable rows.
  const [activeRowId, setActiveRowId] = useState<string | number | null>(null)
  const [tiles, setTiles] = useState(generateTiles(4))

  return (
    <StandardTable
      customHeight='500px'
      customWidth='auto'
      stickyTableConfig={{ right: 1 }}
      {...args}
      config={args.config.filter(
        (c) => selectionList.includes(c.label) || c.label === 'Name',
      )}
      customColumnProps={tableSettings({
        selectionList,
        defaultColumns,
        setSelectionList,
        resetSelectionList,
        topChildren: TopSettings(),
        bottomChildren: BottomSettings(),
      })}
      {...(args.noSort ? { noSort: true } : { sort: setSortBy, sortBy: sort })}
      data={data}
      {...(args.hasExpandableContent
        ? {
            hasExpandableContent: true,
            expandedAccordionContent: {
              id: activeRowId,
              isLoading: false,
              content: (
                <Tiles
                  tiles={tiles}
                  onTilesChange={(newTiles) => setTiles(newTiles)}
                />
              ),
              callout: (id: string | number) => {
                setActiveRowId(id)
              },
            },
          }
        : {})}
    />
  )
}

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

const HandleStandardTableWithHeader = (args) => {
  const [activeFilters, setActiveFilters] = useState<ActiveFilterProps>({})
  const { data, sort, setSortBy } = useSortableData(
    args.data,
    {
      prop: 'name',
      flip: true,
    },
    activeFilters,
  )
  const { selectionList, setSelectionList, resetSelectionList } =
    useSelectionList(args.tableHeaderProps?.customColumnProps?.list)

  const remove = (filter?: ActiveTableFilterObj & { keyField: string }) => {
    if (filter) {
      setActiveFilters((prevState) => {
        const prevStateCopy = { ...prevState }
        Object.keys(prevStateCopy).forEach((key) => {
          if (prevStateCopy[key].keyField === filter.keyField) {
            delete prevStateCopy[key]
          }
        })
        return prevStateCopy
      })
    } else {
      setActiveFilters({})
    }
  }

  return (
    <>
      <StandardTable
        customHeight='500px'
        customWidth='auto'
        {...args}
        config={
          args.tableHeaderProps?.customColumnProps?.isColumnsReorderable
            ? [
                args.config[0],
                ...selectionList
                  .map(
                    (text) =>
                      args.config?.filter((item) => item.label === text)?.[0],
                  )
                  .filter((item) => hasValue(item)),
              ]
            : args.config.reduce((acc, c) => {
                if (selectionList.includes(c.label) || c.label === 'Name') {
                  const column = notEmpty(c.filter)
                    ? {
                        ...c,
                        filter: {
                          ...c.filter,
                          callout: (
                            _: string,
                            selectedColumnFilter: ActiveFilterProps,
                          ) => {
                            if (notEmpty(selectedColumnFilter[c.label].value)) {
                              setActiveFilters((prev) => ({
                                ...prev,
                                ...selectedColumnFilter,
                              }))
                            }
                          },
                        },
                      }
                    : c

                  acc.push(column)
                }
                return acc
              }, [])
        }
        {...(args.tableHeaderProps
          ? {
              tableHeaderProps: {
                ...args.tableHeaderProps,
                customColumnProps: tableSettings({
                  selectionList,
                  defaultColumns:
                    args.tableHeaderProps?.customColumnProps?.list,
                  setSelectionList,
                  resetSelectionList,
                  isColumnsReorderable:
                    args.tableHeaderProps?.customColumnProps
                      ?.isColumnsReorderable,
                  getSecondaryOption:
                    args.tableHeaderProps?.customColumnProps
                      ?.getSecondaryOption,
                }),
                columnFilterProps: {
                  activeFilters,
                  remove,
                },
              },
            }
          : {})}
        sortBy={sort}
        sort={setSortBy}
        data={data}
      />
    </>
  )
}

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

const storyConfig = {
  data: standardTableSampleData,
  config: tableConfig,
  dataKey: 'name',
  hasData: true,
  hasMore: false,
  successStatus: true,
  loading: false,
  tableId: 'unique_table_string',
  noDataFields: {
    primaryText: 'No Data Available',
    secondaryText:
      'There has been a problem with the data file. Please restart your computer.',
  },
  getData: () => undefined,
}
const { config, loading } = storyConfig

export const basicTable = {
  ...Template,
  args: storyConfig,
  parameters: {
    docs: {
      source: {
        code: `<StandardTable
  data={data}
  config={tableConfig}
  dataKey="name"
  customHeight="500px"
  customWidth="auto"
/>`,
      },
    },
  },
}

const tableHeaderColumns = generateTableConfig(
  ['Name', ...defaultColumns],
  false,
  true,
)

export const tableHeader = {
  ...TemplateWithHeader,
  args: {
    ...storyConfig,
    config: tableHeaderColumns,
    tableHeaderProps: {
      ...tableHeaderStoryArgs,
      customColumnProps: {
        list: defaultColumns,
      },
    },
  },
  parameters: {
    docs: {
      source: {
        code: `<StandardTable
  data={data}
  config={tableConfig}
  dataKey="name"
  customHeight="500px"
  customWidth="auto"
  tableHeaderProps={{
    title: "Table Title",
    customColumnProps: {
      list: defaultColumns
    }
  }}
/>`,
      },
    },
  },
}

const customColumns = (isLongTooltip?: boolean) =>
  generateTableConfig(['Name', ...defaultColumns], false, false, isLongTooltip)

const showCheckedItemsToast = (checkedItems: any[]) => {
  const items = checkedItems.map((item) => item?.name).join(', ')

  toast({
    type: 'info',
    message:
      checkedItems.length > 0 ? `Checked rows: ${items}` : 'No rows checked!',
  })
}

export const customizeColumns = {
  ...Template,
  args: {
    ...storyConfig,
    config: customColumns(true),
    customColumnProps: true,
  },
  parameters: {
    docs: {
      source: {
        code: `<StandardTable
  data={data}
  config={tableConfig}
  dataKey="name"
  customHeight="500px"
  customWidth="auto"
  customColumnProps={{
    title: "Table Settings",
    list: defaultColumns,
    selected: selectedColumns
  }}
/>`,
      },
    },
  },
}
customizeColumns.storyName = 'Customize Columns (Desktop only)'

export const rowStyling = {
  ...Template,
  args: {
    ...storyConfig,
    data: standardTableSampleData.map((item: TableObjectType) => {
      // Create alternating pattern with multiple color variations
      if (item.number === 1 || item.number === 2) {
        return { ...item, rowClassName: 'bgc-light-red' }
      }
      if (item.number === 10) {
        return { ...item, rowClassName: 'bgc-light-yellow' }
      }
      if (item.number === 11 || item.number === 12) {
        return { ...item, rowClassName: 'bgc-light-green' }
      }
      if (item.number === 14) {
        return {
          ...item,
          rowStyle: {
            fontWeight: 'bold',
            backgroundColor: 'var(--light-purple)',
          },
        }
      }
      return item
    }),
  },
}

export const rowStylingWithCheckboxes = {
  ...Template,
  args: {
    ...storyConfig,
    hasCheckboxes: true,
    handleCheckedBoxes: (checkedItems: TableObjectType[]) => {
      showCheckedItemsToast(checkedItems)
    },
    data: standardTableSampleData.map((item: TableObjectType) => {
      // Highlight rows with checkbox column also styled
      if (item.number === 1 || item.number === 10) {
        return { ...item, rowClassName: 'bgc-light-red' }
      }
      if (item.number === 13 || item.number === 14) {
        return { ...item, rowClassName: 'bgc-light-yellow' }
      }
      return item
    }),
  },
}
rowStylingWithCheckboxes.storyName = 'Row Styling with Checkboxes'

export const cellOverrideRow = {
  ...Template,
  args: {
    ...storyConfig,
    data: standardTableSampleData.map((item: TableObjectType) => {
      if (item.number === 1) {
        return {
          ...item,
          rowClassName: 'bgc-light-red',
        }
      }
      if (item.number === 2) {
        return {
          ...item,
          rowStyle: { backgroundColor: 'var(--light-yellow)' },
        }
      }
      if (item.number === 3) {
        return {
          ...item,
          rowClassName: 'bgc-light-green',
        }
      }
      if (item.number === 4) {
        return {
          ...item,
          rowStyle: { backgroundColor: 'var(--light-red)' },
        }
      }

      return item
    }),
    config: storyConfig.config.map((configItem, index) => {
      if (index === 1) {
        return {
          ...configItem,
          cell: {
            ...configItem.cell,
            className: (data: TableObjectType) => {
              if (data.number === 1) {
                return 'bgc-light-blue'
              }
              return ''
            },
          },
        }
      }
      if (index === 2) {
        return {
          ...configItem,
          cell: {
            ...configItem.cell,
            style: (data: TableObjectType) => {
              if (data.number === 1) {
                return { backgroundColor: 'var(--light-blue)' }
              }
              if (data.number === 2) {
                return { backgroundColor: 'var(--light-purple)' }
              }
              if (data.number === 3) {
                return { backgroundColor: 'var(--light-orange)' }
              }
              return {}
            },
          },
        }
      }
      return configItem
    }),
  },
}
cellOverrideRow.storyName = 'Cell Styling'

export const rowStylingWithNestedRows = {
  ...Template,
  args: {
    ...storyConfig,
    nestedDataKey: 'id',
    data: standardTableSampleData.map((item: TableObjectType) => {
      if (item.number === 1) return { ...item, rowClassName: 'bgc-light-red' }
      if (item.number === 2)
        return { ...item, rowClassName: 'bgc-light-yellow' }
      if (item.number === 3) return { ...item, rowClassName: 'bgc-light-green' }
      return item
    }),
    nestedRowProps: {
      nestedData: nestedRowStylingData,
      getNestedData: () => undefined,
      showCaret: (dataItem: TableObjectType) =>
        [1, 2, 3].includes(dataItem?.id),
    },
  },
}
rowStylingWithNestedRows.storyName = 'Row Styling with Nested Rows'

export const checkboxTable = {
  ...Template,
  args: {
    ...storyConfig,
    hasCheckboxes: true,
    disableCheckboxes: (item: TableObjectType) => item.number === 3,
    handleCheckedBoxes: (checkedItems: TableObjectType[]) => {
      showCheckedItemsToast(checkedItems)
    },
    disableCheckAll: false,
  },
  parameters: {
    docs: {
      source: {
        code: `<StandardTable
  data={data}
  config={tableConfig}
  dataKey="name"
  hasCheckboxes
  disableCheckboxes={(item) => item.number === 3}
  handleCheckedBoxes={(checkedItems) => {
    // Handle checked items
  }}
/>`,
      },
    },
  },
}

export const DisabledCheckAll = {
  ...Template,
  args: {
    ...storyConfig,
    hasCheckboxes: true,
    disableCheckboxes: (item) => item.number === 3,
    handleCheckedBoxes: (checkedItems) => {
      showCheckedItemsToast(checkedItems)
    },
    disableCheckAll: true,
  },
  parameters: {
    docs: {
      source: {
        code: `<StandardTable
  data={data}
  config={tableConfig}
  dataKey="name"
  hasCheckboxes
  disableCheckAll
  disableCheckboxes={(item) => item.number === 3}
  handleCheckedBoxes={(checkedItems) => {
    // Handle checked items
  }}
/>`,
      },
    },
  },
}

export const checkboxTableWithSelectOptions = {
  ...Template,
  args: {
    ...storyConfig,
    hasCheckboxes: true,
    handleCheckedBoxes: (checkedItems) => {
      showCheckedItemsToast(checkedItems)
    },
    checkboxSelectOptions: {
      options: [
        { name: 'option1', label: 'Option 1' },
        { name: 'option2', label: 'Option 2' },
        { name: 'option3', label: 'Option 3' },
      ],
      callout: (option) => {
        toast({
          type: 'success',
          message: `You clicked on ${option.label}!`,
        })
      },
    },
  },
  parameters: {
    docs: {
      source: {
        code: `<StandardTable
  data={data}
  config={tableConfig}
  dataKey="name"
  hasCheckboxes
  handleCheckedBoxes={(checkedItems) => {
    // Handle checked items
  }}
  checkboxSelectOptions={{
    options: [
      { name: 'option1', label: 'Option 1' },
      { name: 'option2', label: 'Option 2' },
      { name: 'option3', label: 'Option 3' }
    ],
    callout: (option) => {
      // Handle option selection
    }
  }}
/>`,
      },
    },
  },
}

export const reorderableColumns = {
  ...TemplateWithHeader,
  args: {
    ...storyConfig,
    config: customColumns,
    tableHeaderProps: {
      ...tableHeaderStoryArgs,
      customColumnProps: {
        list: defaultColumns,
        isColumnsReorderable: true,
      },
    },
  },
  parameters: {
    docs: {
      source: {
        code: `<StandardTable
  data={data}
  config={tableConfig}
  dataKey="name"
  tableHeaderProps={{
    title: "Table Title",
    customColumnProps: {
      list: defaultColumns,
      isColumnsReorderable: true
    }
  }}
/>`,
      },
    },
  },
}

export const customizeColumnsWithSecondaryOption = {
  ...TemplateWithHeader,
  args: {
    ...storyConfig,
    config: customColumns,
    tableHeaderProps: {
      ...tableHeaderStoryArgs,
      customColumnProps: {
        list: defaultColumns,
        isColumnsReorderable: true,
        getSecondaryOption: (label: string) => {
          const secondaryMap: Record<string, string> = {
            Tag: 'Secondary Text',
            Number: 'Secondary Text',
            Percent: 'Secondary Text',
            Currency: 'Secondary Text',
          }
          return secondaryMap[label] ? (
            <Tag color='blue'>{secondaryMap[label]}</Tag>
          ) : null
        },
      },
    },
  },
  parameters: {
    docs: {
      source: {
        code: `<StandardTable
  data={data}
  config={tableConfig}
  dataKey="name"
  tableHeaderProps={{
    title: "Table Title",
    customColumnProps: {
      list: defaultColumns,
      isColumnsReorderable: true,
      getSecondaryOption: (label) => {
        const secondaryMap = {
            Tag: 'Secondary Text',
            Number: 'Secondary Text',
            Percent: 'Secondary Text',
            Currency: 'Secondary Text',
        };
        return <Tag color='blue'>{secondaryMap[label]}</Tag>
      }
    }
  }}
/>`,
      },
    },
  },
}

export const checkedAllCheckboxTable = {
  ...Template,
  args: {
    ...storyConfig,
    hasCheckboxes: true,
    handleCheckedBoxes: (checkedItems) => {
      showCheckedItemsToast(checkedItems)
    },
    isDefaultCheckedAll: true,
  },
}
checkedAllCheckboxTable.storyName = 'Check All Enabled (Desktop only)'

export const groups = {
  ...Template,
  args: {
    ...storyConfig,
    getData: () => undefined,
    showGroups: true,
    groups: [
      {
        groupHeader: (
          <div className='flex items-center'>
            <img
              src='https://m.media-amazon.com/images/I/41Jd5FzxAkL.SL500.jpg'
              alt='flag'
              height={18}
              width={18}
              className='p-1'
            />
            <span> Group 1 - under 3</span>
          </div>
        ),
        tooltipContent: <span>Description of the header group 1 </span>,
        check: (item) => item.number < 3,
      },
      {
        groupHeader: 'Group 2 - over 3',
        tooltipContent: <span>Description of the header group 2 </span>,
        check: (item) => item.number > 3,
      },
    ],
  },
  parameters: {
    docs: {
      source: {
        code: `<StandardTable
  data={data}
  config={tableConfig}
  dataKey="name"
  showGroups
  groups={[
    {
      groupHeader: <div>Group 1 - under 3</div>,
      tooltipContent: <span>Description of the header group 1</span>,
      check: (item) => item.number < 3
    },
    {
      groupHeader: "Group 2 - over 3",
      tooltipContent: <span>Description of the header group 2</span>,
      check: (item) => item.number > 3
    }
  ]}
/>`,
      },
    },
  },
}

export const AlwaysShowGroups = {
  ...Template,
  args: {
    ...storyConfig,
    showGroups: true,
    hasCheckboxes: true,
    handleCheckedBoxes: (checkedItems) => {
      showCheckedItemsToast(checkedItems)
    },
    groups: [
      {
        groupHeader: 'Group 1 - Default Gray',
        check: (item: { number: number }) => item.number < 3,
        alwaysShowGroups: true,
      },
      {
        groupHeader: 'Group 2 - Red',
        check: (item: { number: number }) =>
          item.number >= 3 && item.number < 6,
        type: 'red',
        alwaysShowGroups: true,
      },
      {
        groupHeader: 'Group 3 - Blue',
        check: (item: { number: number }) => item.number > 6,
        type: 'blue',
        alwaysShowGroups: true,
      },
    ],
  },
}

export const groupColorVariation = {
  ...Template,
  args: {
    ...storyConfig,
    showGroups: true,
    groups: [
      {
        groupHeader: 'Group 1 - Default Gray',
        check: (item) => item.number < 3,
      },
      {
        groupHeader: 'Group 2 - Red',
        check: (item) => item.number > 3 && item.number < 6,
        type: 'red',
      },
      {
        groupHeader: 'Group 3 - Blue',
        check: (item) => item.number > 6 && item.number < 9,
        type: 'blue',
      },
      {
        groupHeader: 'Group 4 - Yellow',
        check: (item) => item.number > 9 && item.number < 12,
        type: 'yellow',
      },
      {
        groupHeader: 'Group 5 - Green',
        check: (item) => item.number > 12 && item.number < 15,
        type: 'green',
      },
    ],
  },
}

export const groupAccordion = {
  ...Template,
  args: {
    ...storyConfig,
    data: groupAccordionSampleData,
    showGroups: true,
    groups: [
      {
        groupHeader: 'Group 1',
        check: (item) => item.phaseKey === 'name1',
        groupAccordion: {
          isCollapsed: true,
          groupKey: 'name1',
        },
      },
      {
        groupHeader: 'Group 2',
        check: (item) => item.phaseKey === 'name2',
        groupAccordion: {
          isCollapsed: false,
          groupKey: 'name2',
        },
      },
    ],
  },
}
groupAccordion.storyName = 'Group Accordion (Desktop only)'

export const headerDetails = {
  ...Template,
  args: {
    ...storyConfig,
    data: [...standardTableSampleData, ...extraTableSampleData],
    showGroups: true,
    groups: [
      { groupHeader: 'Group 1 - under 3', check: (item) => item.number < 3 },
      { groupHeader: 'Group 2 - over 3', check: (item) => item.number > 3 },
    ],
  },
}
headerDetails.storyName = 'Group Header Details (Desktop only)'

export const checkboxGroups = {
  ...Template,
  args: {
    ...storyConfig,
    hasCheckboxes: true,
    handleCheckedBoxes: (checkedItems) => {
      showCheckedItemsToast(checkedItems)
    },
    showGroups: true,
    groups: [
      { groupHeader: 'Group 1 - under 3', check: (item) => item.number < 3 },
      { groupHeader: 'Group 2 - over 3', check: (item) => item.number > 3 },
    ],
  },
}
checkboxGroups.storyName = 'Checkbox & Groups (Desktop only)'

const HandleSimpleTable = (args) => {
  const [allData, setAllData] = useState<typeof standardTableSampleData>(
    generateRandomSampleData(),
  )
  const [data, setData] = useState<typeof standardTableSampleData>(
    allData.slice(0, 20),
  )

  const [sort, setSort] = useState({ prop: 'name', flip: false })

  const sortData = useCallback(
    (dataArray: typeof standardTableSampleData) => {
      const sortedData = [...dataArray]

      sortedData.sort((a, b) => {
        const aValue = a[sort.prop]
        const bValue = b[sort.prop]

        if (aValue < bValue) {
          return sort.flip ? 1 : -1
        }
        if (aValue > bValue) {
          return sort.flip ? -1 : 1
        }
        return 0
      })

      setAllData((prev) => {
        const isSame = isEqual(prev, sortedData)
        if (isSame) {
          return prev
        } else {
          setData(sortedData.slice(0, 20))
          return sortedData
        }
      })
    },
    [sort.flip, sort.prop],
  )

  const handleSort = (sortObj) => {
    setSort((prevState) => ({
      ...prevState,
      prop: sortObj.activeColumn,
      flip: sortObj.direction,
    }))
    setTimeout(() => sortData(allData))
  }

  const sortConfig = (args.config ?? tableConfig).map((configBase) => {
    delete configBase.noSort
    return {
      ...configBase,
      sort: handleSort,
      sortBy: sort,
    }
  })

  let newDataCount = 20

  const getData = () => {
    const newData = [...data]
    newData.push(
      ...standardTableSampleData.slice(newDataCount, newDataCount + 20),
    )
    newDataCount += 20
    setTimeout(() => setData(newData), 1000)
  }

  return (
    <StandardTable
      {...args}
      customHeight='500px'
      customWidth='auto'
      data={data}
      hasData={true}
      config={sortConfig}
      getData={getData}
      hasMore={data.length < allData.length}
      sort={handleSort}
      sortBy={sort}
    />
  )
}

const CheckboxTemplate: Story = {
  render: ({ ...args }) => {
    return <HandleSimpleTable {...args} />
  },
}
export const checkboxGroupsNewCheckAll = {
  ...CheckboxTemplate,
  args: {
    dataKey: 'name',
    successStatus: true,
    loading: false,
    tableId: 'checkbox_table_with_checkAll_banner',
    noDataFields: {
      primaryText: 'No Data Available',
      secondaryText:
        'There has been a problem with the data file. Please restart your computer.',
    },
    hasCheckboxes: true,
    handleCheckedBoxes: (checkedItems, checkAll) => {
      if (checkAll) {
        toast({
          type: 'info',
          message: 'ALL OPTIONS SELECTED (included options not yet loaded).',
        })
      } else {
        showCheckedItemsToast(checkedItems)
      }
    },
    enableCheckAll: true,
    totalCheckboxOptions: 100,
  },
}
checkboxGroupsNewCheckAll.storyName =
  'New Checkbox Experience (checkAll Banner)'

const HandleNestedCheckboxTable = (args) => {
  const { data, sort, setSortBy } = useSortableData(args.data.slice(0, 2), {
    prop: 'name',
    flip: true,
  })
  const [checkedCount, setCheckedCount] = useState(0)

  const showChildCheckboxes = args.nestedRowProps?.showCheckboxes !== false

  const handleCheckedBoxes = (items: TableObjectType[]) => {
    if (!showChildCheckboxes) {
      // showCheckboxes: false — count parent rows only (no _nestedParentKey)
      setCheckedCount(
        items.filter(
          (item) =>
            (item as Record<string, unknown>)[NESTED_PARENT_KEY] === undefined,
        ).length,
      )
    } else {
      // showCheckboxes: true — count child rows only (have _nestedParentKey)
      // also count parent rows that have no children (leaf-level)
      const parentKeysWithChildren = new Set(
        Object.keys(args.nestedRowProps?.nestedData ?? {}).filter(
          (k) => args.nestedRowProps?.nestedData[k]?.length > 0,
        ),
      )
      setCheckedCount(
        items.filter((item) => {
          const parentKey = (item as Record<string, unknown>)[NESTED_PARENT_KEY]
          if (parentKey !== undefined) return true // child row
          return !parentKeysWithChildren.has(String(item.id)) // parent with no children
        }).length,
      )
    }
    args.handleCheckedBoxes?.(items)
  }

  return (
    <div>
      <div className='mb-2 text-sm font-semibold'>
        {showChildCheckboxes ? 'Child rows' : 'Parent rows'} selected:{' '}
        <span className='font-semibold'>{checkedCount}</span>
      </div>
      <StandardTable
        customHeight='500px'
        customWidth='auto'
        stickyTableConfig={{ right: 1 }}
        {...args}
        sort={setSortBy}
        sortBy={sort}
        data={data}
        handleCheckedBoxes={handleCheckedBoxes}
      />
    </div>
  )
}

export const nestedRows = {
  ...Template,
  args: {
    ...storyConfig,
    nestedDataKey: 'id',
    nestedRowProps: {
      nestedData: nestedTableSampleData,
      getNestedData: () => undefined,
      showCaret: (dataItem) => {
        return !!nestedTableSampleData[dataItem?.id]
      },
      initiallyExpandedRows: [1],
    },
  },
  parameters: {
    docs: {
      source: {
        code: `<StandardTable
  data={data}
  config={tableConfig}
  dataKey="name"
  nestedDataKey="id"
  nestedRowProps={{
    nestedData: nestedData,
    showCaret: (dataItem) => !!nestedData[dataItem?.id],
    initiallyExpandedRows: [1]
  }}
/>`,
      },
    },
  },
}

const multiParentData = [
  {
    id: 999,
    name: `Parent Row Example`,
    tag: `Tag 0`,
    number: 54,
    decimal: 3.27,
    percent: 0.75,
    currency: 3546,
  },
  ...standardTableSampleData,
]

export const multiNestedRows = {
  ...Template,
  args: {
    ...storyConfig,
    data: multiParentData,
    nestedDataKey: 'id',
    nestedRowProps: {
      nestedData: multiNestedTableSampleData,
      getNestedData: () => undefined,
      showCaret: (dataItem) => {
        return !!multiNestedTableSampleData[dataItem?.id]
      },
      subRowDataKey: 'subCategory',
    },
  },
}

export const expandableRows = {
  ...Template,
  args: {
    ...storyConfig,
    hasExpandableContent: true,
  },
  parameters: {
    docs: {
      source: {
        code: `<StandardTable
  data={data}
  config={tableConfig}
  dataKey="name"
  hasExpandableContent
  expandedAccordionContent={{
    id: activeRowId,
    content: <YourExpandedContent />,
    callout: (id) => setActiveRowId(id)
  }}
/>`,
      },
    },
  },
}

export const loadingTable = {
  ...Template,
  args: {
    data: [],
    config,
    loading: true,
    shortListLoading: true,
    customHeight: 'auto',
  },
  parameters: {
    docs: {
      source: {
        code: `<StandardTable
  data={[]}
  config={tableConfig}
  loading
  shortListLoading
  customHeight="auto"
/>`,
      },
    },
  },
}

export const noDataTable = {
  ...Template,
  args: {
    data: [],
    config,
    loading,
    shortListLoading: true,
    noDataFields: {
      primaryText: 'No Data Available',
      secondaryText:
        'There has been a problem with the data file. Please restart your computer.',
      buttonProps: {
        children: 'Primary Button',
        onClick: () => {
          toast({
            type: 'success',
            message: 'You clicked the Primary button!',
          })
        },
      },
      icon: 'sellers',
    },
    customHeight: 'auto',
  },
  parameters: {
    docs: {
      source: {
        code: `<StandardTable
  data={[]}
  config={tableConfig}
  noDataFields={{
    primaryText: "No Data Available",
    secondaryText: "There has been a problem with the data file.",
    buttonProps: {
      children: "Primary Button",
      onClick: () => handleButtonClick()
    },
    icon: "sellers"
  }}
  customHeight="auto"
/>`,
      },
    },
  },
}

const newConfig = [...tableConfig]

const configChange = [
  {
    label: 'Percent',
    name: 'percent',
    noSort: true,
    columnHeaderSubContent: (
      <Tooltip tooltipContent='This is just a custom JSX node. Does not need to be a tooltip.'>
        <div className='text-blue'>View Details</div>
      </Tooltip>
    ),
    cell: {
      children: (d) => {
        return (
          <MdashCheck check={d?.percent}>
            <span
              className={d.sortProp === 'percent' ? 'font-semibold' : ''}
            >{`${(d?.percent * 100).toFixed(0)}%`}</span>
          </MdashCheck>
        )
      },
    },
  },
]
newConfig.splice(4, 1, ...configChange)

export const customColumnHeader = {
  ...Template,
  args: {
    ...storyConfig,
    config: newConfig,
  },
}

export const twoLineLabel = {
  ...CheckboxTemplate,
  args: {
    ...storyConfig,
    config: tableConfig.map((col) => {
      if (col.name === 'tag') {
        return {
          ...col,
          label: 'Column Tag Label',
        }
      }
      if (col.name === 'number') {
        return {
          ...col,
          label: 'A Very Long Label Value for the Number Column',
        }
      }
      if (col.name === 'decimal') {
        return {
          ...col,
          label: 'AVeryLongSingleWordThatShouldNotFitInTheColumnWidth',
        }
      }
      if (col.name === 'percent') {
        return {
          ...col,
          label: 'Standard Percent Column Values',
        }
      }
      return col
    }),
    twoLineLabel: true,
  },
}
twoLineLabel.storyName = 'Two Line Label (Desktop only)'

export const noSort = {
  ...Template,
  args: {
    ...storyConfig,
    noSort: true,
    config,
  },
}

export const columnBadges = {
  ...Template,
  args: {
    ...storyConfig,
    config: tableConfig.map((col) => {
      // Show beta prop (backward compatibility)
      if (col.name === 'tag') {
        return {
          ...col,
          beta: true,
        }
      }
      // Show badgeProps with different colors
      if (col.name === 'number') {
        return {
          ...col,
          badgeProps: {
            children: 'New',
            color: 'dark-green',
          },
        }
      }
      if (col.name === 'decimal') {
        return {
          ...col,
          badgeProps: {
            children: 'Updated',
            color: 'black',
          },
        }
      }
      if (col.name === 'percent') {
        return {
          ...col,
          badgeProps: {
            children: 'Beta',
            color: 'lavender',
          },
        }
      }
      return col
    }),
  },
}
columnBadges.storyName = 'Column Badges'

export const columnTags = {
  ...Template,
  args: {
    ...storyConfig,
    config: tableConfig.map((col) => {
      if (col.name === 'tag') {
        return {
          ...col,
          beta: true,
        }
      }

      if (col.name === 'number') {
        return {
          ...col,
          tagProps: {
            children: 'Live',
            color: 'green',
          },
        }
      }
      return col
    }),
  },
}
columnTags.storyName = 'Column Tags'

export const nestedRowCheckboxes = {
  render: ({ ...args }) => <HandleNestedCheckboxTable {...args} />,
  args: {
    ...storyConfig,
    dataKey: 'id',
    hasCheckboxes: true,
    nestedDataKey: 'id',
    disableCheckboxes: (item: TableObjectType) => item.number === 3,
    handleCheckedBoxes: (checkedItems: TableObjectType[]) => {
      showCheckedItemsToast(checkedItems)
    },
    nestedRowProps: {
      nestedData: nestedTableSampleData,
      getNestedData: () => undefined,
      showCaret: (dataItem: TableObjectType) =>
        !!nestedTableSampleData[dataItem?.id],
      showCheckboxes: true,
      initiallyExpandedRows: [1, 2],
    },
  },
  parameters: {
    docs: {
      source: {
        code: `
<StandardTable
  data={data}
  config={tableConfig}
  dataKey="id"
  hasCheckboxes
  nestedDataKey="id"
  disableCheckboxes={(item) => item.number === 3}
  handleCheckedBoxes={(checkedItems) => { /* handle selection */ }}
  nestedRowProps={{
    nestedData: nestedData,
    getNestedData: () => undefined,
    showCaret: (dataItem) => !!nestedData[dataItem?.id],
    showCheckboxes: true,
    initiallyExpandedRows: [1, 2],
  }}
/>`,
      },
    },
  },
}

export const parentRowCheckboxesOnly = {
  render: ({ ...args }) => <HandleNestedCheckboxTable {...args} />,
  args: {
    ...storyConfig,
    dataKey: 'id',
    hasCheckboxes: true,
    nestedDataKey: 'id',
    disableCheckboxes: (item: TableObjectType) => item.number === 3,
    handleCheckedBoxes: (checkedItems: TableObjectType[]) => {
      showCheckedItemsToast(checkedItems)
    },
    nestedRowProps: {
      nestedData: nestedTableSampleData,
      getNestedData: () => undefined,
      showCaret: (dataItem: TableObjectType) =>
        !!nestedTableSampleData[dataItem?.id],
      initiallyExpandedRows: [1, 2],
      showCheckboxes: false,
    },
  },
  parameters: {
    docs: {
      source: {
        code: `
<StandardTable
  data={data}
  config={tableConfig}
  dataKey="id"
  hasCheckboxes
  nestedDataKey="id"
  disableCheckboxes={(item) => item.number === 3}
  handleCheckedBoxes={(checkedItems) => { /* handle selection */ }}
  nestedRowProps={{
    nestedData: nestedData,
    getNestedData: () => undefined,
    showCaret: (dataItem) => !!nestedData[dataItem?.id],
    showCheckboxes: false,
    initiallyExpandedRows: [1, 2],
  }}
/>`,
      },
    },
  },
}

const HandleGroupNestedCheckboxTable = (args) => {
  const { data, sort, setSortBy } = useSortableData(args.data, {
    prop: 'name',
    flip: true,
  })
  const [checkedCount, setCheckedCount] = useState(0)

  const handleCheckedBoxes = (items: TableObjectType[]) => {
    // showCheckboxes: false — only count parent rows (no _nestedParentKey)
    setCheckedCount(
      items.filter(
        (item) =>
          (item as Record<string, unknown>)[NESTED_PARENT_KEY] === undefined,
      ).length,
    )
    args.handleCheckedBoxes?.(items)
  }

  return (
    <div>
      <div className='mb-2 text-sm font-semibold'>
        Parent rows selected:{' '}
        <span className='font-semibold'>{checkedCount}</span>
      </div>
      <StandardTable
        customHeight='500px'
        customWidth='auto'
        {...args}
        sort={setSortBy}
        sortBy={sort}
        data={data}
        handleCheckedBoxes={handleCheckedBoxes}
      />
    </div>
  )
}

export const groupWithNestedRowCheckboxes = {
  render: ({ ...args }) => <HandleGroupNestedCheckboxTable {...args} />,
  args: {
    ...storyConfig,
    data: standardTableSampleData.slice(0, 4),
    dataKey: 'id',
    tableId: 'group_nested_checkbox_table',
    hasCheckboxes: true,
    nestedDataKey: 'id',
    handleCheckedBoxes: (checkedItems: TableObjectType[]) => {
      showCheckedItemsToast(checkedItems)
    },
    showGroups: true,
    groups: [
      {
        groupHeader: 'Group A',
        check: (item: TableObjectType) => item.id <= 2,
        alwaysShowGroups: true,
        groupAccordion: {
          isCollapsed: false,
          groupKey: 'group-a',
        },
      },
      {
        groupHeader: 'Group B',
        check: (item: TableObjectType) => item.id > 2 && item.id <= 4,
        alwaysShowGroups: true,
        groupAccordion: {
          isCollapsed: false,
          groupKey: 'group-b',
        },
      },
    ],
    nestedRowProps: {
      nestedData: nestedTableSampleData,
      getNestedData: () => undefined,
      showCaret: (dataItem: TableObjectType) =>
        !!nestedTableSampleData[dataItem?.id],
      showCheckboxes: false,
      initiallyExpandedRows: [1, 2],
    },
  },
  parameters: {
    docs: {
      source: {
        code: `
<StandardTable
  data={data}
  config={tableConfig}
  dataKey="id"
  hasCheckboxes
  nestedDataKey="id"
  showGroups
  handleCheckedBoxes={(checkedItems) => { /* handle selection */ }}
  groups={[
    {
      groupHeader: 'Group A',
      check: (item) => item.id <= 2,
      alwaysShowGroups: true,
      groupAccordion: { isCollapsed: false, groupKey: 'group-a' },
    },
    {
      groupHeader: 'Group B',
      check: (item) => item.id > 2 && item.id <= 4,
      alwaysShowGroups: true,
      groupAccordion: { isCollapsed: false, groupKey: 'group-b' },
    },
  ]}
  nestedRowProps={{
    nestedData: nestedData,
    getNestedData: () => undefined,
    showCaret: (dataItem) => !!nestedData[dataItem?.id],
    showCheckboxes: false,
    initiallyExpandedRows: [1, 2],
  }}
/>`,
      },
    },
  },
}
groupWithNestedRowCheckboxes.storyName = 'Groups + Nested Row Checkboxes'
