import { useState, useMemo } from "react";

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

export interface SortConfig<T> {
  key: keyof T | null;
  direction: SortDirection;
}

type Comparators<T> = Partial<Record<keyof T, (a: T, b: T, direction: SortDirection) => number>>;

/**
 * Generic hook for client-side sortable table data.
 *
 * @param data - The array of items to sort
 * @param defaultKey - The column key to sort by initially (null = no sort)
 * @param defaultDirection - Initial sort direction
 * @param comparators - Optional per-key custom comparators. Receives both items and the
 *   current direction so the comparator can handle ascending/descending internally
 *   (return positive to sort a after b).
 */
export function useSortableData<T>(
  data: T[],
  defaultKey: keyof T | null = null,
  defaultDirection: SortDirection = "asc",
  comparators?: Comparators<T>
): {
  sortedData: T[];
  sortConfig: SortConfig<T>;
  requestSort: (key: keyof T) => void;
} {
  const [sortConfig, setSortConfig] = useState<SortConfig<T>>({
    key: defaultKey,
    direction: defaultDirection,
  });

  const sortedData = useMemo(() => {
    if (!sortConfig.key) return data;

    const key = sortConfig.key;
    const dir = sortConfig.direction;

    return data.toSorted((a, b) => {
      // Use custom comparator if provided
      if (comparators?.[key]) {
        return comparators[key]?.(a, b, dir) ?? 0;
      }

      const aVal = a[key];
      const bVal = b[key];

      if (aVal === null || aVal === undefined) return 1;
      if (bVal === null || bVal === undefined) return -1;

      let cmp = 0;
      if (typeof aVal === "string" && typeof bVal === "string") {
        cmp = aVal.localeCompare(bVal);
      } else {
        cmp = aVal < bVal ? -1 : aVal > bVal ? 1 : 0;
      }

      return dir === "asc" ? cmp : -cmp;
    });
  }, [data, sortConfig, comparators]);

  const requestSort = (key: keyof T) => {
    setSortConfig((prev) => ({
      key,
      direction: prev.key === key && prev.direction === "asc" ? "desc" : "asc",
    }));
  };

  return { sortedData, sortConfig, requestSort };
}
