"use client";

import { useState, useEffect, useCallback, useRef } from "react";
import { TaskStatus, TaskPriority } from "@mosaic/shared";

export interface FilterValues {
  search?: string;
  status?: TaskStatus[];
  priority?: TaskPriority[];
  dateFrom?: string;
  dateTo?: string;
  sortBy?: string;
  sortOrder?: "asc" | "desc";
}

interface FilterBarProps {
  onFilterChange: (filters: FilterValues) => void;
  initialFilters?: FilterValues;
  debounceMs?: number;
}

export function FilterBar({
  onFilterChange,
  initialFilters = {},
  debounceMs = 300,
}: FilterBarProps): React.JSX.Element {
  const [filters, setFilters] = useState<FilterValues>(initialFilters);
  const [searchValue, setSearchValue] = useState(initialFilters.search ?? "");
  const [showStatusDropdown, setShowStatusDropdown] = useState(false);
  const [showPriorityDropdown, setShowPriorityDropdown] = useState(false);
  const isFirstRender = useRef(true);

  // Stable ref for onFilterChange to avoid re-triggering the debounce effect
  const onFilterChangeRef = useRef(onFilterChange);
  useEffect(() => {
    onFilterChangeRef.current = onFilterChange;
  }, [onFilterChange]);

  // Debounced search
  useEffect(() => {
    // Skip callback on first render to avoid calling with initial empty value
    if (isFirstRender.current) {
      isFirstRender.current = false;
      return;
    }

    const timer = setTimeout(() => {
      setFilters((prevFilters) => {
        if (searchValue !== prevFilters.search) {
          const newFilters = { ...prevFilters };
          if (searchValue) {
            newFilters.search = searchValue;
          } else {
            delete newFilters.search;
          }
          onFilterChangeRef.current(newFilters);
          return newFilters;
        }
        return prevFilters;
      });
    }, debounceMs);

    return (): void => {
      clearTimeout(timer);
    };
  }, [searchValue, debounceMs]);

  const handleFilterChange = useCallback(
    (key: keyof FilterValues, value: FilterValues[keyof FilterValues]): void => {
      const newFilters = { ...filters, [key]: value };
      if (!value || (Array.isArray(value) && value.length === 0)) {
        // Use Object.assign to avoid dynamic delete
        const { [key]: _removed, ...rest } = newFilters;
        setFilters(rest);
        onFilterChange(rest);
      } else {
        setFilters(newFilters);
        onFilterChange(newFilters);
      }
    },
    [filters, onFilterChange]
  );

  const handleStatusToggle = (status: TaskStatus): void => {
    const currentStatuses = filters.status ?? [];
    const newStatuses = currentStatuses.includes(status)
      ? currentStatuses.filter((s) => s !== status)
      : [...currentStatuses, status];
    handleFilterChange("status", newStatuses.length > 0 ? newStatuses : undefined);
  };

  const handlePriorityToggle = (priority: TaskPriority): void => {
    const currentPriorities = filters.priority ?? [];
    const newPriorities = currentPriorities.includes(priority)
      ? currentPriorities.filter((p) => p !== priority)
      : [...currentPriorities, priority];
    handleFilterChange("priority", newPriorities.length > 0 ? newPriorities : undefined);
  };

  const clearAllFilters = (): void => {
    setFilters({});
    setSearchValue("");
    onFilterChange({});
  };

  const activeFilterCount =
    (filters.status?.length ?? 0) +
    (filters.priority?.length ?? 0) +
    (filters.search ? 1 : 0) +
    (filters.dateFrom ? 1 : 0) +
    (filters.dateTo ? 1 : 0);

  const hasActiveFilters = activeFilterCount > 0;

  return (
    <div className="flex flex-wrap items-center gap-2 p-4 bg-gray-50 rounded-lg">
      {/* Search Input */}
      <div className="relative flex-1 min-w-[200px]">
        <input
          type="text"
          placeholder="Search tasks..."
          aria-label="Search tasks"
          value={searchValue}
          onChange={(e) => {
            setSearchValue(e.target.value);
          }}
          className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
        />
      </div>

      {/* Status Filter */}
      <div className="relative">
        <button
          onClick={() => {
            setShowStatusDropdown(!showStatusDropdown);
          }}
          className="px-3 py-2 border border-gray-300 rounded-md hover:bg-gray-100 flex items-center gap-2"
          aria-label="Status filter"
        >
          Status
          {filters.status && filters.status.length > 0 && (
            <span className="bg-blue-500 text-white text-xs px-2 py-0.5 rounded-full">
              {filters.status.length}
            </span>
          )}
        </button>
        {showStatusDropdown && (
          <div className="absolute top-full mt-1 bg-white border border-gray-300 rounded-md shadow-lg z-10 min-w-[150px]">
            {Object.values(TaskStatus).map((status) => (
              <label
                key={status}
                htmlFor={`status-filter-${status}`}
                className="flex items-center px-3 py-2 hover:bg-gray-100 cursor-pointer"
              >
                <input
                  id={`status-filter-${status}`}
                  type="checkbox"
                  checked={filters.status?.includes(status) ?? false}
                  onChange={() => {
                    handleStatusToggle(status);
                  }}
                  aria-label={`Filter by status: ${status.replace(/_/g, " ")}`}
                  className="mr-2"
                />
                {status.replace(/_/g, " ")}
              </label>
            ))}
          </div>
        )}
      </div>

      {/* Priority Filter */}
      <div className="relative">
        <button
          onClick={() => {
            setShowPriorityDropdown(!showPriorityDropdown);
          }}
          className="px-3 py-2 border border-gray-300 rounded-md hover:bg-gray-100 flex items-center gap-2"
          aria-label="Priority filter"
        >
          Priority
          {filters.priority && filters.priority.length > 0 && (
            <span className="bg-blue-500 text-white text-xs px-2 py-0.5 rounded-full">
              {filters.priority.length}
            </span>
          )}
        </button>
        {showPriorityDropdown && (
          <div className="absolute top-full mt-1 bg-white border border-gray-300 rounded-md shadow-lg z-10 min-w-[150px]">
            {Object.values(TaskPriority).map((priority) => (
              <label
                key={priority}
                htmlFor={`priority-filter-${priority}`}
                className="flex items-center px-3 py-2 hover:bg-gray-100 cursor-pointer"
              >
                <input
                  id={`priority-filter-${priority}`}
                  type="checkbox"
                  checked={filters.priority?.includes(priority) ?? false}
                  onChange={() => {
                    handlePriorityToggle(priority);
                  }}
                  aria-label={`Filter by priority: ${priority}`}
                  className="mr-2"
                />
                {priority}
              </label>
            ))}
          </div>
        )}
      </div>

      {/* Date Range */}
      <div className="flex items-center gap-2">
        <input
          type="date"
          placeholder="From date"
          aria-label="Filter from date"
          value={filters.dateFrom ?? ""}
          onChange={(e) => {
            handleFilterChange("dateFrom", e.target.value || undefined);
          }}
          className="px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
        />
        <span className="text-gray-500">to</span>
        <input
          type="date"
          placeholder="To date"
          aria-label="Filter to date"
          value={filters.dateTo ?? ""}
          onChange={(e) => {
            handleFilterChange("dateTo", e.target.value || undefined);
          }}
          className="px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500"
        />
      </div>

      {/* Clear Filters */}
      {hasActiveFilters && (
        <button
          onClick={clearAllFilters}
          className="ml-auto px-3 py-2 text-gray-700 hover:bg-gray-100 rounded-md"
          aria-label="Clear filters"
        >
          Clear filters
        </button>
      )}

      {/* Active Filter Count Badge */}
      {activeFilterCount > 0 && (
        <span className="bg-blue-500 text-white text-sm px-3 py-1 rounded-full">
          {activeFilterCount}
        </span>
      )}
    </div>
  );
}
