"use client"

import React, { useState, useMemo } from 'react'
import { Column, Table } from '@tanstack/react-table'
import { X, Filter, Trash2, Plus } from 'lucide-react'
import { Button } from '../ui/button'
import { Input } from '../ui/input'
import { Label } from '../ui/label'
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '../ui/select'
import { Switch } from '../ui/switch'
import { Separator } from '../ui/separator'
import { cn } from '../../lib/utils'
import { motion, AnimatePresence } from 'framer-motion'

export interface FilterCondition {
  column: string
  operator: FilterOperator
  value: any
}

export type FilterOperator = 
  | 'equals' 
  | 'notEquals' 
  | 'contains' 
  | 'notContains' 
  | 'startsWith' 
  | 'endsWith'
  | 'greaterThan'
  | 'lessThan'
  | 'greaterThanOrEqual'
  | 'lessThanOrEqual'
  | 'between'
  | 'in'
  | 'notIn'
  | 'isNull'
  | 'isNotNull'

export interface DataTableFilterDrawerProps<TData> {
  table: Table<TData>
  open: boolean
  onOpenChange: (open: boolean) => void
  position?: 'left' | 'right'
  width?: string
  filters?: FilterCondition[]
  onFiltersChange?: (filters: FilterCondition[]) => void
  customFilters?: React.ReactNode
  matchAll?: boolean
  onMatchAllChange?: (matchAll: boolean) => void
}

const operatorLabels: Record<FilterOperator, string> = {
  equals: 'Equals',
  notEquals: 'Not equals',
  contains: 'Contains',
  notContains: 'Not contains',
  startsWith: 'Starts with',
  endsWith: 'Ends with',
  greaterThan: 'Greater than',
  lessThan: 'Less than',
  greaterThanOrEqual: 'Greater than or equal',
  lessThanOrEqual: 'Less than or equal',
  between: 'Between',
  in: 'In',
  notIn: 'Not in',
  isNull: 'Is empty',
  isNotNull: 'Is not empty',
}

function getOperatorsForColumnType(columnType?: string): FilterOperator[] {
  switch (columnType) {
    case 'number':
      return ['equals', 'notEquals', 'greaterThan', 'lessThan', 'greaterThanOrEqual', 'lessThanOrEqual', 'between', 'isNull', 'isNotNull']
    case 'date':
      return ['equals', 'notEquals', 'greaterThan', 'lessThan', 'greaterThanOrEqual', 'lessThanOrEqual', 'between', 'isNull', 'isNotNull']
    case 'boolean':
      return ['equals', 'notEquals', 'isNull', 'isNotNull']
    case 'select':
      return ['equals', 'notEquals', 'in', 'notIn', 'isNull', 'isNotNull']
    default: // string
      return ['equals', 'notEquals', 'contains', 'notContains', 'startsWith', 'endsWith', 'isNull', 'isNotNull']
  }
}

export function DataTableFilterDrawer<TData>({
  table,
  open,
  onOpenChange,
  position = 'right',
  width = '400px',
  filters: externalFilters,
  onFiltersChange,
  customFilters,
  matchAll: externalMatchAll,
  onMatchAllChange,
}: DataTableFilterDrawerProps<TData>) {
  const [internalFilters, setInternalFilters] = useState<FilterCondition[]>([])
  const [internalMatchAll, setInternalMatchAll] = useState(true)

  const filters = externalFilters || internalFilters
  const setFilters = onFiltersChange || setInternalFilters
  const matchAll = externalMatchAll !== undefined ? externalMatchAll : internalMatchAll
  const setMatchAll = onMatchAllChange || setInternalMatchAll

  // Get filterable columns
  const filterableColumns = useMemo(() => {
    return table.getAllColumns().filter(column => {
      // Skip special columns
      if (column.id === 'select' || column.id === 'actions' || column.id === 'expander') {
        return false
      }
      // Only include columns that can be filtered
      return column.getCanFilter()
    })
  }, [table])

  const addFilter = () => {
    const firstColumn = filterableColumns[0]
    if (!firstColumn) return

    const newFilter: FilterCondition = {
      column: firstColumn.id,
      operator: 'contains',
      value: '',
    }
    setFilters([...filters, newFilter])
  }

  const updateFilter = (index: number, updates: Partial<FilterCondition>) => {
    const newFilters = [...filters]
    newFilters[index] = { ...newFilters[index], ...updates }
    setFilters(newFilters)
  }

  const removeFilter = (index: number) => {
    setFilters(filters.filter((_, i) => i !== index))
  }

  const clearAllFilters = () => {
    setFilters([])
    table.resetColumnFilters()
  }

  const applyFilters = () => {
    // Create a custom filter function that handles all our conditions
    const customFilterFn = (row: any, columnId: string, filterValue: any) => {
      // Find the filter condition for this column
      const filterCondition = filters.find(f => f.column === columnId)
      if (!filterCondition) return true

      const cellValue = row.getValue(columnId)
      const filterVal = filterCondition.value

      switch (filterCondition.operator) {
        case 'equals':
          return cellValue === filterVal
        case 'notEquals':
          return cellValue !== filterVal
        case 'contains':
          return String(cellValue).toLowerCase().includes(String(filterVal).toLowerCase())
        case 'notContains':
          return !String(cellValue).toLowerCase().includes(String(filterVal).toLowerCase())
        case 'startsWith':
          return String(cellValue).toLowerCase().startsWith(String(filterVal).toLowerCase())
        case 'endsWith':
          return String(cellValue).toLowerCase().endsWith(String(filterVal).toLowerCase())
        case 'greaterThan':
          return Number(cellValue) > Number(filterVal)
        case 'lessThan':
          return Number(cellValue) < Number(filterVal)
        case 'greaterThanOrEqual':
          return Number(cellValue) >= Number(filterVal)
        case 'lessThanOrEqual':
          return Number(cellValue) <= Number(filterVal)
        case 'isNull':
          return cellValue == null || cellValue === ''
        case 'isNotNull':
          return cellValue != null && cellValue !== ''
        default:
          return true
      }
    }

    // Reset all column filters first
    table.resetColumnFilters()

    // Apply filter for each column that has a filter condition
    const columnsWithFilters = [...new Set(filters.map(f => f.column))]
    
    columnsWithFilters.forEach(columnId => {
      const column = table.getColumn(columnId)
      if (!column) return
      
      // Set filter with custom function
      column.setFilterValue({ custom: true, filters, matchAll })
    })

    // If no filters, ensure all filters are cleared
    if (filters.length === 0) {
      table.resetColumnFilters()
    }

    onOpenChange(false)
  }

  return (
    <>
      {/* Backdrop */}
      <AnimatePresence>
        {open && (
          <motion.div
            initial={{ opacity: 0 }}
            animate={{ opacity: 1 }}
            exit={{ opacity: 0 }}
            className="fixed inset-0 bg-black/20 z-40"
            onClick={() => onOpenChange(false)}
          />
        )}
      </AnimatePresence>

      {/* Drawer */}
      <AnimatePresence>
        {open && (
          <motion.div
            initial={{ x: position === 'right' ? '100%' : '-100%' }}
            animate={{ x: 0 }}
            exit={{ x: position === 'right' ? '100%' : '-100%' }}
            transition={{ type: 'spring', damping: 30, stiffness: 300 }}
            className={cn(
              "fixed top-0 bottom-0 z-50 bg-background border-l shadow-xl",
              position === 'right' ? 'right-0' : 'left-0'
            )}
            style={{ width }}
          >
            <div className="flex flex-col h-full">
              {/* Header */}
              <div className="flex items-center justify-between p-4 border-b">
                <div className="flex items-center gap-2">
                  <Filter className="h-5 w-5" />
                  <h2 className="text-lg font-semibold">Filters</h2>
                  {filters.length > 0 && (
                    <span className="text-sm text-muted-foreground">
                      ({filters.length} active)
                    </span>
                  )}
                </div>
                <Button
                  variant="ghost"
                  size="icon"
                  onClick={() => onOpenChange(false)}
                >
                  <X className="h-4 w-4" />
                </Button>
              </div>

              {/* Content */}
              <div className="flex-1 overflow-y-auto p-4">
                {/* Match mode */}
                <div className="mb-6">
                  <Label className="text-sm font-medium mb-2 block">
                    Match conditions
                  </Label>
                  <div className="flex items-center gap-2">
                    <Button
                      variant={matchAll ? 'primary' : 'outline'}
                      size="sm"
                      onClick={() => setMatchAll(true)}
                      className="flex-1"
                    >
                      Match all
                    </Button>
                    <Button
                      variant={!matchAll ? 'primary' : 'outline'}
                      size="sm"
                      onClick={() => setMatchAll(false)}
                      className="flex-1"
                    >
                      Match any
                    </Button>
                  </div>
                </div>

                <Separator className="mb-6" />

                {/* Custom filters */}
                {customFilters && (
                  <>
                    {customFilters}
                    <Separator className="my-6" />
                  </>
                )}

                {/* Filter conditions */}
                <div className="space-y-4">
                  {filters.map((filter, index) => (
                    <FilterConditionRow
                      key={index}
                      filter={filter}
                      columns={filterableColumns}
                      onUpdate={(updates) => updateFilter(index, updates)}
                      onRemove={() => removeFilter(index)}
                    />
                  ))}
                </div>

                {/* Add filter button */}
                <Button
                  variant="outline"
                  size="sm"
                  onClick={addFilter}
                  className="w-full mt-4"
                >
                  <Plus className="h-4 w-4 mr-2" />
                  Add filter
                </Button>
              </div>

              {/* Footer */}
              <div className="p-4 border-t space-y-2">
                <div className="flex gap-2">
                  <Button
                    variant="outline"
                    onClick={clearAllFilters}
                    disabled={filters.length === 0}
                    className="flex-1"
                  >
                    <Trash2 className="h-4 w-4 mr-2" />
                    Clear all
                  </Button>
                  <Button onClick={applyFilters} className="flex-1">
                    Apply filters
                  </Button>
                </div>
              </div>
            </div>
          </motion.div>
        )}
      </AnimatePresence>
    </>
  )
}

interface FilterConditionRowProps<TData> {
  filter: FilterCondition
  columns: Column<TData, any>[]
  onUpdate: (updates: Partial<FilterCondition>) => void
  onRemove: () => void
}

function FilterConditionRow<TData>({
  filter,
  columns,
  onUpdate,
  onRemove,
}: FilterConditionRowProps<TData>) {
  const selectedColumn = columns.find(col => col.id === filter.column)
  const columnDef = selectedColumn?.columnDef as any
  const columnType = columnDef?.meta?.filterType || 'string'
  const availableOperators = getOperatorsForColumnType(columnType)

  const needsValue = filter.operator !== 'isNull' && filter.operator !== 'isNotNull'

  return (
    <div className="space-y-2 p-3 border rounded-lg bg-muted/30">
      {/* Column selector */}
      <div className="flex items-center gap-2">
        <Select
          value={filter.column}
          onValueChange={(value) => onUpdate({ column: value })}
        >
          <SelectTrigger className="flex-1">
            <SelectValue />
          </SelectTrigger>
          <SelectContent>
            {columns.map(column => {
              const header = column.columnDef.header
              const label = typeof header === 'function' ? column.id : header || column.id
              
              return (
                <SelectItem key={column.id} value={column.id}>
                  {label}
                </SelectItem>
              )
            })}
          </SelectContent>
        </Select>

        <Button
          variant="ghost"
          size="icon"
          onClick={onRemove}
          className="h-8 w-8"
        >
          <X className="h-4 w-4" />
        </Button>
      </div>

      {/* Operator selector */}
      <Select
        value={filter.operator}
        onValueChange={(value) => onUpdate({ operator: value as FilterOperator })}
      >
        <SelectTrigger>
          <SelectValue />
        </SelectTrigger>
        <SelectContent>
          {availableOperators.map(operator => (
            <SelectItem key={operator} value={operator}>
              {operatorLabels[operator]}
            </SelectItem>
          ))}
        </SelectContent>
      </Select>

      {/* Value input */}
      {needsValue && (
        <div>
          {columnType === 'boolean' ? (
            <Select
              value={String(filter.value)}
              onValueChange={(value) => onUpdate({ value: value === 'true' })}
            >
              <SelectTrigger>
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="true">True</SelectItem>
                <SelectItem value="false">False</SelectItem>
              </SelectContent>
            </Select>
          ) : columnType === 'number' ? (
            <Input
              type="number"
              value={filter.value || ''}
              onChange={(e) => onUpdate({ value: e.target.value })}
              placeholder="Enter value..."
            />
          ) : (
            <Input
              value={filter.value || ''}
              onChange={(e) => onUpdate({ value: e.target.value })}
              placeholder="Enter value..."
            />
          )}
        </div>
      )}
    </div>
  )
}