/**
 * Digests radar hooks (X12).
 *
 * A digest ("כל יום" daily one-pager, Ofer Toister) is a SECONDARY, discovery-
 * layer source that POINTS at a ruling — never cited in a decision (INV-DIG1),
 * never extracts halachot (INV-DIG2). Distinct from:
 *   - /api/precedent-library (authoritative case-law corpus, citable)
 *   - /api/training (Daphna's style corpus)
 *
 * Endpoints (all under /api/digests):
 *   - POST /upload (multipart) → { status, digest_id } (pending → local enrich)
 *   - GET / (filters) → list
 *   - GET /search → semantic radar search
 *   - GET /queue/pending → digests awaiting local LLM enrichment
 *   - GET /{id} → detail
 *   - PATCH /{id} → metadata edit
 *   - DELETE /{id} → remove
 *   - POST /{id}/link {case_law_id} → bridge to the underlying ruling
 *   - POST /{id}/relink → re-run autolink
 *   - DELETE /{id}/link → clear link
 */

import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { ApiError, apiRequest } from "./client";
import type { PracticeArea } from "./precedent-library";

export type Digest = {
  id: string;
  yomon_number: string;
  digest_date: string | null;
  publication: string;
  source_firm: string;
  concept_tag: string;
  headline_holding: string;
  analysis_text: string;
  summary: string;
  underlying_citation: string;
  underlying_court: string;
  underlying_date: string | null;
  underlying_judge: string;
  practice_area: PracticeArea | "";
  appeal_subtype: string;
  subject_tags: string[];
  linked_case_law_id: string | null;
  source_document_path: string;
  content_hash: string;
  extraction_status: string;
  /** decision (points at a ruling) · announcement (legislative/notice, no ruling) · other · "" */
  digest_kind: string;
  created_at: string;
  updated_at: string;
};

/** A search hit = a Digest plus the joined linked-ruling fields + score. */
export type DigestSearchHit = Digest & {
  linked_case_number: string | null;
  linked_case_name: string | null;
  linked_searchable: boolean | null;
  score: number;
  type: "digest";
};

export type DigestListFilters = {
  practiceArea?: PracticeArea;
  conceptTag?: string;
  /** undefined = all; true = linked to a ruling; false = unlinked (open gap) */
  linked?: boolean;
  search?: string;
  /** source publication: 'כל יום' (daily) | 'עו"ד על נדל"ן' (monthly bulletin) */
  publication?: string;
  limit?: number;
  offset?: number;
};

export const digestKeys = {
  all: ["digests"] as const,
  list: (filters: DigestListFilters) =>
    [...digestKeys.all, "list", filters] as const,
  detail: (id: string) => [...digestKeys.all, "detail", id] as const,
  search: (q: string, filters: Record<string, string>) =>
    [...digestKeys.all, "search", q, filters] as const,
  pending: () => [...digestKeys.all, "pending"] as const,
};

/** A digest is "active" while it awaits or is mid local LLM enrichment. */
export function isDigestActive(d: Digest): boolean {
  return d.extraction_status === "pending" || d.extraction_status === "processing";
}

export function useDigests(filters: DigestListFilters = {}) {
  return useQuery({
    queryKey: digestKeys.list(filters),
    queryFn: ({ signal }) => {
      const p = new URLSearchParams();
      if (filters.practiceArea) p.set("practice_area", filters.practiceArea);
      if (filters.conceptTag) p.set("concept_tag", filters.conceptTag);
      if (filters.linked !== undefined) p.set("linked", String(filters.linked));
      if (filters.search) p.set("search", filters.search);
      if (filters.publication) p.set("publication", filters.publication);
      if (filters.limit) p.set("limit", String(filters.limit));
      if (filters.offset) p.set("offset", String(filters.offset));
      const qs = p.toString();
      return apiRequest<{ items: Digest[]; count: number }>(
        `/api/digests${qs ? `?${qs}` : ""}`,
        { signal },
      );
    },
    staleTime: 30_000,
    // Poll while any row is awaiting/mid local enrichment; stop once settled.
    refetchInterval: (query) => {
      const data = query.state.data;
      if (!data) return false;
      return data.items.some((d) => isDigestActive(d)) ? 5000 : false;
    },
  });
}

export function useDigest(id: string | null) {
  return useQuery({
    queryKey: digestKeys.detail(id ?? ""),
    queryFn: ({ signal }) =>
      apiRequest<Digest>(`/api/digests/${encodeURIComponent(id!)}`, { signal }),
    enabled: Boolean(id),
    staleTime: 30_000,
  });
}

export type DigestSearchFilters = {
  practiceArea?: PracticeArea;
  subjectTag?: string;
  conceptTag?: string;
  limit?: number;
};

export function useDigestSearch(query: string, filters: DigestSearchFilters = {}) {
  const params: Record<string, string> = {};
  if (filters.practiceArea) params.practice_area = filters.practiceArea;
  if (filters.subjectTag) params.subject_tag = filters.subjectTag;
  if (filters.conceptTag) params.concept_tag = filters.conceptTag;

  return useQuery({
    queryKey: digestKeys.search(query, params),
    queryFn: ({ signal }) => {
      const p = new URLSearchParams({ q: query });
      for (const [k, v] of Object.entries(params)) p.set(k, v);
      if (filters.limit) p.set("limit", String(filters.limit));
      return apiRequest<{ items: DigestSearchHit[]; count: number }>(
        `/api/digests/search?${p.toString()}`,
        { signal },
      );
    },
    enabled: query.trim().length >= 2,
    staleTime: 10_000,
    placeholderData: (prev) => prev,
  });
}

/** Digests awaiting local LLM enrichment (drained by `digest_process_pending`). */
export function useDigestPending() {
  return useQuery({
    queryKey: digestKeys.pending(),
    queryFn: ({ signal }) =>
      apiRequest<{ items: Digest[]; count: number }>(
        "/api/digests/queue/pending",
        { signal },
      ),
    staleTime: 15_000,
  });
}

export type DigestUploadInput = {
  file: File;
  yomon_number?: string;
  digest_date?: string;
  practice_area?: PracticeArea;
  appeal_subtype?: string;
  subject_tags?: string[];
};

export function useUploadDigest() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: async (input: DigestUploadInput) => {
      const fd = new FormData();
      fd.append("file", input.file);
      if (input.yomon_number) fd.append("yomon_number", input.yomon_number);
      if (input.digest_date) fd.append("digest_date", input.digest_date);
      if (input.practice_area) fd.append("practice_area", input.practice_area);
      if (input.appeal_subtype) fd.append("appeal_subtype", input.appeal_subtype);
      if (input.subject_tags && input.subject_tags.length)
        fd.append("subject_tags", JSON.stringify(input.subject_tags));

      const res = await fetch("/api/digests/upload", { method: "POST", body: fd });
      const parsed = await res.json().catch(() => null);
      if (!res.ok) {
        throw new ApiError(`Upload failed with ${res.status}`, res.status, parsed);
      }
      return parsed as { status: string; digest_id: string; extraction_status: string };
    },
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: digestKeys.all });
    },
  });
}

export type DigestPatch = Partial<{
  yomon_number: string;
  digest_date: string;
  concept_tag: string;
  headline_holding: string;
  summary: string;
  underlying_citation: string;
  underlying_court: string;
  underlying_date: string;
  underlying_judge: string;
  practice_area: PracticeArea;
  appeal_subtype: string;
  subject_tags: string[];
}>;

export function useUpdateDigest() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: ({ id, patch }: { id: string; patch: DigestPatch }) =>
      apiRequest<Digest>(`/api/digests/${encodeURIComponent(id)}`, {
        method: "PATCH",
        body: patch,
      }),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: digestKeys.all });
    },
  });
}

export function useDeleteDigest() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (id: string) =>
      apiRequest<{ deleted: boolean }>(
        `/api/digests/${encodeURIComponent(id)}`,
        { method: "DELETE" },
      ),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: digestKeys.all });
    },
  });
}

export function useLinkDigest() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: ({ id, caseLawId }: { id: string; caseLawId: string }) =>
      apiRequest<{ linked: boolean; case_number: string }>(
        `/api/digests/${encodeURIComponent(id)}/link`,
        { method: "POST", body: { case_law_id: caseLawId } },
      ),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: digestKeys.all });
    },
  });
}

export function useRelinkDigest() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (id: string) =>
      apiRequest<{ linked: boolean; case_law_id: string | null; changed: boolean }>(
        `/api/digests/${encodeURIComponent(id)}/relink`,
        { method: "POST" },
      ),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: digestKeys.all });
    },
  });
}

export function useUnlinkDigest() {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (id: string) =>
      apiRequest<{ unlinked: boolean }>(
        `/api/digests/${encodeURIComponent(id)}/link`,
        { method: "DELETE" },
      ),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: digestKeys.all });
    },
  });
}
