"use client";

import { useEffect, useState, type ReactNode } from "react";
import { Button } from "@/components/ui/button";
import { Progress } from "@/components/ui/progress";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
  DialogFooter,
} from "@/components/ui/dialog";
import {
  CheckCircle2,
  Clock,
  Eye,
  Loader2,
  Trash2,
  XCircle,
} from "lucide-react";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { apiRequest } from "@/lib/api/client";
import { casesKeys } from "@/lib/api/cases";
import type { CaseDetail, CaseDocument } from "@/lib/api/cases";
import { DocumentTypeEditor } from "@/components/cases/document-type-editor";
import { formatDateShort as formatDate } from "@/lib/format-date";
import {
  documentGroup,
  DOC_GROUP_ORDER,
  DOC_GROUP_LABELS,
  DOC_GROUP_HINTS,
  type DocGroup,
} from "@/lib/doc-types";

/*
 * Document list for the case detail "מסמכים" tab. Uses the real document
 * row shape returned by the FastAPI case_get endpoint — see db.list_documents
 * and the `documents` schema in legal_mcp/services/db.py:
 *   id · case_id · doc_type · title · file_path · extraction_status ·
 *   page_count · created_at · practice_area · appeal_subtype · metadata
 *
 * Doc-type labels and tone classes live in @/lib/doc-types so the upload
 * sheet, the inline editor, and this panel all stay in sync.
 */

const STATUS_LABELS: Record<string, string> = {
  pending:    "בהמתנה",
  processing: "בעיבוד",
  completed:  "הושלם",
  proofread:  "הוגה",
  failed:     "נכשל",
  error:      "שגיאה",
};

/** Sort priority — lower = higher in list */
const STATUS_ORDER: Record<string, number> = {
  failed:     0,
  error:      0,
  processing: 1,
  pending:    2,
  completed:  3,
  proofread:  3,
};

function statusOrder(s: string): number {
  return STATUS_ORDER[s] ?? 3;
}

function StatusIcon({ status }: { status: string }) {
  switch (status) {
    case "completed":
    case "proofread":
      return <CheckCircle2 className="w-4 h-4 text-success shrink-0" />;
    case "processing":
      return <Loader2 className="w-4 h-4 text-gold animate-spin shrink-0" />;
    case "pending":
      return <Clock className="w-4 h-4 text-ink-muted shrink-0" />;
    case "failed":
    case "error":
      return <XCircle className="w-4 h-4 text-danger shrink-0" />;
    default:
      return <Clock className="w-4 h-4 text-ink-muted shrink-0" />;
  }
}

function filenameFromPath(path: string): string {
  const parts = path.split("/");
  return parts[parts.length - 1] || path;
}

/* ── Document text preview dialog ──────────────────────────────── */

function DocumentPreviewDialog({
  doc,
  open,
  onOpenChange,
}: {
  doc: CaseDocument;
  open: boolean;
  onOpenChange: (v: boolean) => void;
}) {
  const [text, setText] = useState<string | null>(null);
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    if (!open) {
      /* eslint-disable react-hooks/set-state-in-effect -- reset on close */
      setText(null);
      setError(null);
      /* eslint-enable react-hooks/set-state-in-effect */
      return;
    }
    let cancelled = false;
    setLoading(true);
    setError(null);
    apiRequest<{ text: string }>(`/api/documents/${doc.id}/text`)
      .then((res) => { if (!cancelled) setText(res.text || "(ריק)"); })
      .catch(() => { if (!cancelled) setError("המסמך עדיין לא עובד או שאין בו טקסט"); })
      .finally(() => { if (!cancelled) setLoading(false); });
    return () => { cancelled = true; };
  }, [open, doc.id]);

  const displayName = doc.title || filenameFromPath(doc.file_path);

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-2xl max-h-[80vh] flex flex-col" dir="rtl">
        <DialogHeader>
          <DialogTitle className="text-right">{displayName}</DialogTitle>
          <DialogDescription className="sr-only">תצוגה מקדימה של תוכן המסמך</DialogDescription>
        </DialogHeader>
        <div className="flex-1 overflow-hidden">
          {loading && (
            <div className="flex items-center justify-center py-12">
              <Loader2 className="w-6 h-6 animate-spin text-gold" />
              <span className="ms-2 text-ink-muted text-sm">טוען מסמך...</span>
            </div>
          )}
          {error && (
            <div className="text-center py-12 text-danger text-sm">{error}</div>
          )}
          {text !== null && !loading && (
            <div className="h-[60vh] overflow-y-auto" dir="rtl">
              <pre className="whitespace-pre-wrap text-sm text-ink leading-relaxed font-sans p-2">
                {text}
              </pre>
            </div>
          )}
        </div>
        <DialogFooter showCloseButton />
      </DialogContent>
    </Dialog>
  );
}

/* ── Delete confirmation dialog ────────────────────────────────── */

function DeleteConfirmDialog({
  doc,
  caseNumber,
  open,
  onOpenChange,
}: {
  doc: CaseDocument;
  caseNumber: string;
  open: boolean;
  onOpenChange: (v: boolean) => void;
}) {
  const qc = useQueryClient();
  const deleteMutation = useMutation({
    mutationFn: () =>
      apiRequest(`/api/cases/${caseNumber}/documents/${doc.id}`, {
        method: "DELETE",
      }),
    onSuccess: () => {
      qc.invalidateQueries({ queryKey: casesKeys.all });
      onOpenChange(false);
    },
  });

  const displayName = doc.title || filenameFromPath(doc.file_path);

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent dir="rtl">
        <DialogHeader>
          <DialogTitle className="text-right">מחיקת מסמך</DialogTitle>
          <DialogDescription className="sr-only">אישור מחיקת המסמך מהתיק</DialogDescription>
        </DialogHeader>
        <p className="text-sm text-ink-muted text-right">
          האם למחוק את המסמך <strong>&ldquo;{displayName}&rdquo;</strong>?
          <br />
          פעולה זו אינה ניתנת לביטול.
        </p>
        <DialogFooter>
          <Button
            variant="destructive"
            onClick={() => deleteMutation.mutate()}
            disabled={deleteMutation.isPending}
          >
            {deleteMutation.isPending ? (
              <Loader2 className="w-4 h-4 animate-spin me-1" />
            ) : (
              <Trash2 className="w-4 h-4 me-1" />
            )}
            מחק
          </Button>
          <Button variant="outline" onClick={() => onOpenChange(false)}>
            ביטול
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

/* ── Single document row ───────────────────────────────────────── */

function DocumentRow({
  doc,
  caseNumber,
}: {
  doc: CaseDocument;
  caseNumber: string;
}) {
  const [previewOpen, setPreviewOpen] = useState(false);
  const [deleteOpen, setDeleteOpen] = useState(false);
  const displayName = doc.title || filenameFromPath(doc.file_path);
  const canPreview =
    doc.extraction_status === "completed" || doc.extraction_status === "proofread";

  const meta = doc.metadata as
    | { appraiser_side?: string; is_post_hearing?: boolean; protocol_scope?: string }
    | undefined;
  const isPostHearing = meta?.is_post_hearing === true;
  const protocolScope = meta?.protocol_scope;
  const isProtocol = doc.doc_type === "protocol";

  return (
    <>
      <li className="py-3 flex items-start gap-3 hover:bg-gold-wash/30 transition-colors px-2 -mx-2 rounded group">
        <StatusIcon status={doc.extraction_status} />
        <button
          type="button"
          className="flex-1 min-w-0 space-y-0.5 text-right cursor-pointer hover:underline decoration-gold/40 underline-offset-2 disabled:cursor-default disabled:no-underline"
          disabled={!canPreview}
          onClick={() => canPreview && setPreviewOpen(true)}
          title={canPreview ? "לחץ לצפייה במסמך" : "המסמך עדיין לא עובד"}
        >
          <div className="text-ink font-medium truncate flex items-center gap-1.5">
            {canPreview && <Eye className="w-3.5 h-3.5 text-ink-muted shrink-0" />}
            <span>{displayName}</span>
          </div>
          <div className="text-[0.72rem] text-ink-muted flex items-center gap-3 flex-wrap">
            {doc.page_count != null && (
              <span className="tabular-nums">{doc.page_count} עמ׳</span>
            )}
            {doc.created_at && <span>{formatDate(doc.created_at)}</span>}
          </div>
        </button>
        {isProtocol && (
          <span className="shrink-0 self-center rounded-full border border-rule bg-parchment px-2 py-0.5 text-[0.62rem] font-medium text-navy whitespace-nowrap">
            {protocolScope === "lower" ? "ועדה מקומית" : "ועדת הערר"}
          </span>
        )}
        {isPostHearing && (
          <span className="shrink-0 self-center rounded-full border border-info/40 bg-info-bg px-2 py-0.5 text-[0.62rem] font-medium text-info whitespace-nowrap">
            לאחר הדיון
          </span>
        )}
        {doc.doc_type && (
          <DocumentTypeEditor
            caseNumber={caseNumber}
            docId={doc.id}
            docType={doc.doc_type}
            appraiserSide={meta?.appraiser_side}
            isPostHearing={isPostHearing}
            protocolScope={protocolScope}
          />
        )}
        <button
          type="button"
          className="shrink-0 p-1 rounded text-ink-muted/40 hover:text-danger hover:bg-danger-bg transition-colors opacity-0 group-hover:opacity-100"
          onClick={() => setDeleteOpen(true)}
          title="מחק מסמך"
        >
          <Trash2 className="w-4 h-4" />
        </button>
      </li>
      {previewOpen && (
        <DocumentPreviewDialog
          doc={doc}
          open={previewOpen}
          onOpenChange={setPreviewOpen}
        />
      )}
      {deleteOpen && (
        <DeleteConfirmDialog
          doc={doc}
          caseNumber={caseNumber}
          open={deleteOpen}
          onOpenChange={setDeleteOpen}
        />
      )}
    </>
  );
}

/* ── Main panel ────────────────────────────────────────────────── */

// IA-redesign mockup 17 — card with a parchment header band wrapping the
// (unchanged) document list. Module-level so it isn't re-created during render
// (React Compiler: "Cannot create components during render").
function DocumentsShell({ count, children }: { count: number; children: ReactNode }) {
  return (
    <div className="rounded-lg border border-rule bg-surface shadow-sm overflow-hidden">
      <div className="px-5 py-3.5 border-b border-rule-soft bg-parchment text-[0.92rem] font-semibold text-navy">
        מסמכי התיק
        {count > 0 && (
          <span className="ms-2 text-[0.72rem] text-ink-muted font-medium tabular-nums">
            ({count})
          </span>
        )}
      </div>
      <div className="px-5 py-4">{children}</div>
    </div>
  );
}

/* ── Group section header ──────────────────────────────────────────
 * The list is split into four convenience buckets (see documentGroup).
 * The number is the fixed 1-4 position in DOC_GROUP_ORDER so a group keeps
 * its identity even when earlier groups are empty and hidden. */
function GroupHeader({ group, count }: { group: DocGroup; count: number }) {
  const index = DOC_GROUP_ORDER.indexOf(group) + 1;
  return (
    <div className="flex items-center gap-2.5 px-2 -mx-2 py-2 border-b border-rule-soft bg-parchment/50">
      <span className="w-[19px] h-[19px] shrink-0 rounded-full bg-navy text-cream text-[0.66rem] font-bold flex items-center justify-center tabular-nums">
        {index}
      </span>
      <span className="text-[0.8rem] font-bold text-navy shrink-0">
        {DOC_GROUP_LABELS[group]}
      </span>
      <span className="shrink-0 text-[0.62rem] font-bold text-gold-deep bg-gold-wash border border-rule rounded-full px-1.5 tabular-nums">
        {count}
      </span>
      <span className="text-[0.66rem] text-ink-muted font-medium truncate">
        {DOC_GROUP_HINTS[group]}
      </span>
    </div>
  );
}

export function DocumentsPanel({
  data,
}: {
  data?: CaseDetail;
}) {
  const docs = data?.documents ?? [];
  const caseNumber = data?.case_number ?? "";

  if (docs.length === 0) {
    return (
      <DocumentsShell count={docs.length}>
        <div className="text-center py-12 text-ink-muted">
          <div className="text-gold text-2xl mb-2" aria-hidden="true">❦</div>
          <p className="text-sm">אין מסמכים בתיק זה</p>
        </div>
      </DocumentsShell>
    );
  }

  const sorted = [...docs].sort(
    (a, b) => statusOrder(a.extraction_status) - statusOrder(b.extraction_status),
  );

  // Bucket into the four overview groups. Iterating `sorted` preserves the
  // within-group status ordering. Grouping is display-only — see documentGroup.
  const grouped = new Map<DocGroup, CaseDocument[]>();
  for (const doc of sorted) {
    const g = documentGroup(doc.doc_type, doc.metadata);
    const bucket = grouped.get(g);
    if (bucket) bucket.push(doc);
    else grouped.set(g, [doc]);
  }

  const done = docs.filter(
    (d) => d.extraction_status === "completed" || d.extraction_status === "proofread",
  ).length;
  const processing = docs.filter((d) => d.extraction_status === "processing").length;
  const pending = docs.filter((d) => d.extraction_status === "pending").length;
  const failed = docs.filter(
    (d) => d.extraction_status === "failed" || d.extraction_status === "error",
  ).length;
  const hasIncomplete = processing > 0 || pending > 0 || failed > 0;
  const pct = docs.length > 0 ? Math.round((done / docs.length) * 100) : 0;

  return (
    <DocumentsShell count={docs.length}>
      <div className="space-y-3">
      {hasIncomplete && (
        <div className="rounded-lg border border-rule bg-parchment/40 px-4 py-3 space-y-2" dir="rtl">
          <div className="flex items-center gap-4 text-[0.78rem] flex-wrap">
            {done > 0 && (
              <span className="flex items-center gap-1 text-success">
                <CheckCircle2 className="w-3.5 h-3.5" />
                {done} {STATUS_LABELS.completed}
              </span>
            )}
            {processing > 0 && (
              <span className="flex items-center gap-1 text-gold-deep">
                <Loader2 className="w-3.5 h-3.5 animate-spin" />
                {processing} {STATUS_LABELS.processing}
              </span>
            )}
            {pending > 0 && (
              <span className="flex items-center gap-1 text-ink-muted">
                <Clock className="w-3.5 h-3.5" />
                {pending} {STATUS_LABELS.pending}
              </span>
            )}
            {failed > 0 && (
              <span className="flex items-center gap-1 text-danger">
                <XCircle className="w-3.5 h-3.5" />
                {failed} {STATUS_LABELS.failed}
              </span>
            )}
          </div>
          <Progress
            value={pct}
            className={failed > 0 && done === 0 ? "[&>div]:bg-danger" : ""}
          />
        </div>
      )}

      <div className="max-h-[70vh] overflow-y-auto overflow-x-hidden space-y-2" dir="rtl">
        {DOC_GROUP_ORDER.map((group) => {
          const groupDocs = grouped.get(group);
          if (!groupDocs || groupDocs.length === 0) return null;
          return (
            <section key={group}>
              <GroupHeader group={group} count={groupDocs.length} />
              <ul className="divide-y divide-rule" dir="rtl">
                {groupDocs.map((doc) => (
                  <DocumentRow key={doc.id} doc={doc} caseNumber={caseNumber} />
                ))}
              </ul>
            </section>
          );
        })}
      </div>
      </div>
    </DocumentsShell>
  );
}
