import type { Meta, StoryObj } from '@storybook/react-vite'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { useState } from 'react'

import { FilterConfig, FilterFieldName, FilterOption, FilterState, FilterValue } from '@types'

import { Popover, PopoverContent, PopoverTrigger, Button } from '@postxl/ui-components'

import { TableFilter } from './table-filter'

const meta = {
  title: 'Admin/TableFilter',
  component: TableFilter,
  tags: ['autodocs'],
  parameters: {
    layout: 'centered',
  },
  decorators: [
    (Story) => {
      const queryClient = new QueryClient({
        defaultOptions: {
          queries: {
            retry: false,
          },
        },
      })
      return (
        <QueryClientProvider client={queryClient}>
          <Story />
        </QueryClientProvider>
      )
    },
  ],
} satisfies Meta<typeof TableFilter>
export default meta

type Story = StoryObj<typeof meta>

// Mock data for different filter types
const stringOptions = [
  { value: '', label: 'Empty', hasMatches: true },
  { value: 'apple', label: 'Apple', hasMatches: true },
  { value: 'banana', label: 'Banana', hasMatches: true },
  { value: 'cherry', label: 'Cherry', hasMatches: true },
  { value: 'date', label: 'Date', hasMatches: true },
  { value: 'elderberry', label: 'Elderberry', hasMatches: true },
]

const numberOptions = [
  { value: '10', label: '10', hasMatches: true },
  { value: '20', label: '20', hasMatches: true },
  { value: '30', label: '30', hasMatches: true },
  { value: '40', label: '40', hasMatches: true },
  { value: '50', label: '50', hasMatches: true },
]

const booleanOptions = [
  { value: 'true', label: 'Yes', hasMatches: true },
  { value: 'false', label: 'No', hasMatches: true },
]

const dateOptions = [
  { value: '2024-01-15', label: '2024-01-15', hasMatches: true },
  { value: '2024-02-20', label: '2024-02-20', hasMatches: true },
  { value: '2024-03-25', label: '2024-03-25', hasMatches: true },
]

const hierarchyOptions: FilterOption[] = [
  {
    value: 'europe',
    label: 'Europe',
    hasMatches: true,
    children: [
      {
        value: 'germany',
        label: 'Germany',
        hasMatches: true,
        children: [
          { value: 'berlin', label: 'Berlin', hasMatches: true },
          { value: 'munich', label: 'Munich', hasMatches: true },
          { value: 'hamburg', label: 'Hamburg', hasMatches: true },
        ],
      },
      {
        value: 'france',
        label: 'France',
        hasMatches: true,
        children: [
          { value: 'paris', label: 'Paris', hasMatches: true },
          { value: 'lyon', label: 'Lyon', hasMatches: true },
        ],
      },
      {
        value: 'spain',
        label: 'Spain',
        hasMatches: true,
        children: [
          { value: 'madrid', label: 'Madrid', hasMatches: true },
          { value: 'barcelona', label: 'Barcelona', hasMatches: true },
        ],
      },
    ],
  },
  {
    value: 'asia',
    label: 'Asia',
    hasMatches: true,
    children: [
      {
        value: 'japan',
        label: 'Japan',
        hasMatches: true,
        children: [
          { value: 'tokyo', label: 'Tokyo', hasMatches: true },
          { value: 'osaka', label: 'Osaka', hasMatches: true },
        ],
      },
      { value: 'singapore', label: 'Singapore', hasMatches: true },
    ],
  },
]

// Mock filter configs
type MockFilterState = FilterState & {
  stringField?: { values?: string[] }
  numberField?: { values?: number[]; min?: number; max?: number }
  booleanField?: boolean[]
  dateField?: { values?: string[]; start?: string; end?: string }
  hierarchyField?: { values?: string[] }
}

const stringFilterConfig: FilterConfig<FilterFieldName, MockFilterState> = {
  stringField: {
    filterKey: 'stringField',
    valueType: 'string',
    kind: 'scalar',
  },
}

const numberFilterConfig: FilterConfig<FilterFieldName, MockFilterState> = {
  numberField: {
    filterKey: 'numberField',
    valueType: 'number',
    kind: 'scalar',
  },
}

const booleanFilterConfig: FilterConfig<FilterFieldName, MockFilterState> = {
  booleanField: {
    filterKey: 'booleanField',
    valueType: 'boolean',
    kind: 'scalar',
  },
}

const dateFilterConfig: FilterConfig<FilterFieldName, MockFilterState> = {
  dateField: {
    filterKey: 'dateField',
    valueType: 'date',
    kind: 'scalar',
  },
}

const hierarchyFilterConfig: FilterConfig<FilterFieldName, MockFilterState> = {
  hierarchyField: {
    filterKey: 'hierarchyField',
    valueType: 'hierarchy',
    kind: 'hierarchy',
  },
}

// Mock getFilterOptions function
const createMockGetFilterOptions =
  (options: FilterOption[]) => (_args: { field: FilterFieldName; filters: MockFilterState }) => ({
    queryKey: ['mockFilterOptions'],
    queryFn: async () => options,
  })

// Wrapper component for stories
const FilterWrapper = ({
  field,
  config,
  options,
  initialFilters = {},
}: {
  field: FilterFieldName
  config: FilterConfig<FilterFieldName, MockFilterState>
  options: FilterOption[]
  initialFilters?: MockFilterState
}) => {
  const [filters, setFilters] = useState<MockFilterState>(initialFilters)
  const [open, setOpen] = useState(false)

  const handleChange = (val: FilterValue) => {
    const fieldConfig = config[field]
    if (fieldConfig) {
      setFilters((prev) => ({
        ...prev,
        [fieldConfig.filterKey]: val,
      }))
    }
  }

  return (
    <div className="flex flex-col gap-4 items-center">
      <Popover open={open} onOpenChange={setOpen}>
        <PopoverTrigger asChild>
          <Button variant="outline">{open ? 'Filter Open' : 'Open Filter'}</Button>
        </PopoverTrigger>
        <PopoverContent className="w-[280px] p-0">
          <TableFilter
            open={open}
            field={field}
            filters={filters}
            onChange={handleChange}
            config={config}
            getFilterOptions={createMockGetFilterOptions(options)}
          />
        </PopoverContent>
      </Popover>

      <div className="text-xs bg-muted p-2 rounded">
        <pre>{JSON.stringify(filters, null, 2)}</pre>
      </div>
    </div>
  )
}

export const StringFilter: Story = {
  args: {} as any,
  render: () => <FilterWrapper field="stringField" config={stringFilterConfig} options={stringOptions} />,
}

export const NumberFilter: Story = {
  args: {} as any,
  render: () => <FilterWrapper field="numberField" config={numberFilterConfig} options={numberOptions} />,
}

export const BooleanFilter: Story = {
  args: {} as any,
  render: () => <FilterWrapper field="booleanField" config={booleanFilterConfig} options={booleanOptions} />,
}

export const DateFilter: Story = {
  args: {} as any,
  render: () => <FilterWrapper field="dateField" config={dateFilterConfig} options={dateOptions} />,
}

export const HierarchyFilter: Story = {
  args: {} as any,
  render: () => <FilterWrapper field="hierarchyField" config={hierarchyFilterConfig} options={hierarchyOptions} />,
}

export const WithOutMatchesOnCrossFiltering: Story = {
  args: {} as any,
  render: () => (
    <FilterWrapper
      field="stringField"
      config={stringFilterConfig}
      options={stringOptions
        .map((opt) => (opt.value === 'banana' || opt.value === 'elderberry' ? { ...opt, hasMatches: false } : opt))
        .sort((a, b) => (a.hasMatches && !b.hasMatches ? -1 : !a.hasMatches && b.hasMatches ? 1 : 0))} // Simulate "banana" and "elderberry" having no matches due to cross-filtering
    />
  ),
}
