"use client";

/*
 * Upload a Daphna decision into the style corpus, from the /training page.
 *
 * The flow is three explicit steps inside the same sheet:
 *   1. file picker → POST /api/upload                    (gets sanitized filename)
 *   2. preview     → POST /api/training/analyze          (proofread + auto-extracted meta)
 *                    chair can correct decision_number / decision_date / subjects
 *   3. commit      → POST /api/training/upload           (background task)
 *                    progress watched via SSE; on completion we invalidate
 *                    corpus + style-report so the new row appears.
 *
 * The Sheet UX mirrors precedent-upload-sheet.tsx: same dir="rtl", same
 * loading + error patterns, same toast on success. The reason this isn't
 * a single one-click upload is that style-corpus rows are write-once
 * (we don't allow editing full_text), so the chair MUST see the proofread
 * preview before committing — otherwise a bad OCR/proofread can silently
 * pollute the style portrait.
 */

import { useEffect, useState } from "react";
import { Upload, Loader2, CheckCircle2, AlertCircle, FileText } from "lucide-react";
import { toast } from "sonner";
import { useQueryClient } from "@tanstack/react-query";
import {
  Sheet, SheetContent, SheetHeader, SheetTitle, SheetDescription,
} from "@/components/ui/sheet";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Progress } from "@/components/ui/progress";
import { Badge } from "@/components/ui/badge";
import {
  trainingKeys,
  useAnalyzeTraining,
  useCommitTrainingUpload,
  useUploadFile,
  type AnalyzeTrainingResponse,
} from "@/lib/api/training";
import { useProgress } from "@/lib/api/documents";

const ACCEPT = ".pdf,.docx,.doc,.rtf,.txt,.md";

type Props = {
  open: boolean;
  onOpenChange: (open: boolean) => void;
};

type Stage = "pick" | "analyzing" | "preview" | "committing" | "done" | "error";

export function TrainingUploadDialog({ open, onOpenChange }: Props) {
  const [stage, setStage] = useState<Stage>("pick");
  const [file, setFile] = useState<File | null>(null);
  const [analysis, setAnalysis] = useState<AnalyzeTrainingResponse | null>(null);
  // editable copies of the auto-extracted metadata
  const [decisionNumber, setDecisionNumber] = useState("");
  const [decisionDate, setDecisionDate] = useState("");
  const [subjectsRaw, setSubjectsRaw] = useState("");
  const [title, setTitle] = useState("");
  const [taskId, setTaskId] = useState<string | null>(null);
  const [errorMsg, setErrorMsg] = useState("");

  const uploadFile = useUploadFile();
  const analyze = useAnalyzeTraining();
  const commit = useCommitTrainingUpload();
  const progress = useProgress(taskId);
  const qc = useQueryClient();

  // Reset everything when the sheet closes — important because Sheet keeps
  // the component mounted between opens. The cascade-render warning is the
  // intended behavior (reset is the side effect we want).
  useEffect(() => {
    if (open) return;
    /* eslint-disable react-hooks/set-state-in-effect */
    setStage("pick"); setFile(null); setAnalysis(null);
    setDecisionNumber(""); setDecisionDate(""); setSubjectsRaw("");
    setTitle(""); setTaskId(null); setErrorMsg("");
    /* eslint-enable react-hooks/set-state-in-effect */
  }, [open]);

  // Watch background task. When complete, invalidate corpus + report so the
  // new row + updated stats show up automatically. The setStage call here
  // is the deliberate UX (success card → auto-close) — synchronizing UI
  // with the external SSE stream is exactly what effects are for.
  useEffect(() => {
    if (!progress) return;
    if (progress.status === "completed") {
      qc.invalidateQueries({ queryKey: trainingKeys.corpus() });
      qc.invalidateQueries({ queryKey: trainingKeys.report() });
      // eslint-disable-next-line react-hooks/set-state-in-effect
      setStage("done");
      toast.success(`החלטה ${decisionNumber || analysis?.decision_number || ""} נוספה לקורפוס`);
      const t = window.setTimeout(() => onOpenChange(false), 1500);
      return () => window.clearTimeout(t);
    }
    if (progress.status === "failed") {
      setStage("error");
      setErrorMsg(progress.error || "כשל בעיבוד");
    }
  }, [progress, analysis, decisionNumber, qc, onOpenChange]);

  const onPickFile = async (f: File | null) => {
    setFile(f);
    setErrorMsg("");
    if (!f) return;
    setStage("analyzing");
    try {
      const { filename } = await uploadFile.mutateAsync(f);
      const result = await analyze.mutateAsync(filename);
      setAnalysis(result);
      setDecisionNumber(result.decision_number);
      setDecisionDate(result.decision_date);
      setSubjectsRaw(result.subject_categories.join(", "));
      // Default title from the original filename stem (chair can override).
      const stem = f.name.replace(/\.[^.]+$/, "");
      setTitle(stem);
      setStage("preview");
    } catch (e) {
      setStage("error");
      setErrorMsg(e instanceof Error ? e.message : "כשל בקריאת הקובץ");
    }
  };

  const onCommit = async () => {
    if (!analysis) return;
    setStage("committing");
    setErrorMsg("");
    try {
      const subjects = subjectsRaw
        .split(/[,،]/)
        .map((s) => s.trim())
        .filter(Boolean);
      const res = await commit.mutateAsync({
        filename: analysis.filename,
        decision_number: decisionNumber.trim(),
        decision_date: decisionDate || "",
        subject_categories: subjects,
        title: title.trim() || undefined,
      });
      setTaskId(res.task_id);
    } catch (e) {
      setStage("error");
      // 409 = duplicate decision_number — surface the backend's Hebrew message.
      setErrorMsg(e instanceof Error ? e.message : "כשל בהעלאה");
    }
  };

  const isProcessing =
    stage === "analyzing" || stage === "committing" ||
    (taskId !== null && progress?.status !== "completed" && progress?.status !== "failed");
  const progressStep = (progress as { step?: string } | null)?.step;

  return (
    <Sheet open={open} onOpenChange={onOpenChange}>
      <SheetContent side="left" className="w-full sm:max-w-2xl overflow-y-auto" dir="rtl">
        <SheetHeader>
          <SheetTitle className="text-navy">העלאת החלטה לקורפוס הסגנון</SheetTitle>
          <SheetDescription className="text-ink-muted">
            הקובץ יעבור הגהה (סינון Nevo, ניקוד), חילוץ אוטומטי של מספר תיק, תאריך
            ונושאים, ויוטמע ב-style_corpus עם chunks ו-embeddings. תוכל לתקן את
            פרטי המטא-דאטה לפני שמירה.
          </SheetDescription>
        </SheetHeader>

        <div className="px-6 pb-6 mt-4 space-y-4">
          {/* Step 1: pick */}
          {stage === "pick" && (
            <div className="space-y-2">
              <Label htmlFor="t-file">קובץ ההחלטה (PDF / DOCX / DOC / RTF / TXT / MD)</Label>
              <Input
                id="t-file" type="file" accept={ACCEPT}
                onChange={(e) => onPickFile(e.target.files?.[0] ?? null)}
              />
              <p className="text-[0.78rem] text-ink-muted">
                המערכת תחלץ מהקובץ את מספר התיק, התאריך והנושאים. תוכל לערוך
                לפני השמירה.
              </p>
            </div>
          )}

          {/* Stage 2: analyzing the file */}
          {stage === "analyzing" && (
            <div className="rounded-lg border border-rule bg-rule-soft/40 p-6 space-y-2 text-center">
              <Loader2 className="w-5 h-5 animate-spin mx-auto text-navy" />
              <p className="text-sm text-navy">מבצע הגהה וחילוץ מטא-דאטה…</p>
              <p className="text-[0.78rem] text-ink-muted">
                {file?.name}
              </p>
            </div>
          )}

          {/* Stage 3: preview + editable metadata */}
          {stage === "preview" && analysis && (
            <form
              className="space-y-4"
              onSubmit={(e) => { e.preventDefault(); onCommit(); }}
            >
              <div className="rounded-lg border border-rule bg-surface px-4 py-3">
                <h3 className="text-[0.78rem] uppercase tracking-wider text-gold-deep font-semibold mb-2">
                  תצוגה מקדימה של הטקסט הנקי
                </h3>
                <p className="text-sm text-ink leading-relaxed line-clamp-6 whitespace-pre-wrap">
                  {analysis.preview}
                </p>
                <div className="mt-2 flex items-center gap-3 text-[0.72rem] text-ink-muted tabular-nums">
                  <span className="flex items-center gap-1">
                    <FileText className="w-3 h-3" />
                    {analysis.chars.toLocaleString("he-IL")} תווים
                  </span>
                </div>
              </div>

              <div className="grid grid-cols-2 gap-3">
                <div className="space-y-1">
                  <Label htmlFor="t-decision-number">מספר ההחלטה</Label>
                  <Input
                    id="t-decision-number"
                    value={decisionNumber}
                    onChange={(e) => setDecisionNumber(e.target.value)}
                    placeholder="1130-25"
                    dir="rtl"
                  />
                </div>
                <div className="space-y-1">
                  <Label htmlFor="t-decision-date">תאריך ההחלטה</Label>
                  <Input
                    id="t-decision-date" type="date"
                    value={decisionDate}
                    onChange={(e) => setDecisionDate(e.target.value)}
                  />
                </div>
              </div>

              <div className="space-y-1">
                <Label htmlFor="t-title">כותרת קצרה (אופציונלי)</Label>
                <Input
                  id="t-title" value={title}
                  onChange={(e) => setTitle(e.target.value)}
                  placeholder="ARAR-25-1130 - כרמל יצחק" dir="rtl"
                />
              </div>

              <div className="space-y-1">
                <Label htmlFor="t-subjects">נושאים (מופרדים בפסיקים)</Label>
                <Input
                  id="t-subjects" value={subjectsRaw}
                  onChange={(e) => setSubjectsRaw(e.target.value)}
                  placeholder="חניה, קווי בניין, שימוש חורג" dir="rtl"
                />
                {analysis.subject_categories.length > 0 && (
                  <div className="flex flex-wrap gap-1 mt-1">
                    <span className="text-[0.72rem] text-ink-muted">חולץ אוטומטית:</span>
                    {analysis.subject_categories.map((s) => (
                      <Badge key={s} variant="outline"
                        className="text-[0.7rem] bg-gold-wash text-gold-deep border-gold/40">
                        {s}
                      </Badge>
                    ))}
                  </div>
                )}
              </div>

              {errorMsg && (
                <div className="rounded-lg border border-danger/40 bg-danger-bg p-3 flex items-center gap-2 text-danger text-sm">
                  <AlertCircle className="w-4 h-4 shrink-0" />
                  {errorMsg}
                </div>
              )}

              <div className="flex gap-2 justify-end pt-2">
                <Button type="button" variant="ghost"
                  onClick={() => onOpenChange(false)}
                  disabled={isProcessing}>
                  ביטול
                </Button>
                <Button type="submit" disabled={isProcessing || !decisionNumber.trim()}
                  className="bg-navy text-parchment hover:bg-navy-soft">
                  <Upload className="w-4 h-4 me-1" />
                  שמור בקורפוס
                </Button>
              </div>
            </form>
          )}

          {/* Stage 4: committing — background task progress */}
          {(stage === "committing" || (taskId && stage !== "done" && stage !== "error")) && (
            <div className="rounded-lg border border-rule bg-rule-soft/40 p-4 space-y-2">
              <div className="flex items-center gap-2 text-sm text-navy">
                <Loader2 className="w-4 h-4 animate-spin" />
                <span>{progressStep || "מעבד את ההחלטה לקורפוס"}</span>
              </div>
              <Progress value={progressStep ? 60 : 30} className="h-1.5" />
            </div>
          )}

          {/* Stage 5: success */}
          {stage === "done" && (
            <div className="rounded-lg border border-gold/40 bg-gold-wash p-4 flex items-center gap-2 text-gold-deep text-sm">
              <CheckCircle2 className="w-4 h-4" />
              ההחלטה נוספה לקורפוס בהצלחה.
            </div>
          )}

          {/* Stage 6: error (after a failed analyze or upload) */}
          {stage === "error" && (
            <div className="space-y-3">
              <div className="rounded-lg border border-danger/40 bg-danger-bg p-4 flex items-center gap-2 text-danger text-sm">
                <AlertCircle className="w-4 h-4 shrink-0" />
                {errorMsg || "שגיאה לא ידועה"}
              </div>
              <div className="flex gap-2 justify-end">
                <Button type="button" variant="ghost"
                  onClick={() => onOpenChange(false)}>
                  סגור
                </Button>
                <Button type="button"
                  onClick={() => { setStage("pick"); setErrorMsg(""); setFile(null); }}>
                  נסה קובץ אחר
                </Button>
              </div>
            </div>
          )}
        </div>
      </SheetContent>
    </Sheet>
  );
}
