/**
 * Planning-schemes registry (מרשם-התכניות, V38) — typed API hooks.
 *
 * SSOT for a plan's identity + validity, reused across cases. LLM-extracted rows
 * arrive pending_review; only approved validity feeds block-tet (INV-DM5/G10).
 * Variant duplicates are surfaced (usePlanDuplicates), never auto-merged — the
 * chair merges manually. Mirrors the precedent-library hook conventions.
 */

import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { apiRequest } from "./client";

export type PlanReviewStatus = "pending_review" | "approved" | "rejected";

export type PlanDiscrepancy = {
  field: string;
  old: string;
  new: string;
  source_case_number?: string;
  via?: string;
};

export type Plan = {
  id: string;
  plan_number: string;
  display_name: string;
  aliases: string[];
  plan_type: string;
  gazette_date: string | null;     // ISO YYYY-MM-DD
  yalkut_number: string;
  purpose: string;
  citation_formatted: string;       // the deterministic block-tet sentence
  review_status: PlanReviewStatus;
  source_case_number: string;
  source_document_id: string | null;
  model_used: string;
  discrepancies: PlanDiscrepancy[];
  created_at: string;
  updated_at: string;
  /** Only present on a duplicate-candidate hit. */
  match_reason?: string;
};

export const planKeys = {
  all: ["plans"] as const,
  list: () => [...planKeys.all, "list"] as const,
  duplicates: (id: string) => [...planKeys.all, "duplicates", id] as const,
};

/**
 * The whole registry in one fetch (every review_status). The panel filters
 * client-side by status segment (ממתינים/מאושרות/כולן) and search — the
 * registry is small, so one load gives accurate segment counts + instant
 * filtering without per-keystroke round-trips. `limit` is a safety ceiling;
 * if it is ever hit the panel surfaces a truncation note (no silent cap).
 */
export function usePlansAll(limit = 1000) {
  return useQuery({
    queryKey: planKeys.list(),
    queryFn: ({ signal }) =>
      apiRequest<{ items: Plan[]; count: number }>(
        `/api/plans?limit=${limit}`,
        { signal },
      ),
    staleTime: 5_000,
    refetchOnMount: "always",
  });
}

/** Near-duplicate candidates for a plan — surfaced for manual merge. */
export function usePlanDuplicates(planId: string, enabled = true) {
  return useQuery({
    queryKey: planKeys.duplicates(planId),
    queryFn: ({ signal }) =>
      apiRequest<{ items: Plan[]; count: number }>(
        `/api/plans/${encodeURIComponent(planId)}/duplicates`,
        { signal },
      ),
    enabled: enabled && !!planId,
    staleTime: 10_000,
  });
}

/** The candidate mavat returns for the form (INV-AH: every value carries source_url). */
export type PlanFetchResult = {
  plan_number: string;
  display_name: string;
  plan_type: string;
  purpose: string;
  gazette_date: string;     // ISO YYYY-MM-DD, "" if mavat doesn't expose it
  yalkut_number: string;
  yalkut_page: string;
  source_url: string;       // the mavat plan page
};

/**
 * Pull a plan's identity + validity from mavat (מנהל התכנון) to prefill the form.
 * Slow — drives a real browser on the host bridge (~½–1 min); surface a spinner.
 */
export function useFetchPlan() {
  return useMutation({
    mutationFn: (planNumber: string) =>
      apiRequest<PlanFetchResult>(`/api/plans/fetch`, {
        method: "POST",
        body: { plan_number: planNumber },
      }),
  });
}

export type PlanUpsert = {
  plan_number: string;
  display_name?: string;
  plan_type?: string;
  gazette_date?: string;   // ISO; "" = unknown
  yalkut_number?: string;
  purpose?: string;
  review_status?: PlanReviewStatus;
  aliases?: string[];
};

export type PlanEdit = {
  plan_number: string;
  display_name?: string;
  plan_type?: string;
  gazette_date?: string;
  yalkut_number?: string;
  purpose?: string;
  aliases?: string[] | null;
};

function invalidate(qc: ReturnType<typeof useQueryClient>) {
  qc.invalidateQueries({ queryKey: planKeys.all });
  // the chair-pending aggregate (/approvals) carries a plans count (INV-IA2)
  qc.invalidateQueries({ queryKey: ["chair", "pending"] });
}

/** Manual chair add/upsert (idempotent on normalized plan_number). */
export function useUpsertPlan() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (body: PlanUpsert) =>
      apiRequest<Plan>(`/api/plans`, { method: "POST", body }),
    onSuccess: () => invalidate(qc),
  });
}

/** Edit/fix a plan by id (refuses a number collision → use merge). */
export function useUpdatePlan() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: ({ id, patch }: { id: string; patch: PlanEdit }) =>
      apiRequest<Plan>(
        `/api/plans/${encodeURIComponent(id)}`,
        { method: "PATCH", body: patch },
      ),
    onSuccess: () => invalidate(qc),
  });
}

/** Chair gate (G10): approve / reject / reset. */
export function useReviewPlan() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: ({ id, status }: { id: string; status: PlanReviewStatus }) =>
      apiRequest<Plan>(
        `/api/plans/${encodeURIComponent(id)}/review`,
        { method: "POST", body: { review_status: status } },
      ),
    onSuccess: () => invalidate(qc),
  });
}

/** Fold a source plan into a target (manual dedup); source is deleted. */
export function useMergePlans() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: ({ sourceId, targetId }: { sourceId: string; targetId: string }) =>
      apiRequest<Plan>(
        `/api/plans/merge`,
        { method: "POST", body: { source_id: sourceId, target_id: targetId } },
      ),
    onSuccess: () => invalidate(qc),
  });
}
