"use client";

import { useState, useEffect, useCallback, useRef, useMemo } from "react";
import { createPortal } from "react-dom";
import { Filter, Search, Check } from "lucide-react";
import { Button } from "./button";
import { cn } from "@/lib/utils";
import { PRIMARY_COLOR, type CSSPropertiesWithVars } from "@/lib/common";

export type FilterOption = {
  id: string | number;
  label: string;
  value: string | number;
};

export type FilterColumn = {
  label: string;
  apiEndpoint: string;
  searchPlaceholder?: string;
  valueKey?: string; // Key in API response for the value (default: 'id')
  labelKey?: string; // Key in API response for the label (default: 'label' or 'name')
  transformData?: (data: any) => FilterOption[]; // Custom transform function
};

export type FilterDropdownProps = {
  columns: FilterColumn[];
  onGenerate?: (filters: Record<string, (string | number)[]>, sortOrder: "asc" | "desc") => void;
  initialFilters?: Record<string, (string | number)[]>;
  initialSort?: "asc" | "desc";
  filterIconUrl?: string;
  generateButtonText?: string;
  showSortOptions?: boolean;
  className?: string;
};

export function FilterDropdown({
  columns,
  onGenerate,
  initialFilters = {},
  initialSort = "desc",
  filterIconUrl,
  generateButtonText = "Generate Report",
  showSortOptions = true,
  className,
}: FilterDropdownProps) {
  const [isOpen, setIsOpen] = useState(false);
  const [loading, setLoading] = useState<Record<string, boolean>>({});
  const [data, setData] = useState<Record<string, FilterOption[]>>({});
  const [selectedFilters, setSelectedFilters] = useState<Record<string, Set<string | number>>>(
    Object.keys(initialFilters).reduce(
      (acc, key) => ({ ...acc, [key]: new Set(initialFilters[key]) }),
      {}
    )
  );
  const [searchTerms, setSearchTerms] = useState<Record<string, string>>({});
  const [sortOrder, setSortOrder] = useState<"asc" | "desc">(initialSort);
  const [errors, setErrors] = useState<Record<string, string>>({});
  const [dropdownPosition, setDropdownPosition] = useState<{ top: number; right: number } | null>(null);
  const [mounted, setMounted] = useState(false);
  const dropdownRef = useRef<HTMLDivElement>(null);
  const buttonRef = useRef<HTMLDivElement>(null);

  useEffect(() => {
    setMounted(true);
  }, []);

  // Calculate dropdown position when opening
  useEffect(() => {
    if (isOpen && buttonRef.current) {
      // Use requestAnimationFrame to ensure DOM is ready
      requestAnimationFrame(() => {
        if (buttonRef.current) {
          const buttonRect = buttonRef.current.getBoundingClientRect();
          setDropdownPosition({
            top: buttonRect.bottom + window.scrollY + 8,
            right: window.innerWidth - buttonRect.right,
          });
        }
      });
    } else {
      setDropdownPosition(null);
    }
  }, [isOpen]);

  // Close dropdown when clicking outside
  useEffect(() => {
    if (!isOpen) return;

    const handleClickOutside = (event: MouseEvent) => {
      const target = event.target as Node;
      if (
        dropdownRef.current &&
        !dropdownRef.current.contains(target) &&
        buttonRef.current &&
        !buttonRef.current.contains(target)
      ) {
        event.preventDefault();
        event.stopPropagation();
        setIsOpen(false);
      }
    };

    // Use capture phase and add delay to prevent immediate closing
    const timeoutId = setTimeout(() => {
      document.addEventListener("mousedown", handleClickOutside, true);
    }, 150);
    
    return () => {
      clearTimeout(timeoutId);
      document.removeEventListener("mousedown", handleClickOutside, true);
    };
  }, [isOpen]);

  // Fetch data for each column
  const fetchColumnData = useCallback(async (column: FilterColumn) => {
    const columnKey = column.label.toLowerCase().replace(/\s+/g, "_");
    setLoading((prev) => ({ ...prev, [columnKey]: true }));
    setErrors((prev) => ({ ...prev, [columnKey]: "" }));

    try {
      const response = await fetch(column.apiEndpoint, {
        method: "GET",
        credentials: "include",
      });

      if (!response.ok) {
        throw new Error(`Failed to fetch ${column.label} (${response.status})`);
      }

      const json = await response.json();
      let options: FilterOption[] = [];

      if (column.transformData) {
        options = column.transformData(json);
      } else {
        const dataArray = Array.isArray(json) ? json : json.data || json.items || [];
        const valueKey = column.valueKey || "id";
        const labelKey = column.labelKey || "label" || "name";

        options = dataArray.map((item: any) => ({
          id: item[valueKey],
          label: item[labelKey] || String(item[valueKey]),
          value: item[valueKey],
        }));
      }

      setData((prev) => ({ ...prev, [columnKey]: options }));

      // Initialize selected filters if not set
      if (!selectedFilters[columnKey] || selectedFilters[columnKey].size === 0) {
        setSelectedFilters((prev) => ({
          ...prev,
          [columnKey]: new Set(options.map((opt) => opt.value)),
        }));
      }
    } catch (error) {
      console.error(`Error fetching ${column.label}:`, error);
      setErrors((prev) => ({
        ...prev,
        [columnKey]: error instanceof Error ? error.message : "Failed to load data",
      }));
    } finally {
      setLoading((prev) => ({ ...prev, [columnKey]: false }));
    }
  }, [selectedFilters]);

  // Fetch all columns when dropdown opens
  useEffect(() => {
    if (isOpen) {
      columns.forEach((column) => {
        const columnKey = column.label.toLowerCase().replace(/\s+/g, "_");
        if (!data[columnKey] || data[columnKey].length === 0) {
          fetchColumnData(column);
        }
      });
    }
  }, [isOpen, columns, data, fetchColumnData]);

  const toggleFilter = useCallback((columnKey: string, value: string | number) => {
    setSelectedFilters((prev) => {
      const newSet = new Set(prev[columnKey] || []);
      if (newSet.has(value)) {
        newSet.delete(value);
      } else {
        newSet.add(value);
      }
      return { ...prev, [columnKey]: newSet };
    });
  }, []);

  const selectAll = useCallback((columnKey: string) => {
    setSelectedFilters((prev) => {
      const columnData = data[columnKey] || [];
      return {
        ...prev,
        [columnKey]: new Set(columnData.map((opt) => opt.value)),
      };
    });
  }, [data]);

  const deselectAll = useCallback((columnKey: string) => {
    setSelectedFilters((prev) => ({
      ...prev,
      [columnKey]: new Set(),
    }));
  }, []);

  const handleGenerate = () => {
    const filters: Record<string, (string | number)[]> = {};
    Object.keys(selectedFilters).forEach((key) => {
      filters[key] = Array.from(selectedFilters[key]);
    });
    onGenerate?.(filters, sortOrder);
    setIsOpen(false);
  };

  const getFilteredOptions = (columnKey: string): FilterOption[] => {
    const columnData = data[columnKey] || [];
    const searchTerm = searchTerms[columnKey]?.toLowerCase() || "";
    if (!searchTerm) return columnData;
    return columnData.filter((opt) => opt.label.toLowerCase().includes(searchTerm));
  };

  return (
    <>
      <div className={cn("relative inline-block z-[100]", className)} ref={buttonRef}>
        <button
          type="button"
          onClick={(e) => {
            e.preventDefault();
            e.stopPropagation();
            setIsOpen((prev) => !prev);
          }}
          onMouseDown={(e) => {
            e.preventDefault();
            e.stopPropagation();
          }}
          className={cn(
            "inline-flex items-center gap-2 rounded-lg border bg-white px-3 py-1.5 text-xs font-semibold text-slate-700 transition-all duration-200 relative z-[100] shadow-sm",
            isOpen
              ? "text-white"
              : "border-opacity-40"
          )}
          style={isOpen ? {
            borderColor: PRIMARY_COLOR,
            backgroundColor: PRIMARY_COLOR,
          } : {
            borderColor: `${PRIMARY_COLOR}66`,
          }}
          onMouseEnter={(e) => {
            if (!isOpen) {
              e.currentTarget.style.backgroundColor = PRIMARY_COLOR;
              e.currentTarget.style.color = "white";
              e.currentTarget.style.borderColor = PRIMARY_COLOR;
            }
          }}
          onMouseLeave={(e) => {
            if (!isOpen) {
              e.currentTarget.style.backgroundColor = "white";
              e.currentTarget.style.color = "";
              e.currentTarget.style.borderColor = `${PRIMARY_COLOR}66`;
            }
          }}
          title="Filter"
          aria-haspopup="true"
          aria-expanded={isOpen}
        >
          {filterIconUrl ? (
            <img src={filterIconUrl} alt="Filter" className="h-4 w-4 object-contain" />
          ) : (
            <Filter className="h-4 w-4" />
          )}
          <span>Filter</span>
        </button>
      </div>

      {mounted && isOpen && createPortal(
        <div
          ref={dropdownRef}
          className="fixed z-[9999] bg-white rounded-xl shadow-2xl border border-slate-200 p-6 min-w-[900px] max-w-[1200px]"
          onClick={(e) => {
            e.stopPropagation();
            e.preventDefault();
          }}
          onMouseDown={(e) => {
            e.stopPropagation();
            e.preventDefault();
          }}
          style={
            dropdownPosition
              ? {
                  top: `${dropdownPosition.top}px`,
                  right: `${dropdownPosition.right}px`,
                }
              : { visibility: "hidden" }
          }
        >
          {/* Error Messages */}
          {Object.keys(errors).map(
            (key) =>
              errors[key] && (
                <div
                  key={key}
                  className="mb-4 p-3 rounded-lg bg-red-50 border border-red-200 text-red-700 text-sm max-w-[300px] shadow-sm"
                >
                  {errors[key]}
                </div>
              )
          )}

          {/* Filter Columns */}
          <div className="flex gap-4 mb-4">
            {columns.map((column) => {
              const columnKey = column.label.toLowerCase().replace(/\s+/g, "_");
              const columnData = data[columnKey] || [];
              const filteredOptions = getFilteredOptions(columnKey);
              const isLoading = loading[columnKey];
              const selectedSet = selectedFilters[columnKey] || new Set();

              return (
                <div 
                  key={columnKey} 
                  className="flex-1" 
                  onClick={(e) => e.stopPropagation()}
                  onMouseDown={(e) => e.stopPropagation()}
                >
                  <label className="block mb-3">
                    <h6 
                      className="text-sm font-semibold uppercase tracking-wide"
                      style={{ color: PRIMARY_COLOR }}
                    >
                      {column.label}
                    </h6>
                  </label>

                  {/* Search Input */}
                  <div className="mb-2">
                    <div className="relative">
                      <Search className="absolute left-2 top-1/2 -translate-y-1/2 h-4 w-4 text-slate-400" />
                      <input
                        type="text"
                        placeholder={column.searchPlaceholder || "Search..."}
                        value={searchTerms[columnKey] || ""}
                        onChange={(e) =>
                          setSearchTerms((prev) => ({ ...prev, [columnKey]: e.target.value }))
                        }
                        onClick={(e) => e.stopPropagation()}
                        onMouseDown={(e) => e.stopPropagation()}
                        className="w-full pl-8 pr-3 py-1.5 text-sm border border-slate-300 rounded-md focus:outline-none focus:ring-2 focus:ring-opacity-30 focus:border-opacity-100 bg-white transition-all"
                        style={{
                          "--focus-ring": `${PRIMARY_COLOR}4D`,
                          "--focus-border": PRIMARY_COLOR,
                        } as CSSPropertiesWithVars}
                        onFocus={(e) => {
                          e.currentTarget.style.borderColor = PRIMARY_COLOR;
                          e.currentTarget.style.boxShadow = `0 0 0 2px ${PRIMARY_COLOR}4D`;
                        }}
                        onBlur={(e) => {
                          e.currentTarget.style.borderColor = "";
                          e.currentTarget.style.boxShadow = "";
                        }}
                      />
                    </div>
                    <div className="mt-2 text-xs flex items-center gap-1">
                      <button
                        type="button"
                        onClick={(e) => {
                          e.preventDefault();
                          e.stopPropagation();
                          selectAll(columnKey);
                        }}
                        onMouseDown={(e) => {
                          e.preventDefault();
                          e.stopPropagation();
                        }}
                        className="hover:underline font-semibold transition-colors"
                        style={{ color: PRIMARY_COLOR }}
                        onMouseEnter={(e) => {
                          e.currentTarget.style.color = `${PRIMARY_COLOR}CC`;
                        }}
                        onMouseLeave={(e) => {
                          e.currentTarget.style.color = PRIMARY_COLOR;
                        }}
                      >
                        Select All
                      </button>
                      <span className="text-slate-400">|</span>
                      <button
                        type="button"
                        onClick={(e) => {
                          e.preventDefault();
                          e.stopPropagation();
                          deselectAll(columnKey);
                        }}
                        onMouseDown={(e) => {
                          e.preventDefault();
                          e.stopPropagation();
                        }}
                        className="hover:underline font-semibold transition-colors"
                        style={{ color: PRIMARY_COLOR }}
                        onMouseEnter={(e) => {
                          e.currentTarget.style.color = `${PRIMARY_COLOR}CC`;
                        }}
                        onMouseLeave={(e) => {
                          e.currentTarget.style.color = PRIMARY_COLOR;
                        }}
                      >
                        Deselect All
                      </button>
                    </div>
                  </div>

                  {/* Options List */}
                  <div
                    className="border-2 border-slate-200 rounded-lg p-3 max-h-[250px] overflow-y-auto bg-white shadow-inner"
                    onClick={(e) => e.stopPropagation()}
                  >
                    {isLoading ? (
                      <div className="text-center py-8 text-slate-500 text-sm flex items-center justify-center gap-2">
                        <div 
                          className="animate-spin rounded-full h-4 w-4 border-2 border-t-transparent"
                          style={{ borderColor: PRIMARY_COLOR }}
                        ></div>
                        Loading...
                      </div>
                    ) : filteredOptions.length === 0 ? (
                      <div className="text-center py-8 text-slate-500 text-sm">
                        {searchTerms[columnKey] ? "No results found" : "No options available"}
                      </div>
                    ) : (
                      <ul className="space-y-0.5">
                        {filteredOptions.map((option) => {
                          const isChecked = selectedSet.has(option.value);
                          return (
                            <li
                              key={String(option.value)}
                              className="flex items-center gap-2.5 p-2 rounded-md cursor-pointer transition-colors group"
                              style={{
                                "--hover-bg": `${PRIMARY_COLOR}1A`,
                              } as CSSPropertiesWithVars}
                              onMouseEnter={(e) => {
                                e.currentTarget.style.backgroundColor = `${PRIMARY_COLOR}1A`;
                              }}
                              onMouseLeave={(e) => {
                                e.currentTarget.style.backgroundColor = "";
                              }}
                              onClick={(e) => {
                                e.preventDefault();
                                e.stopPropagation();
                                toggleFilter(columnKey, option.value);
                              }}
                              onMouseDown={(e) => {
                                e.preventDefault();
                                e.stopPropagation();
                              }}
                            >
                              <div className="relative flex items-center shrink-0">
                                <input
                                  type="checkbox"
                                  checked={isChecked}
                                  onChange={() => toggleFilter(columnKey, option.value)}
                                  onClick={(e) => e.stopPropagation()}
                                  onMouseDown={(e) => e.stopPropagation()}
                                  className="sr-only"
                                  id={`${columnKey}_${option.value}`}
                                />
                                <div
                                  className={cn(
                                    "w-4 h-4 border-2 rounded flex items-center justify-center transition-all",
                                    isChecked
                                      ? "shadow-sm"
                                      : "border-slate-300 bg-white"
                                  )}
                                  style={isChecked ? {
                                    backgroundColor: PRIMARY_COLOR,
                                    borderColor: PRIMARY_COLOR,
                                  } : {}}
                                  onMouseEnter={(e) => {
                                    if (!isChecked) {
                                      e.currentTarget.style.borderColor = `${PRIMARY_COLOR}99`;
                                    }
                                  }}
                                  onMouseLeave={(e) => {
                                    if (!isChecked) {
                                      e.currentTarget.style.borderColor = "";
                                    }
                                  }}
                                >
                                  {isChecked && <Check className="h-3 w-3 text-white" strokeWidth={3} />}
                                </div>
                              </div>
                              <label
                                htmlFor={`${columnKey}_${option.value}`}
                                className="text-sm text-slate-700 cursor-pointer flex-1 select-none"
                                onClick={(e) => e.stopPropagation()}
                                onMouseDown={(e) => e.stopPropagation()}
                              >
                                {option.label}
                              </label>
                            </li>
                          );
                        })}
                      </ul>
                    )}
                  </div>
                </div>
              );
            })}
          </div>

          {/* Actions */}
          <div className="flex items-center gap-4 mt-6 pt-4 border-t border-slate-200">
            <Button
              type="button"
              onClick={(e) => {
                e.preventDefault();
                e.stopPropagation();
                handleGenerate();
              }}
              onMouseDown={(e) => {
                e.preventDefault();
                e.stopPropagation();
              }}
              className="text-white shadow-md hover:shadow-lg transition-all px-6 font-semibold"
              style={{ backgroundColor: PRIMARY_COLOR }}
              onMouseEnter={(e) => {
                e.currentTarget.style.backgroundColor = `${PRIMARY_COLOR}E6`;
              }}
              onMouseLeave={(e) => {
                e.currentTarget.style.backgroundColor = PRIMARY_COLOR;
              }}
            >
              {generateButtonText}
            </Button>

            {showSortOptions && (
              <div className="flex items-center gap-2">
                <div className="flex gap-2">
                  <input
                    type="radio"
                    name="sort"
                    id="sort_desc"
                    checked={sortOrder === "desc"}
                    onChange={() => setSortOrder("desc")}
                    onClick={(e) => e.stopPropagation()}
                    onMouseDown={(e) => e.stopPropagation()}
                    className="sr-only"
                  />
                  <label
                    htmlFor="sort_desc"
                    onClick={(e) => {
                      e.preventDefault();
                      e.stopPropagation();
                      setSortOrder("desc");
                    }}
                    onMouseDown={(e) => {
                      e.preventDefault();
                      e.stopPropagation();
                    }}
                    className={cn(
                      "px-4 py-2 text-sm font-semibold border-2 rounded-lg cursor-pointer transition-all select-none",
                      sortOrder === "desc"
                        ? "bg-opacity-10 shadow-sm"
                        : "hover:bg-opacity-10 hover:border-opacity-80"
                    )}
                    style={sortOrder === "desc" ? {
                      backgroundColor: `${PRIMARY_COLOR}1A`,
                      borderColor: PRIMARY_COLOR,
                      color: PRIMARY_COLOR,
                    } : {
                      borderColor: PRIMARY_COLOR,
                      color: PRIMARY_COLOR,
                    }}
                    onMouseEnter={(e) => {
                      if (sortOrder !== "desc") {
                        e.currentTarget.style.backgroundColor = `${PRIMARY_COLOR}1A`;
                        e.currentTarget.style.borderColor = `${PRIMARY_COLOR}CC`;
                      }
                    }}
                    onMouseLeave={(e) => {
                      if (sortOrder !== "desc") {
                        e.currentTarget.style.backgroundColor = "";
                        e.currentTarget.style.borderColor = PRIMARY_COLOR;
                      }
                    }}
                  >
                    Sort DESC
                  </label>

                  <input
                    type="radio"
                    name="sort"
                    id="sort_asc"
                    checked={sortOrder === "asc"}
                    onChange={() => setSortOrder("asc")}
                    onClick={(e) => {
                      e.preventDefault();
                      e.stopPropagation();
                    }}
                    onMouseDown={(e) => {
                      e.preventDefault();
                      e.stopPropagation();
                    }}
                    className="sr-only"
                  />
                  <label
                    htmlFor="sort_asc"
                    onClick={(e) => {
                      e.preventDefault();
                      e.stopPropagation();
                      setSortOrder("asc");
                    }}
                    onMouseDown={(e) => {
                      e.preventDefault();
                      e.stopPropagation();
                    }}
                    className={cn(
                      "px-4 py-2 text-sm font-semibold border-2 rounded-lg cursor-pointer transition-all select-none",
                      sortOrder === "asc"
                        ? "bg-[#428B4D]/10 border-[#428B4D] text-[#428B4D] shadow-sm"
                        : "border-[#428B4D] text-[#428B4D] hover:bg-[#428B4D]/10 hover:border-[#428B4D]/80"
                    )}
                  >
                    Sort ASC
                  </label>
                </div>
              </div>
            )}
          </div>
        </div>,
        document.body
      )}
    </>
  );
}
