"use client";

/**
 * useViewPrefs — per-view persistence of sort state and row order.
 *
 * Uses a separate localStorage key ("viewprefs_<view>") from useColumnConfig
 * ("colvis_<view>") to avoid format conflicts. Server-side the data is merged
 * into the same User.columnPreferences JSONB via trpc.user.setColumnPreferences.
 *
 * Each user's sort + row order is independent (stored on their own User record).
 */

import { useState, useCallback, useRef } from "react";
import type { ViewKey } from "@capakraken/shared";
import { trpc } from "~/lib/trpc/client.js";

interface SavedSort {
  field: string;
  dir: "asc" | "desc";
}

interface LocalViewPrefs {
  sort?: SavedSort;
  rowOrder?: string[];
}

const LS_KEY = (view: ViewKey) => `viewprefs_${view}`;

function readLocal(view: ViewKey): LocalViewPrefs {
  if (typeof window === "undefined") return {};
  try {
    const raw = localStorage.getItem(LS_KEY(view));
    return raw ? (JSON.parse(raw) as LocalViewPrefs) : {};
  } catch {
    return {};
  }
}

function writeLocal(view: ViewKey, patch: { sort?: SavedSort | null; rowOrder?: string[] | null }) {
  if (typeof window === "undefined") return;
  try {
    const current = readLocal(view);
    const next = { ...current, ...patch };
    // Remove keys that are explicitly set to null/undefined
    if (next.sort == null) delete next.sort;
    if (!next.rowOrder?.length) delete next.rowOrder;
    localStorage.setItem(LS_KEY(view), JSON.stringify(next));
  } catch {
    // ignore write errors (private browsing, quota, etc.)
  }
}

export function useViewPrefs(view: ViewKey) {
  // Initialise synchronously from localStorage so there's no flash
  const init = readLocal(view);

  const [savedSort, setSavedSortState] = useState<SavedSort | null>(init.sort ?? null);
  const [rowOrder, setRowOrderState] = useState<string[]>(init.rowOrder ?? []);

  const setMutation = trpc.user.setColumnPreferences.useMutation();

  // Debounce server sync so rapid drags don't spam mutations
  const debounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  function scheduleSave(patch: Parameters<typeof setMutation.mutate>[0]) {
    if (debounceRef.current) clearTimeout(debounceRef.current);
    debounceRef.current = setTimeout(() => {
      setMutation.mutate(patch);
    }, 600);
  }

  const setSavedSort = useCallback(
    (sort: SavedSort | null) => {
      setSavedSortState(sort);
      writeLocal(view, { sort: sort ?? null });
      scheduleSave({ view, sort: sort ?? null });
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [view],
  );

  const setRowOrder = useCallback(
    (ids: string[]) => {
      setRowOrderState(ids);
      writeLocal(view, { rowOrder: ids });
      scheduleSave({ view, rowOrder: ids.length > 0 ? ids : null });
    },
    // eslint-disable-next-line react-hooks/exhaustive-deps
    [view],
  );

  return { savedSort, setSavedSort, rowOrder, setRowOrder };
}

export type ViewPrefsHandle = ReturnType<typeof useViewPrefs>;
