/**
 * Style-acquisition learning surface (T6/T13) — reconciliation ledger + style-distance.
 * Backs the /training "למידה" tab. Endpoints under /api/learning.
 */

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

export type DraftFinalPair = {
  id: string;
  case_id: string | null;
  case_number: string;
  title: string;
  status: "final_received" | "analyzed" | "lessons_folded" | string;
  change_percent: number | null;
  created_at: string | null;
  updated_at: string | null;
};

export type StyleDistance = {
  case_number: string;
  outcome: string;
  golden_ratio_adherence: {
    outcome: string;
    total_words: number;
    sections: Record<string, { actual_pct: number; target: [number, number]; deviation_pp: number }>;
    max_deviation: number | null;
  };
  anti_pattern_hits: { total: number; by_pattern: Record<string, { count: number; note: string }> };
  draft_to_final_diff: { change_percent?: number } | null;
  pair_status: string | null;
  summary: {
    ratio_max_deviation_pp: number | null;
    anti_pattern_total: number;
    change_percent: number | null;
  };
  error?: string;
};

export const learningKeys = {
  all: ["learning"] as const,
  pairs: (status: string) => [...learningKeys.all, "pairs", status] as const,
  distance: (caseNumber: string) => [...learningKeys.all, "distance", caseNumber] as const,
  caseStatus: (caseNumber: string) => [...learningKeys.all, "case-status", caseNumber] as const,
};

export function useReconciliationLedger(status = "") {
  return useQuery({
    queryKey: learningKeys.pairs(status),
    queryFn: ({ signal }) =>
      apiRequest<{ items: DraftFinalPair[]; count: number }>(
        `/api/learning/pairs${status ? `?status=${status}` : ""}`,
        { signal },
      ),
    staleTime: 15_000,
  });
}

export function useStyleDistance(caseNumber: string | null) {
  return useQuery({
    queryKey: learningKeys.distance(caseNumber ?? ""),
    queryFn: ({ signal }) =>
      apiRequest<StyleDistance>(
        `/api/learning/style-distance/${encodeURIComponent(caseNumber!)}`,
        { signal },
      ),
    enabled: Boolean(caseNumber),
    staleTime: 15_000,
  });
}

// ── T14: curator distillation proposal + chair approval gate ──────

export type DistillationChange = {
  type?: string;
  domain?: string;
  block?: string;
  description?: string;
  draft_text?: string;
  final_text?: string;
  lesson?: string;
};

export type PairDetail = {
  id: string;
  case_number: string;
  title: string;
  status: string;
  diff_stats: { change_percent?: number } | null;
  overall_assessment: string;
  changes: DistillationChange[];     // style_method only (server-filtered)
  new_expressions: string[];
};

export function usePairDetail(pairId: string | null) {
  return useQuery({
    queryKey: [...learningKeys.all, "pair", pairId ?? ""] as const,
    queryFn: ({ signal }) =>
      apiRequest<PairDetail>(`/api/learning/pairs/${pairId}`, { signal }),
    enabled: Boolean(pairId),
    staleTime: 15_000,
  });
}

export function usePromoteLearning(pairId: string) {
  const qc = useQueryClient();
  return useMutation({
    mutationFn: (body: { lessons: string[]; phrases: string[] }) =>
      apiRequest<{ id: string; status: string; folded_lessons: number; folded_phrases: number }>(
        `/api/learning/pairs/${pairId}/promote`,
        { method: "POST", body },
      ),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: learningKeys.all });
      // LRN-10 (INV-IA2): promote flips folded lessons' review_status, so the
      // per-corpus LessonsTab must refetch (lessons key is corpus-scoped —
      // invalidate the whole "lessons" prefix since promote is pair-scoped).
      qc.invalidateQueries({ queryKey: [...trainingKeys.all, "lessons"] });
      // MET-1 (INV-IA2): promote also writes discussion_rules + transition_
      // phrases['universal'] — /methodology (staleTime 30s) would stay stale.
      qc.invalidateQueries({ queryKey: methodologyKeys.all });
    },
  });
}

// ── Post-final pipeline status (case indicator) ──────────────────────
// Derived status of the two post-final pipelines for one case: whether voice
// learning + halacha extraction ran, succeeded, why not, and how many halachot
// were extracted. Backs the indicator in the drafts panel's final-decision section.

export type VoiceLearningStatus = {
  ran: boolean;
  outcome: "succeeded" | "failed" | "not_run";
  error: string | null;
  pair_status: string; // final_received | analyzed | lessons_folded | ''
  lessons_count: number;
  style_corpus_enrolled: boolean;
  lessons_proposed: number;
  analyzed_at: string | null;
};

export type HalachaExtractionStatus = {
  enrolled_in_corpus: boolean;
  not_enrolled_reason: string | null;
  status:
    | "pending"
    | "processing"
    | "completed"
    | "failed"
    | "partial"
    | "extraction_failed"
    | "no_chunks"
    | "busy"
    | null;
  failed?: boolean;
  halachot_count: number;
  approved: number;
  pending: number;
  rejected: number;
};

export type CaseLearningStatus = {
  final_uploaded: boolean;
  voice_learning: VoiceLearningStatus;
  halacha_extraction: HalachaExtractionStatus;
};

/** Whether the indicator should keep polling (a pipeline is mid-flight). */
function isLearningInFlight(s: CaseLearningStatus | undefined): boolean {
  const h = s?.halacha_extraction.status;
  return h === "processing" || h === "pending" || h === "busy";
}

export function useCaseLearningStatus(caseNumber: string, enabled = true) {
  return useQuery({
    queryKey: learningKeys.caseStatus(caseNumber),
    queryFn: ({ signal }) =>
      apiRequest<CaseLearningStatus>(
        `/api/cases/${caseNumber}/learning-status`,
        { signal },
      ),
    enabled,
    staleTime: 15_000,
    // Background pipelines: refetch gently while something is still running.
    refetchInterval: (query) =>
      isLearningInFlight(query.state.data as CaseLearningStatus | undefined)
        ? 15_000
        : false,
  });
}
