"use client";

import { useState, useMemo } from "react";

export type SortDir = "asc" | "desc";

export interface TableControlsResult<T> {
  search: string;
  setSearch: (v: string) => void;
  sortKey: keyof T | null;
  sortDir: SortDir;
  toggleSort: (key: keyof T) => void;
  activeFilters: string[];
  toggleFilter: (chip: string) => void;
  filtered: T[];
}

export interface UseTableControlsOptions<T> {
  /** All rows from the server. */
  rows: T[];
  /**
   * Return a flat string of all searchable text for a row.
   * Concatenate every visible column value, lower-cased.
   */
  searchText: (row: T) => string;
  /**
   * Return true if the row matches the given active chip label.
   * Called once per active chip; row must match ALL active chips.
   */
  chipMatch: (row: T, chip: string) => boolean;
  /**
   * Return a comparable primitive for a sort key so the hook can sort.
   * Strings are compared case-insensitively; numbers/booleans natively.
   */
  sortValue?: (row: T, key: keyof T) => string | number | boolean | null | undefined;
  /** Default sort column. Pass null to start unsorted. */
  defaultSortKey?: keyof T | null;
  /** Default sort direction. */
  defaultSortDir?: SortDir;
}

export function useTableControls<T>({
  rows,
  searchText,
  chipMatch,
  sortValue,
  defaultSortKey = null,
  defaultSortDir = "asc",
}: UseTableControlsOptions<T>): TableControlsResult<T> {
  const [search, setSearch] = useState("");
  const [sortKey, setSortKey] = useState<keyof T | null>(defaultSortKey);
  const [sortDir, setSortDir] = useState<SortDir>(defaultSortDir);
  const [activeFilters, setActiveFilters] = useState<string[]>([]);

  const toggleSort = (key: keyof T) => {
    setSortKey((prev) => {
      if (prev === key) {
        setSortDir((d) => (d === "asc" ? "desc" : "asc"));
        return key;
      }
      setSortDir("asc");
      return key;
    });
  };

  const toggleFilter = (chip: string) => {
    setActiveFilters((prev) =>
      prev.includes(chip) ? prev.filter((c) => c !== chip) : [...prev, chip]
    );
  };

  const filtered = useMemo(() => {
    let result = rows;

    // 1. Search
    const q = search.trim().toLowerCase();
    if (q) {
      result = result.filter((row) => searchText(row).toLowerCase().includes(q));
    }

    // 2. Chip filters — row must satisfy every active chip
    if (activeFilters.length > 0) {
      result = result.filter((row) => activeFilters.every((chip) => chipMatch(row, chip)));
    }

    // 3. Sort
    if (sortKey !== null && sortValue) {
      result = [...result].sort((a, b) => {
        const av = sortValue(a, sortKey) ?? "";
        const bv = sortValue(b, sortKey) ?? "";
        let cmp = 0;
        if (typeof av === "string" && typeof bv === "string") {
          cmp = av.toLowerCase().localeCompare(bv.toLowerCase());
        } else {
          cmp = av < bv ? -1 : av > bv ? 1 : 0;
        }
        return sortDir === "asc" ? cmp : -cmp;
      });
    }

    return result;
  }, [rows, search, activeFilters, sortKey, sortDir, searchText, chipMatch, sortValue]);

  return {
    search,
    setSearch,
    sortKey,
    sortDir,
    toggleSort,
    activeFilters,
    toggleFilter,
    filtered,
  };
}
