import { useState, useRef, useEffect, ReactNode } from 'react'
import { createPortal } from 'react-dom'
import { SlidersHorizontal, X, ChevronDown, Calendar, HardDrive, Search } from 'lucide-react'

export interface FilterSection {
  id: string
  label: string
  type: 'select' | 'radio' | 'checkbox' | 'multiselect'
  options: { value: string; label: string }[]
  value: string | string[]
  onChange: (value: string | string[]) => void
}

function MultiSelectFilter({ section }: { section: FilterSection }) {
  const [search, setSearch] = useState('')
  const selected = Array.isArray(section.value) ? section.value : []
  const filtered = section.options.filter(opt =>
    opt.label.toLowerCase().includes(search.toLowerCase())
  )

  const toggle = (value: string) => {
    const newSelected = selected.includes(value)
      ? selected.filter(v => v !== value)
      : [...selected, value]
    section.onChange(newSelected)
  }

  return (
    <div className="space-y-2">
      <div className="relative">
        <Search className="absolute left-2.5 top-1/2 -translate-y-1/2 w-3.5 h-3.5 text-slate-400" />
        <input
          type="text"
          value={search}
          onChange={e => setSearch(e.target.value)}
          placeholder="Search..."
          className="w-full pl-8 pr-3 py-1.5 rounded-lg border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm"
        />
      </div>
      <div className="max-h-[320px] overflow-y-auto space-y-0.5">
        {filtered.map(opt => (
          <label
            key={opt.value}
            className="flex items-center gap-2 px-2 py-1.5 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-700/50 cursor-pointer"
          >
            <input
              type="checkbox"
              checked={selected.includes(opt.value)}
              onChange={() => toggle(opt.value)}
              className="w-4 h-4 rounded text-blue-500 border-slate-300 focus:ring-blue-500"
            />
            <span className="text-sm text-slate-700 dark:text-slate-300 truncate">{opt.label}</span>
          </label>
        ))}
        {filtered.length === 0 && (
          <p className="text-xs text-slate-400 px-2 py-1">No matches</p>
        )}
      </div>
      {selected.length > 0 && (
        <button
          onClick={() => section.onChange([])}
          className="text-xs text-blue-600 dark:text-blue-400 hover:underline"
        >
          Clear ({selected.length})
        </button>
      )}
    </div>
  )
}

interface FilterPopoverProps {
  sections: FilterSection[]
  activeCount: number
  onClear: () => void
}

export function FilterPopover({ sections, activeCount, onClear }: FilterPopoverProps) {
  const [isOpen, setIsOpen] = useState(false)
  const buttonRef = useRef<HTMLButtonElement>(null)
  const popoverRef = useRef<HTMLDivElement>(null)
  const [popoverPosition, setPopoverPosition] = useState({ top: 0, left: 0 })

  // Update popover position when opened
  useEffect(() => {
    if (isOpen && buttonRef.current) {
      const rect = buttonRef.current.getBoundingClientRect()
      const viewportHeight = window.innerHeight
      const popoverMaxHeight = viewportHeight * 0.8 // 80vh
      const spaceBelow = viewportHeight - rect.bottom - 16 // 16px margin from bottom

      // If not enough space below, position above or limit to available space
      let top = rect.bottom + 8
      if (spaceBelow < 300) {
        // Position above the button if very limited space below
        top = Math.max(8, rect.top - Math.min(popoverMaxHeight, rect.top - 16))
      }

      setPopoverPosition({
        top,
        left: rect.right - 320, // 320px is w-80, align right edge
      })
    }
  }, [isOpen])

  // Close on click outside
  useEffect(() => {
    function handleClickOutside(event: MouseEvent) {
      const target = event.target as Node
      if (
        popoverRef.current && !popoverRef.current.contains(target) &&
        buttonRef.current && !buttonRef.current.contains(target)
      ) {
        setIsOpen(false)
      }
    }
    if (isOpen) {
      document.addEventListener('mousedown', handleClickOutside)
      return () => document.removeEventListener('mousedown', handleClickOutside)
    }
  }, [isOpen])

  // Close on escape
  useEffect(() => {
    function handleEscape(event: KeyboardEvent) {
      if (event.key === 'Escape') setIsOpen(false)
    }
    if (isOpen) {
      document.addEventListener('keydown', handleEscape)
      return () => document.removeEventListener('keydown', handleEscape)
    }
  }, [isOpen])

  // Close on scroll to prevent misalignment (but not when scrolling inside the popover)
  useEffect(() => {
    if (isOpen) {
      const handleScroll = (e: Event) => {
        if (popoverRef.current && popoverRef.current.contains(e.target as Node)) return
        setIsOpen(false)
      }
      window.addEventListener('scroll', handleScroll, true)
      return () => window.removeEventListener('scroll', handleScroll, true)
    }
  }, [isOpen])

  return (
    <div className="relative">
      <button
        ref={buttonRef}
        onClick={() => setIsOpen(!isOpen)}
        className={`flex items-center gap-2 px-4 py-2 rounded-lg border transition-colors ${
          activeCount > 0
            ? 'border-blue-500 bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-300'
            : 'border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-800 text-slate-700 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-slate-700'
        }`}
      >
        <SlidersHorizontal className="w-4 h-4" />
        <span>Filters</span>
        {activeCount > 0 && (
          <span className="flex items-center justify-center w-5 h-5 text-xs font-medium bg-blue-500 text-white rounded-full">
            {activeCount}
          </span>
        )}
        <ChevronDown className={`w-4 h-4 transition-transform ${isOpen ? 'rotate-180' : ''}`} />
      </button>

      {isOpen && createPortal(
        <div
          ref={popoverRef}
          className="fixed w-80 bg-white dark:bg-slate-800 rounded-xl border border-slate-200 dark:border-slate-700 shadow-xl overflow-hidden"
          style={{
            top: popoverPosition.top,
            left: Math.max(8, popoverPosition.left), // Ensure at least 8px from left edge
            zIndex: 9999,
          }}
        >
          {/* Header */}
          <div className="flex items-center justify-between px-4 py-3 border-b border-slate-200 dark:border-slate-700 bg-slate-50 dark:bg-slate-900/50">
            <span className="font-medium text-slate-900 dark:text-slate-100">Filters</span>
            <div className="flex items-center gap-2">
              {activeCount > 0 && (
                <button
                  onClick={onClear}
                  className="text-xs text-blue-600 dark:text-blue-400 hover:underline"
                >
                  Clear all
                </button>
              )}
              <button
                onClick={() => setIsOpen(false)}
                className="p-1 rounded hover:bg-slate-200 dark:hover:bg-slate-700"
              >
                <X className="w-4 h-4 text-slate-500" />
              </button>
            </div>
          </div>

          {/* Filter Sections */}
          <div className="max-h-[80vh] overflow-y-auto">
            {sections.map((section, index) => (
              <div
                key={section.id}
                className={`px-4 py-3 ${
                  index < sections.length - 1 ? 'border-b border-slate-100 dark:border-slate-700/50' : ''
                }`}
              >
                <label className="block text-xs font-medium text-slate-500 dark:text-slate-400 uppercase tracking-wider mb-2">
                  {section.label}
                </label>

                {section.type === 'select' && (
                  <select
                    value={section.value as string}
                    onChange={(e) => section.onChange(e.target.value)}
                    className="w-full px-3 py-2 rounded-lg border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm"
                  >
                    {section.options.map((opt) => (
                      <option key={opt.value} value={opt.value}>
                        {opt.label}
                      </option>
                    ))}
                  </select>
                )}

                {section.type === 'radio' && (
                  <div className="space-y-1">
                    {section.options.map((opt) => (
                      <label
                        key={opt.value}
                        className="flex items-center gap-2 px-2 py-1.5 rounded-lg hover:bg-slate-100 dark:hover:bg-slate-700/50 cursor-pointer"
                      >
                        <input
                          type="radio"
                          name={section.id}
                          value={opt.value}
                          checked={section.value === opt.value}
                          onChange={(e) => section.onChange(e.target.value)}
                          className="w-4 h-4 text-blue-500 border-slate-300 focus:ring-blue-500"
                        />
                        <span className="text-sm text-slate-700 dark:text-slate-300">{opt.label}</span>
                      </label>
                    ))}
                  </div>
                )}

                {section.type === 'multiselect' && (
                  <MultiSelectFilter section={section} />
                )}
              </div>
            ))}
          </div>
        </div>,
        document.body
      )}
    </div>
  )
}

export interface ActiveFilter {
  id: string
  label: string
  value: string
  displayValue: string
  onRemove: () => void
}

export interface AdvancedFilters {
  dateFrom?: { value: string; onChange: (v: string) => void; label?: string }
  dateTo?: { value: string; onChange: (v: string) => void; label?: string }
  sizeMin?: { value: string; onChange: (v: string) => void; placeholder?: string }
  sizeMax?: { value: string; onChange: (v: string) => void; placeholder?: string }
}

interface FilterBarProps {
  searchValue: string
  onSearchChange: (value: string) => void
  searchPlaceholder?: string
  filterSections: FilterSection[]
  activeFilters: ActiveFilter[]
  onClearAll: () => void
  totalCount?: number
  countLabel?: string
  advancedFilters?: AdvancedFilters
  children?: ReactNode
}

export function FilterBar({
  searchValue,
  onSearchChange,
  searchPlaceholder = 'Search...',
  filterSections,
  activeFilters,
  onClearAll,
  totalCount,
  countLabel = 'items',
  advancedFilters,
  children,
}: FilterBarProps) {
  const [showAdvanced, setShowAdvanced] = useState(false)
  const hasAdvanced = advancedFilters && (
    advancedFilters.dateFrom || advancedFilters.dateTo ||
    advancedFilters.sizeMin || advancedFilters.sizeMax
  )
  const hasActiveAdvanced = advancedFilters && (
    advancedFilters.dateFrom?.value || advancedFilters.dateTo?.value ||
    advancedFilters.sizeMin?.value || advancedFilters.sizeMax?.value
  )

  return (
    <div className="space-y-3">
      {/* Search + Filter Button Row */}
      <div className="flex items-center gap-3">
        <div className="flex-1 relative">
          <input
            type="text"
            value={searchValue}
            onChange={(e) => onSearchChange(e.target.value)}
            placeholder={searchPlaceholder}
            className="w-full px-4 py-2 pl-10 rounded-lg border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-800 text-slate-900 dark:text-slate-100 focus:outline-none focus:ring-2 focus:ring-blue-500"
          />
          <svg
            className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-slate-400"
            fill="none"
            stroke="currentColor"
            viewBox="0 0 24 24"
          >
            <path
              strokeLinecap="round"
              strokeLinejoin="round"
              strokeWidth={2}
              d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"
            />
          </svg>
          {searchValue && (
            <button
              onClick={() => onSearchChange('')}
              className="absolute right-3 top-1/2 -translate-y-1/2 p-0.5 rounded hover:bg-slate-200 dark:hover:bg-slate-700"
            >
              <X className="w-4 h-4 text-slate-400" />
            </button>
          )}
        </div>
        {hasAdvanced && (
          <button
            onClick={() => setShowAdvanced(!showAdvanced)}
            className={`flex items-center gap-2 px-4 py-2 rounded-lg border transition-colors ${
              showAdvanced || hasActiveAdvanced
                ? 'border-blue-500 bg-blue-50 dark:bg-blue-900/20 text-blue-700 dark:text-blue-300'
                : 'border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-800 text-slate-700 dark:text-slate-300 hover:bg-slate-50 dark:hover:bg-slate-700'
            }`}
          >
            <SlidersHorizontal className="w-4 h-4" />
            <span className="hidden sm:inline">Advanced</span>
          </button>
        )}
        <FilterPopover
          sections={filterSections}
          activeCount={activeFilters.length}
          onClear={onClearAll}
        />
      </div>

      {/* Advanced Filters Panel */}
      {hasAdvanced && showAdvanced && (
        <div className="grid grid-cols-2 sm:grid-cols-4 gap-3 p-3 bg-slate-50 dark:bg-slate-800/50 rounded-lg border border-slate-200 dark:border-slate-700">
          {advancedFilters.dateFrom && (
            <div>
              <label className="flex items-center gap-1 text-xs font-medium text-slate-600 dark:text-slate-400 mb-1">
                <Calendar className="w-3 h-3" />
                {advancedFilters.dateFrom.label || 'From'}
              </label>
              <input
                type="date"
                value={advancedFilters.dateFrom.value}
                onChange={(e) => advancedFilters.dateFrom!.onChange(e.target.value)}
                className="w-full px-2 py-1.5 text-sm rounded-lg border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 focus:outline-none focus:ring-2 focus:ring-blue-500"
              />
            </div>
          )}
          {advancedFilters.dateTo && (
            <div>
              <label className="flex items-center gap-1 text-xs font-medium text-slate-600 dark:text-slate-400 mb-1">
                <Calendar className="w-3 h-3" />
                {advancedFilters.dateTo.label || 'To'}
              </label>
              <input
                type="date"
                value={advancedFilters.dateTo.value}
                onChange={(e) => advancedFilters.dateTo!.onChange(e.target.value)}
                className="w-full px-2 py-1.5 text-sm rounded-lg border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 focus:outline-none focus:ring-2 focus:ring-blue-500"
              />
            </div>
          )}
          {advancedFilters.sizeMin && (
            <div>
              <label className="flex items-center gap-1 text-xs font-medium text-slate-600 dark:text-slate-400 mb-1">
                <HardDrive className="w-3 h-3" />
                Min Size
              </label>
              <input
                type="number"
                value={advancedFilters.sizeMin.value}
                onChange={(e) => advancedFilters.sizeMin!.onChange(e.target.value)}
                placeholder={advancedFilters.sizeMin.placeholder || '1MB = 1048576'}
                className="w-full px-2 py-1.5 text-sm rounded-lg border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-blue-500"
              />
            </div>
          )}
          {advancedFilters.sizeMax && (
            <div>
              <label className="flex items-center gap-1 text-xs font-medium text-slate-600 dark:text-slate-400 mb-1">
                <HardDrive className="w-3 h-3" />
                Max Size
              </label>
              <input
                type="number"
                value={advancedFilters.sizeMax.value}
                onChange={(e) => advancedFilters.sizeMax!.onChange(e.target.value)}
                placeholder={advancedFilters.sizeMax.placeholder || '10MB = 10485760'}
                className="w-full px-2 py-1.5 text-sm rounded-lg border border-slate-300 dark:border-slate-600 bg-white dark:bg-slate-700 text-slate-900 dark:text-slate-100 placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-blue-500"
              />
            </div>
          )}
        </div>
      )}

      {/* Custom children slot */}
      {children}

      {/* Active Filters + Count Row */}
      {(activeFilters.length > 0 || totalCount !== undefined) && (
        <div className="flex items-center justify-between">
          <div className="flex items-center gap-2 flex-wrap">
            {activeFilters.map((filter) => (
              <span
                key={filter.id}
                className="inline-flex items-center gap-1 px-2 py-1 text-xs bg-blue-100 dark:bg-blue-900/30 text-blue-700 dark:text-blue-300 rounded-md"
              >
                {filter.label}: {filter.displayValue}
                <button
                  onClick={filter.onRemove}
                  className="p-0.5 rounded hover:bg-blue-200 dark:hover:bg-blue-800"
                >
                  <X className="w-3 h-3" />
                </button>
              </span>
            ))}
            {activeFilters.length > 0 && (
              <button
                onClick={onClearAll}
                className="text-xs text-blue-600 dark:text-blue-400 hover:underline ml-1"
              >
                Clear all
              </button>
            )}
          </div>
          {totalCount !== undefined && (
            <span className="text-sm text-slate-500 dark:text-slate-400">
              {totalCount.toLocaleString()} {countLabel}
            </span>
          )}
        </div>
      )}
    </div>
  )
}
