import { useState, useRef, useEffect, createContext, useContext } from 'react';
import { ChevronDown, X } from 'lucide-react';
import { cn } from '@/lib/utils';
import { useDarkMode } from '@/hooks/useDarkMode';
import {
  CategoryCounts,
  CategoryColorTheme,
  formatCategoryName,
  getCategoryCount,
  getCategoryColorTheme,
} from '@/lib/skills-utils';

interface FilterDropdownProps {
  categories: string[];
  categoryCounts: CategoryCounts;
  selectedCategory: string;
  filteredCount: number;
  onSelect: (category: string) => void;
}

const CategoryThemeContext = createContext<CategoryColorTheme | null>(null);

function useCategoryTheme(categoryKey: string): CategoryColorTheme {
  const isDark = useDarkMode();
  return getCategoryColorTheme(categoryKey, isDark);
}

export function FilterDropdown({
  categories,
  categoryCounts,
  selectedCategory,
  filteredCount,
  onSelect,
}: FilterDropdownProps) {
  const [isOpen, setIsOpen] = useState(false);
  const rootRef = useRef<HTMLDivElement>(null);
  const isDark = useDarkMode();
  const triggerTheme = getCategoryColorTheme(selectedCategory, isDark);

  useEffect(() => {
    function handleClickOutside(event: MouseEvent) {
      if (rootRef.current && !rootRef.current.contains(event.target as Node)) {
        setIsOpen(false);
      }
    }
    document.addEventListener('mousedown', handleClickOutside);
    return () => document.removeEventListener('mousedown', handleClickOutside);
  }, []);

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

  const isFiltered = selectedCategory !== 'all';
  const selectedLabel =
    selectedCategory === 'all' ? 'All' : formatCategoryName(selectedCategory);

  const handleClear = (e: React.MouseEvent) => {
    e.stopPropagation();
    onSelect('all');
    setIsOpen(false);
  };

  return (
    <div ref={rootRef} className="relative w-full">
      <div className="flex items-center gap-1.5">
        <button
          type="button"
          onClick={() => setIsOpen((o) => !o)}
          aria-expanded={isOpen}
          aria-haspopup="listbox"
          className={cn(
            'category-select-trigger flex min-w-0 flex-1 items-center gap-2 rounded-lg border px-2.5 h-8',
            'text-xs text-foreground transition-colors duration-150 cursor-pointer',
            'bg-muted/30 hover:bg-muted/50',
            isOpen && 'border-primary/35 bg-muted/40',
            !isOpen && isFiltered && 'border-primary/25',
            !isOpen && !isFiltered && 'border-border/50'
          )}
        >
          <CategoryThemeContext.Provider value={triggerTheme}>
            <CategoryDot categoryKey={selectedCategory} />
            <span className="min-w-0 flex-1 truncate text-left font-medium">{selectedLabel}</span>
            <CategoryCountPill
              categoryKey={selectedCategory}
              count={getCategoryCount(categoryCounts, selectedCategory)}
            />
          </CategoryThemeContext.Provider>
          <ChevronDown
            className={cn(
              'h-3.5 w-3.5 shrink-0 text-muted-foreground/70 transition-transform duration-150',
              isOpen && 'rotate-180'
            )}
            strokeWidth={2}
          />
        </button>

        {isFiltered && (
          <button
            type="button"
            onClick={handleClear}
            className="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg border border-border/50 text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground"
            aria-label="Clear filter"
          >
            <X className="h-3.5 w-3.5" strokeWidth={2} />
          </button>
        )}
      </div>
      {isOpen && (
        <div
          role="listbox"
          className="category-dropdown absolute left-0 right-0 top-[calc(100%+4px)] z-[100] overflow-hidden rounded-lg border border-border/60 py-1 animate-dropdown-enter"
        >
          <ul className="panel-scroll max-h-[min(240px,42vh)] overflow-y-auto overscroll-contain">
            <FilterOption
              categoryKey="all"
              label="All categories"
              count={getCategoryCount(categoryCounts, 'all')}
              selected={selectedCategory === 'all'}
              onSelect={() => {
                onSelect('all');
                setIsOpen(false);
              }}
            />
            {categories.map((category) => (
              <FilterOption
                key={category}
                categoryKey={category}
                label={formatCategoryName(category)}
                count={getCategoryCount(categoryCounts, category)}
                selected={selectedCategory === category}
                onSelect={() => {
                  onSelect(category);
                  setIsOpen(false);
                }}
              />
            ))}
          </ul>
          <div className="border-t border-border/40 px-2.5 py-1.5">
            <p className="text-[10px] text-muted-foreground">
              <span className="font-mono tabular-nums text-foreground/70">{filteredCount}</span> shown
            </p>
          </div>
        </div>
      )}
    </div>
  );
}

function CategoryDot({ categoryKey }: { categoryKey: string }) {
  const theme = useContext(CategoryThemeContext) ?? useCategoryTheme(categoryKey);
  const { dot } = theme;

  return (
    <span
      className="h-2 w-2 shrink-0 rounded-full ring-1 ring-black/5 dark:ring-white/10"
      style={{ backgroundColor: dot, boxShadow: `0 0 0 2px color-mix(in srgb, ${dot} 28%, transparent)` }}
      aria-hidden
    />
  );
}

function CategoryCountPill({
  categoryKey,
  count,
}: {
  categoryKey: string;
  count: number;
}) {
  const theme = useContext(CategoryThemeContext) ?? useCategoryTheme(categoryKey);

  return (
    <span
      className="shrink-0 rounded-md border px-1.5 py-0.5 font-mono text-[10px] font-semibold tabular-nums leading-none"
      style={{
        backgroundColor: theme.badgeBg,
        color: theme.badgeText,
        borderColor: theme.badgeBorder,
      }}
    >
      {count}
    </span>
  );
}

function FilterOption({
  categoryKey,
  label,
  count,
  selected,
  onSelect,
}: {
  categoryKey: string;
  label: string;
  count: number;
  selected: boolean;
  onSelect: () => void;
}) {
  const isDark = useDarkMode();
  const theme = getCategoryColorTheme(categoryKey, isDark);

  return (
    <li>
      <CategoryThemeContext.Provider value={theme}>
        <button
          type="button"
          role="option"
          aria-selected={selected}
          onClick={onSelect}
          className={cn(
            'flex w-full items-center gap-2 px-2.5 py-1.5 text-left transition-colors cursor-pointer',
            selected ? 'bg-muted/40' : 'hover:bg-muted/30'
          )}
          style={
            selected
              ? { boxShadow: `inset 2px 0 0 0 ${theme.dot}` }
              : undefined
          }
        >
          <CategoryDot categoryKey={categoryKey} />
          <span className={cn('min-w-0 flex-1 truncate text-xs', selected && 'font-medium')}>
            {label}
          </span>
          <CategoryCountPill categoryKey={categoryKey} count={count} />
        </button>
      </CategoryThemeContext.Provider>
    </li>
  );
}
