"use client";

import { useState } from "react";
import Link from "next/link";
import { Trash2, Plus, Pencil, Wand2, Loader2 } from "lucide-react";
import { toast } from "sonner";
import {
  Table, TableBody, TableCell, TableHead, TableHeader, TableRow,
} from "@/components/ui/table";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Input } from "@/components/ui/input";
import { Progress } from "@/components/ui/progress";
import { Skeleton } from "@/components/ui/skeleton";
import { cn } from "@/lib/utils";
import {
  Select, SelectContent, SelectItem, SelectTrigger, SelectValue,
} from "@/components/ui/select";
import {
  usePrecedents,
  useDeletePrecedent,
  useRequestHalachotExtraction,
  isPrecedentActive,
  type Precedent,
  type PracticeArea,
} from "@/lib/api/precedent-library";
import { PRACTICE_AREAS, practiceAreaShort } from "./practice-area";
import { PrecedentUploadSheet } from "./precedent-upload-sheet";
import { PrecedentEditSheet } from "./precedent-edit-sheet";
import {
  FormattedCitation,
  CitationCopyButton,
} from "./formatted-citation";
import { formatDateShort as formatDate } from "@/lib/format-date";

function cleanCitation(s: string | null | undefined): string {
  if (!s) return "—";
  return s.replace(/[‎‏‪-‮⁦-⁩]/g, "").trim();
}

// Show the "extract halachot" button only when the precedent hasn't had a
// successful (or even attempted) extraction yet. Hide while processing or
// after completion to avoid duplicate requests.
function needsHalachaExtraction(p: Precedent): boolean {
  if (p.extraction_status !== "completed") return false; // text not ready
  if (p.halacha_extraction_status === "processing") return false;
  if (p.halacha_extraction_status === "completed") return false;
  if (p.halacha_extraction_status === "pending" && p.halacha_extraction_requested_at) {
    return false; // already queued
  }
  // Remaining cases: pending+no-requested_at (never tried) or failed (retry).
  return true;
}

function ActivePill({ label }: { label: string }) {
  return (
    <Badge
      variant="outline"
      className="bg-gold-wash text-gold-deep border-gold/40 shimmer-active"
    >
      {label}
    </Badge>
  );
}

function StatusPill({ p }: { p: Precedent }) {
  if (p.extraction_status === "failed") {
    return (
      <Badge variant="outline" className="bg-danger-bg text-danger border-danger/40">
        נכשל
      </Badge>
    );
  }
  if (p.extraction_status === "processing") {
    return <ActivePill label="מעבד טקסט" />;
  }
  if (p.extraction_status !== "completed") {
    return (
      <Badge variant="outline" className="bg-rule-soft text-ink-muted">
        בתור
      </Badge>
    );
  }
  // Metadata extraction (orthogonal one-off re-extract). Surface it while
  // active so the chair sees the queued button actually ran on something.
  if (p.metadata_extraction_status === "processing") {
    return <ActivePill label="מחלץ מטא-דאטה" />;
  }
  if (p.metadata_extraction_status === "failed") {
    return (
      <Badge variant="outline" className="bg-danger-bg text-danger border-danger/40">
        מטא-דאטה נכשל
      </Badge>
    );
  }
  if (
    p.metadata_extraction_requested_at &&
    p.metadata_extraction_status !== "completed"
  ) {
    return (
      <Badge variant="outline" className="bg-rule-soft text-ink-muted">
        ממתין למטא-דאטה
      </Badge>
    );
  }
  if (p.halacha_extraction_status === "processing") {
    return <ActivePill label="מחלץ הלכות" />;
  }
  if (p.halacha_extraction_status === "failed") {
    return (
      <Badge variant="outline" className="bg-danger-bg text-danger border-danger/40">
        חילוץ נכשל
      </Badge>
    );
  }
  if (p.halacha_extraction_status === "pending") {
    if (p.halacha_extraction_requested_at) {
      return (
        <Badge variant="outline" className="bg-rule-soft text-ink-muted">
          ממתין לחילוץ
        </Badge>
      );
    }
    return (
      <Badge variant="outline" className="bg-rule-soft text-ink-muted">
        לא חולץ
      </Badge>
    );
  }
  if (p.halachot_count === 0) {
    return <Badge variant="outline">ללא הלכות</Badge>;
  }
  // Split the count into approved / pending / rejected so a high total no
  // longer reads as "lots waiting" when the remainder is actually rejected.
  // Only pending_review needs the chair — it (and only it) is highlighted red
  // and tints the row. deferred ("snoozed", #84) was deliberately set aside and
  // is excluded from the active review queue, so it never alarms — it shows as
  // a separate muted segment, surfaced only when present.
  const hasPending = p.pending_count > 0;
  const title =
    `${p.approved_count} מאושרות · ${p.pending_count} ממתינות · ${p.rejected_count} נדחו` +
    (p.deferred_count > 0 ? ` · ${p.deferred_count} נדחו למועד` : "");
  return (
    <Badge
      variant="outline"
      dir="ltr"
      className="bg-gold-wash text-gold-deep border-gold/40 tabular-nums"
      title={title}
    >
      <span className="text-success font-semibold">{p.approved_count}</span>
      <span className="text-ink-light">/</span>
      <span className={hasPending ? "text-danger font-bold" : "text-ink-light"}>
        {p.pending_count}
      </span>
      <span className="text-ink-light">/</span>
      <span className="text-ink-muted">{p.rejected_count}</span>
      {p.deferred_count > 0 ? (
        <span className="ms-1 text-[0.7rem] text-ink-light">
          (⏸ {p.deferred_count})
        </span>
      ) : null}
      <span className="ms-1 text-[0.7rem] text-ink-muted">הלכות</span>
    </Badge>
  );
}

// Rows with halachot still awaiting the chair get a reddish wash so the
// "needs attention" queue is visible at a glance without opening each row.
function rowClassName(p: Precedent): string {
  return p.pending_count > 0
    ? "border-rule bg-danger-bg/40 hover:bg-danger-bg/60 align-top"
    : "border-rule hover:bg-gold-wash/30 align-top";
}

function CourtRow({ p, onEdit }: { p: Precedent; onEdit: (id: string) => void }) {
  const del = useDeletePrecedent();
  const reqHalachot = useRequestHalachotExtraction();
  const active = isPrecedentActive(p);
  const showExtractHalachot = needsHalachaExtraction(p);

  const onDelete = async () => {
    if (active) {
      toast.error("מתבצע עיבוד — לא ניתן למחוק עכשיו.");
      return;
    }
    if (!window.confirm(`למחוק את ${p.case_number}?`)) return;
    try {
      await del.mutateAsync(p.id);
      toast.success("נמחק");
    } catch (e) {
      toast.error(e instanceof Error ? e.message : "שגיאה");
    }
  };

  const onExtractHalachot = async () => {
    try {
      await reqHalachot.mutateAsync(p.id);
      toast.success("סומן לחילוץ הלכות. הריצי מ-Claude Code: precedent_process_pending_halachot");
    } catch (e) {
      toast.error(e instanceof Error ? e.message : "שגיאה");
    }
  };

  return (
    <TableRow className={rowClassName(p)}>
      <TableCell
        className="font-semibold text-navy text-right whitespace-normal break-words min-w-[280px] max-w-[420px] py-3"
        dir="rtl"
      >
        <div className="flex items-start justify-between gap-2">
          <Link
            href={`/precedents/${p.id}`}
            className="hover:underline hover:text-gold-deep block min-w-0"
            dir="auto"
          >
            {p.citation_formatted ? (
              <FormattedCitation
                citation={p.citation_formatted}
                className="block leading-snug"
              />
            ) : (
              cleanCitation(p.case_number)
            )}
          </Link>
          {p.citation_formatted ? (
            <CitationCopyButton citation={p.citation_formatted} size="xs" />
          ) : null}
        </div>
      </TableCell>
      {/* Column "שם / ערכאה" hidden by request (case_name often equals case_number prefix). Keep field in DB; restore by un-hiding. */}
      <TableCell className="hidden text-ink whitespace-normal break-words max-w-[260px] py-3">
        <div className="font-medium">{cleanCitation(p.case_name)}</div>
        {p.court ? <div className="text-[0.72rem] text-ink-muted">{p.court}</div> : null}
      </TableCell>
      <TableCell className="text-ink-muted">{p.date ? formatDate(p.date) : <span className="text-ink-light">—</span>}</TableCell>
      <TableCell>
        {p.practice_area ? (
          <Badge variant="outline" className="bg-navy-soft/40 text-navy border-navy/30">
            {practiceAreaShort(p.practice_area)}
          </Badge>
        ) : <span className="text-ink-light">—</span>}
      </TableCell>
      <TableCell className="text-ink-muted text-[0.78rem]">
        {p.precedent_level || <span className="text-ink-light">—</span>}
      </TableCell>
      <TableCell><StatusPill p={p} /></TableCell>
      <TableCell className="text-end">
        <div className="flex items-center gap-1 justify-end">
          <Button variant="ghost" size="sm" onClick={() => onEdit(p.id)}
            aria-label={`ערוך את ${p.case_number}`} title="ערוך"
            className="text-ink-muted hover:text-navy">
            <Pencil className="w-4 h-4" />
          </Button>
          {showExtractHalachot && (
            <Button variant="ghost" size="sm" onClick={onExtractHalachot}
              disabled={reqHalachot.isPending}
              aria-label={`חלץ הלכות מ-${p.case_number}`}
              title="חלץ הלכות"
              className="text-gold-deep hover:text-gold-deep hover:bg-gold-wash disabled:opacity-30">
              <Wand2 className="w-4 h-4" />
            </Button>
          )}
          <Button variant="ghost" size="sm" onClick={onDelete}
            disabled={del.isPending || active}
            aria-label={`מחק את ${p.case_number}`}
            title={active ? "מתבצע עיבוד — לא ניתן למחוק" : "מחק"}
            className="text-danger hover:text-danger hover:bg-danger-bg disabled:opacity-30">
            <Trash2 className="w-4 h-4" />
          </Button>
        </div>
      </TableCell>
    </TableRow>
  );
}

function CommitteeRow({ p, onEdit }: { p: Precedent; onEdit: (id: string) => void }) {
  const del = useDeletePrecedent();
  const reqHalachot = useRequestHalachotExtraction();
  const active = isPrecedentActive(p);
  const showExtractHalachot = needsHalachaExtraction(p);

  const onDelete = async () => {
    if (active) {
      toast.error("מתבצע עיבוד — לא ניתן למחוק עכשיו.");
      return;
    }
    if (!window.confirm(`למחוק את ${p.case_number}?`)) return;
    try {
      await del.mutateAsync(p.id);
      toast.success("נמחק");
    } catch (e) {
      toast.error(e instanceof Error ? e.message : "שגיאה");
    }
  };

  const onExtractHalachot = async () => {
    try {
      await reqHalachot.mutateAsync(p.id);
      toast.success("סומן לחילוץ הלכות. הריצי מ-Claude Code: precedent_process_pending_halachot");
    } catch (e) {
      toast.error(e instanceof Error ? e.message : "שגיאה");
    }
  };

  return (
    <TableRow className={rowClassName(p)}>
      <TableCell
        className="font-semibold text-navy text-right whitespace-normal break-words min-w-[200px] max-w-[320px] py-3"
        dir="rtl"
      >
        <div className="flex items-start justify-between gap-2">
          <Link
            href={`/precedents/${p.id}`}
            className="hover:underline hover:text-gold-deep block min-w-0"
            dir="auto"
          >
            {p.citation_formatted ? (
              <FormattedCitation
                citation={p.citation_formatted}
                className="block leading-snug"
              />
            ) : (
              cleanCitation(p.case_number)
            )}
          </Link>
          {p.citation_formatted ? (
            <CitationCopyButton citation={p.citation_formatted} size="xs" />
          ) : null}
        </div>
      </TableCell>
      {/* Column "שם" hidden by request (case_name often equals case_number prefix). Keep field in DB; restore by un-hiding. */}
      <TableCell className="hidden text-ink whitespace-normal break-words max-w-[220px] py-3">
        <div className="font-medium">{cleanCitation(p.case_name)}</div>
      </TableCell>
      <TableCell className="text-ink-muted text-[0.78rem]">
        {p.district || <span className="text-ink-light">—</span>}
      </TableCell>
      <TableCell className="text-ink-muted text-[0.78rem]">
        {p.chair_name || <span className="text-ink-light">—</span>}
      </TableCell>
      <TableCell className="text-ink-muted">{p.date ? formatDate(p.date) : <span className="text-ink-light">—</span>}</TableCell>
      <TableCell>
        {p.practice_area ? (
          <Badge variant="outline" className="bg-navy-soft/40 text-navy border-navy/30">
            {practiceAreaShort(p.practice_area)}
          </Badge>
        ) : <span className="text-ink-light">—</span>}
      </TableCell>
      <TableCell><StatusPill p={p} /></TableCell>
      <TableCell className="text-end">
        <div className="flex items-center gap-1 justify-end">
          <Button variant="ghost" size="sm" onClick={() => onEdit(p.id)}
            aria-label={`ערוך את ${p.case_number}`} title="ערוך"
            className="text-ink-muted hover:text-navy">
            <Pencil className="w-4 h-4" />
          </Button>
          {showExtractHalachot && (
            <Button variant="ghost" size="sm" onClick={onExtractHalachot}
              disabled={reqHalachot.isPending}
              aria-label={`חלץ הלכות מ-${p.case_number}`}
              title="חלץ הלכות"
              className="text-gold-deep hover:text-gold-deep hover:bg-gold-wash disabled:opacity-30">
              <Wand2 className="w-4 h-4" />
            </Button>
          )}
          <Button variant="ghost" size="sm" onClick={onDelete}
            disabled={del.isPending || active}
            aria-label={`מחק את ${p.case_number}`}
            title={active ? "מתבצע עיבוד — לא ניתן למחוק" : "מחק"}
            className="text-danger hover:text-danger hover:bg-danger-bg disabled:opacity-30">
            <Trash2 className="w-4 h-4" />
          </Button>
        </div>
      </TableCell>
    </TableRow>
  );
}

/**
 * Live banner for the metadata-extraction queue. The local-MCP worker
 * (`precedent_process_pending kind=metadata`) drains stamped rows serially;
 * while it runs, rows carry metadata_extraction_status='processing' (current
 * item) or a request timestamp (still queued). We surface a real, advancing
 * percentage by tracking the session high-water-mark of the queue depth:
 * percent = (peak - remaining) / peak. Hidden when the queue is empty.
 */
function MetadataQueueBanner({ items }: { items: Precedent[] }) {
  const processing = items.filter(
    (p) => p.metadata_extraction_status === "processing",
  ).length;
  const pending = items.filter(
    (p) =>
      p.metadata_extraction_status !== "processing" &&
      p.metadata_extraction_requested_at !== null &&
      p.metadata_extraction_status !== "completed" &&
      p.metadata_extraction_status !== "failed",
  ).length;
  const remaining = processing + pending;

  // Session high-water-mark of the queue depth, using React's documented
  // "adjust state during render" pattern (no effect, no ref-in-render). React
  // re-renders immediately without committing the intermediate UI. Resets to 0
  // when the queue drains, so the next batch starts a fresh 0→100% sweep.
  const [peak, setPeak] = useState(0);
  if (remaining === 0) {
    if (peak !== 0) setPeak(0);
  } else if (remaining > peak) {
    setPeak(remaining);
  }

  if (remaining === 0) return null;
  const done = Math.max(0, peak - remaining);
  const percent = peak > 0 ? Math.round((done / peak) * 100) : 0;

  return (
    <div className="rounded-lg border border-gold/40 bg-gold-wash/50 p-4 space-y-2">
      <div className="flex items-center gap-2 text-sm text-gold-deep">
        <Loader2 className="w-4 h-4 animate-spin shrink-0" />
        <span>
          חילוץ מטא-דאטה פעיל — מעבד {processing}, נותרו {pending} בתור
          {peak > 0 ? ` · ${done}/${peak}` : ""}
        </span>
      </div>
      <Progress value={percent} className="h-1.5" />
    </div>
  );
}

function SegButton({
  active, onClick, label, count,
}: {
  active: boolean;
  onClick: () => void;
  label: string;
  count?: number;
}) {
  return (
    <button
      type="button"
      onClick={onClick}
      aria-pressed={active}
      className={cn(
        "flex items-center gap-2 rounded-md px-4 py-1.5 text-sm font-semibold transition-colors",
        active
          ? "bg-surface text-navy shadow-sm"
          : "text-ink-muted hover:text-navy",
      )}
    >
      {label}
      {count !== undefined && (
        <Badge
          variant="outline"
          className={cn(
            "text-[0.72rem]",
            active ? "border-navy/30 text-navy" : "text-ink-muted",
          )}
        >
          {count}
        </Badge>
      )}
    </button>
  );
}

function TableSkeleton({ cols }: { cols: number }) {
  return (
    <>
      {[...Array(4)].map((_, i) => (
        <TableRow key={i} className="border-rule">
          {[...Array(cols)].map((_, j) => (
            <TableCell key={j}><Skeleton className="h-5 w-full" /></TableCell>
          ))}
        </TableRow>
      ))}
    </>
  );
}

export function LibraryListPanel() {
  const [practiceArea, setPracticeArea] = useState<PracticeArea>("");
  const [search, setSearch] = useState("");
  const [uploadOpen, setUploadOpen] = useState(false);
  const [editingId, setEditingId] = useState<string | null>(null);
  // Which of the two corpora to show. Both queries stay mounted (counts +
  // cross-table polling), but only the active table renders — no long scroll.
  // Default to committee decisions (the chair's primary corpus).
  const [view, setView] = useState<"court" | "committee">("committee");

  const sharedFilters = {
    practiceArea: practiceArea || undefined,
    search: search.trim() || undefined,
    limit: 200,
  };

  const courts = usePrecedents({ ...sharedFilters, sourceKind: "external_upload", sourceType: "court_ruling" });
  const committee = usePrecedents({ ...sharedFilters, sourceKind: "all_committees" });

  // Metadata-queue banner draws on both corpora (a stamped row can be either).
  const allItems = [
    ...(courts.data?.items ?? []),
    ...(committee.data?.items ?? []),
  ];

  return (
    <div className="space-y-8">
      {/* Shared filters */}
      <div className="flex items-end gap-3 flex-wrap">
        <div className="flex-1 min-w-[200px]">
          <label className="text-[0.78rem] text-ink-muted">חיפוש (מספר תיק / שם)</label>
          <Input
            value={search}
            onChange={(e) => setSearch(e.target.value)}
            placeholder="עע״מ 3975/22 / 1200-25"
            dir="rtl"
          />
        </div>
        <div className="min-w-[180px]">
          <label className="text-[0.78rem] text-ink-muted">תחום</label>
          <Select value={practiceArea || "_all"} onValueChange={(v) => setPracticeArea(v === "_all" ? "" : v as PracticeArea)}>
            <SelectTrigger><SelectValue placeholder="הכל" /></SelectTrigger>
            <SelectContent>
              <SelectItem value="_all">הכל</SelectItem>
              {PRACTICE_AREAS.map((a) => (
                <SelectItem key={a.value} value={a.value}>{a.label}</SelectItem>
              ))}
            </SelectContent>
          </Select>
        </div>
        <Button onClick={() => setUploadOpen(true)} className="bg-navy text-parchment hover:bg-navy-soft">
          <Plus className="w-4 h-4 me-1" />
          העלאת פסיקה
        </Button>
      </div>

      {/* Metadata-extraction queue progress (hidden when idle) */}
      <MetadataQueueBanner items={allItems} />

      {/* Segmented control — show one corpus at a time */}
      <div className="inline-flex rounded-lg border border-rule bg-rule-soft/40 p-1 gap-1">
        <SegButton
          active={view === "court"}
          onClick={() => setView("court")}
          label="פסיקת בתי משפט"
          count={courts.data?.count}
        />
        <SegButton
          active={view === "committee"}
          onClick={() => setView("committee")}
          label="החלטות ועדות ערר"
          count={committee.data?.count}
        />
      </div>

      {/* Table 1 — Court rulings */}
      {view === "court" && (
      <section>
        {courts.error ? (
          <div className="rounded bg-danger-bg border border-danger/40 px-6 py-4 text-danger text-center text-sm">
            {courts.error.message}
          </div>
        ) : (
          <div className="rounded-lg border border-rule bg-surface shadow-sm overflow-hidden">
            <Table>
              <TableHeader className="bg-rule-soft/60">
                <TableRow className="border-rule">
                  <TableHead className="text-navy text-right">מס׳ / מראה מקום</TableHead>
                  {/* "שם / ערכאה" hidden by request — see CourtRow */}
                  <TableHead className="hidden text-navy text-right">שם / ערכאה</TableHead>
                  <TableHead className="text-navy text-right">תאריך</TableHead>
                  <TableHead className="text-navy text-right">תחום</TableHead>
                  <TableHead className="text-navy text-right">רמה</TableHead>
                  <TableHead className="text-navy text-right">הלכות</TableHead>
                  <TableHead className="text-navy" />
                </TableRow>
              </TableHeader>
              <TableBody>
                {courts.isPending ? (
                  <TableSkeleton cols={7} />
                ) : !courts.data?.items.length ? (
                  <TableRow className="border-rule">
                    <TableCell colSpan={7} className="text-center text-ink-muted py-8">
                      אין פסיקת בתי משפט בקורפוס.
                    </TableCell>
                  </TableRow>
                ) : (
                  courts.data.items.map((p) => (
                    <CourtRow key={p.id} p={p} onEdit={setEditingId} />
                  ))
                )}
              </TableBody>
            </Table>
          </div>
        )}
      </section>
      )}

      {/* Table 2 — Appeals committee decisions */}
      {view === "committee" && (
      <section>
        {committee.error ? (
          <div className="rounded bg-danger-bg border border-danger/40 px-6 py-4 text-danger text-center text-sm">
            {committee.error.message}
          </div>
        ) : (
          <div className="rounded-lg border border-rule bg-surface shadow-sm overflow-hidden">
            <Table>
              <TableHeader className="bg-rule-soft/60">
                <TableRow className="border-rule">
                  <TableHead className="text-navy text-right">מספר ערר</TableHead>
                  {/* "שם" hidden by request — see CommitteeRow */}
                  <TableHead className="hidden text-navy text-right">שם</TableHead>
                  <TableHead className="text-navy text-right">מחוז</TableHead>
                  <TableHead className="text-navy text-right">יו״ר</TableHead>
                  <TableHead className="text-navy text-right">תאריך</TableHead>
                  <TableHead className="text-navy text-right">תחום</TableHead>
                  <TableHead className="text-navy text-right">הלכות</TableHead>
                  <TableHead className="text-navy" />
                </TableRow>
              </TableHeader>
              <TableBody>
                {committee.isPending ? (
                  <TableSkeleton cols={8} />
                ) : !committee.data?.items.length ? (
                  <TableRow className="border-rule">
                    <TableCell colSpan={8} className="text-center text-ink-muted py-8">
                      אין החלטות ועדת ערר בקורפוס.
                    </TableCell>
                  </TableRow>
                ) : (
                  committee.data.items.map((p) => (
                    <CommitteeRow key={p.id} p={p} onEdit={setEditingId} />
                  ))
                )}
              </TableBody>
            </Table>
          </div>
        )}
      </section>
      )}

      <PrecedentUploadSheet open={uploadOpen} onOpenChange={setUploadOpen} />
      <PrecedentEditSheet
        caseLawId={editingId}
        onOpenChange={(open) => { if (!open) setEditingId(null); }}
      />
    </div>
  );
}
