import { useMemo, useCallback } from "react";
import type { ViewPrefsHandle } from "./useViewPrefs.js";

/**
 * Manages manual drag-to-reorder row ordering for a table.
 *
 * - When a column sort is active (sortField !== null), row order is suppressed —
 *   the sorted rows are returned unchanged and dragging is disabled.
 * - When no column sort is active and a saved rowOrder exists, rows are sorted
 *   by their position in rowOrder; rows without a saved position go to the end.
 * - Calling reorder() saves the new order and clears any active column sort.
 *
 * Each user's rowOrder is persisted independently via useViewPrefs.
 */
export function useRowOrder<T extends { id: string }>(
  rows: T[],
  prefs: Pick<ViewPrefsHandle, "rowOrder" | "setRowOrder">,
  activeSortField: string | null,
  resetSort: () => void,
) {
  const { rowOrder, setRowOrder } = prefs;

  const orderedRows = useMemo((): T[] => {
    // Column sort takes precedence — ignore manual order while sorting
    if (activeSortField !== null) return rows;
    if (rowOrder.length === 0) return rows;

    const indexMap = new Map(rowOrder.map((id, i) => [id, i]));
    return [...rows].sort((a, b) => {
      const ai = indexMap.get(a.id) ?? Infinity;
      const bi = indexMap.get(b.id) ?? Infinity;
      return ai - bi;
    });
  }, [rows, rowOrder, activeSortField]);

  const reorder = useCallback(
    (draggedId: string, targetId: string) => {
      if (draggedId === targetId) return;

      // Build current ordered ID list from the current orderedRows snapshot
      // (works correctly even when rowOrder is empty / partial)
      const currentIds = orderedRows.map((r) => r.id);
      const fromIdx = currentIds.indexOf(draggedId);
      const toIdx = currentIds.indexOf(targetId);
      if (fromIdx === -1 || toIdx === -1) return;

      const next = [...currentIds];
      next.splice(fromIdx, 1);
      next.splice(toIdx, 0, draggedId);

      // Clear any active column sort (mutual exclusion)
      resetSort();
      setRowOrder(next);
    },
    [orderedRows, resetSort, setRowOrder],
  );

  const resetOrder = useCallback(() => {
    setRowOrder([]);
  }, [setRowOrder]);

  const isCustomOrder = rowOrder.length > 0 && activeSortField === null;

  return { orderedRows, reorder, isCustomOrder, resetOrder };
}
