"use client";

import { useEffect, useMemo, useState } from "react";
import { Check, X, Edit2, ChevronDown, ChevronLeft, AlertTriangle } from "lucide-react";
import { toast } from "sonner";
import { Button } from "@/components/ui/button";
import { Badge } from "@/components/ui/badge";
import { Skeleton } from "@/components/ui/skeleton";
import { Textarea } from "@/components/ui/textarea";
import { practiceAreaLabel } from "./practice-area";
import {
  useHalachotPending, useUpdateHalacha, type Halacha,
} from "@/lib/api/precedent-library";

/**
 * Halacha review queue — the chair-only path between automatic
 * extraction and agent visibility. Per the project's review policy,
 * NO halacha is auto-published; every row sits in pending_review until
 * approved.
 *
 * UX: items are grouped by precedent (case_law_id). Groups start
 * collapsed so the chair picks one ruling at a time. Within an open
 * group, J/K navigates, A approves, R rejects, E edits. Items inside
 * each group are sorted by confidence ascending so the doubtful ones
 * surface first.
 */

function formatDate(iso: string | null | undefined) {
  if (!iso) return "—";
  try {
    return new Date(iso).toLocaleDateString("he-IL");
  } catch {
    return iso;
  }
}

/* The upload form (and Nevo PDFs) embed Unicode bidi marks (RTL/LTR/embedding/
 * isolate) inside the citation. They render as zero-width but visually push
 * the text away from where it should sit. Strip for display only. */
function cleanCitation(s: string | null | undefined): string {
  if (!s) return "—";
  return s.replace(/[‎‏‪-‮⁦-⁩]/g, "").trim();
}

const RULE_TYPE_LABELS: Record<string, string> = {
  binding: "הלכה מחייבת",
  interpretive: "פרשני",
  procedural: "פרוצדורלי",
  obiter: "אמרת אגב",
  application: "יישום הלכה",
  persuasive: "משכנע",
};

function ruleTypeLabel(t: string): string {
  return RULE_TYPE_LABELS[t] ?? t;
}

type EditState = { rule_statement: string; reasoning_summary: string };

function HalachaCard({
  h, focused, onApprove, onReject, onSave,
}: {
  h: Halacha;
  focused: boolean;
  onApprove: () => void;
  onReject: () => void;
  onSave: (patch: Partial<EditState>) => Promise<void>;
}) {
  const [editing, setEditing] = useState(false);
  const [draft, setDraft] = useState<EditState>({
    rule_statement: h.rule_statement,
    reasoning_summary: h.reasoning_summary,
  });

  // Reset draft when underlying row changes (focus moves to a new card).
  useEffect(() => {
    // eslint-disable-next-line react-hooks/set-state-in-effect
    setDraft({
      rule_statement: h.rule_statement,
      reasoning_summary: h.reasoning_summary,
    });
  }, [h.id, h.rule_statement, h.reasoning_summary]);

  const onSubmitEdit = async () => {
    await onSave(draft);
    setEditing(false);
  };

  return (
    <div
      data-halacha-id={h.id}
      className={`
        rounded-lg border bg-surface p-4 space-y-3 transition-colors
        ${focused ? "border-gold ring-2 ring-gold/40 shadow-md" : "border-rule"}
      `}
    >
      {/* Header — status pills only (citation is in the group header) */}
      <div className="flex items-start gap-2 text-[0.78rem] text-ink-muted flex-wrap">
        {h.page_reference && (
          <span className="text-[0.7rem]">{h.page_reference}</span>
        )}
        <span className="ms-auto flex items-center gap-2">
          {h.quote_verified ? (
            <Badge variant="outline" className="text-[0.65rem] bg-gold-wash text-gold-deep border-gold/40">
              <Check className="w-3 h-3 me-1" /> ציטוט מאומת
            </Badge>
          ) : (
            <Badge variant="outline" className="text-[0.65rem] bg-danger-bg text-danger border-danger/40">
              <AlertTriangle className="w-3 h-3 me-1" /> ציטוט לא מאומת
            </Badge>
          )}
          <Badge variant="outline" className="text-[0.65rem] tabular-nums">
            ביטחון {h.confidence.toFixed(2)}
          </Badge>
          <Badge variant="outline" className="text-[0.65rem]">
            {ruleTypeLabel(h.rule_type)}
          </Badge>
        </span>
      </div>

      {/* Side-by-side rule vs quote */}
      <div className="grid md:grid-cols-2 gap-3">
        <div>
          <div className="text-[0.7rem] text-ink-muted mb-1">ניסוח הכלל</div>
          {editing ? (
            <Textarea
              value={draft.rule_statement} rows={4} dir="rtl"
              onChange={(e) => setDraft({ ...draft, rule_statement: e.target.value })}
              className="bg-gold-wash/50 border-gold/30"
            />
          ) : (
            <p className="text-navy font-medium leading-relaxed" dir="rtl">
              {h.rule_statement}
            </p>
          )}
        </div>
        <div>
          <div className="text-[0.7rem] text-ink-muted mb-1">ציטוט תומך</div>
          <blockquote className="text-ink-soft text-sm leading-relaxed border-r-2 border-gold pr-3" dir="rtl">
            &ldquo;{h.supporting_quote}&rdquo;
          </blockquote>
        </div>
      </div>

      {/* Reasoning */}
      {(editing || h.reasoning_summary) && (
        <div>
          <div className="text-[0.7rem] text-ink-muted mb-1">תמצית ההיגיון</div>
          {editing ? (
            <Textarea
              value={draft.reasoning_summary} rows={2} dir="rtl"
              onChange={(e) => setDraft({ ...draft, reasoning_summary: e.target.value })}
              className="bg-gold-wash/50 border-gold/30"
            />
          ) : (
            <p className="text-ink-soft text-sm leading-relaxed" dir="rtl">
              {h.reasoning_summary}
            </p>
          )}
        </div>
      )}

      {/* Tags */}
      <div className="flex items-center gap-2 flex-wrap">
        {h.practice_areas?.map((p) => (
          <Badge key={p} variant="outline" className="text-[0.65rem] bg-navy-soft/30 text-navy">
            {practiceAreaLabel(p)}
          </Badge>
        ))}
        {h.subject_tags?.map((t) => (
          <Badge key={t} variant="outline" className="text-[0.65rem]">
            {t}
          </Badge>
        ))}
      </div>

      {/* Actions */}
      <div className="flex items-center gap-2 justify-end pt-1 border-t border-rule-soft">
        {editing ? (
          <>
            <Button size="sm" variant="ghost" onClick={() => setEditing(false)}>
              ביטול
            </Button>
            <Button size="sm" onClick={onSubmitEdit}
              className="bg-navy text-parchment hover:bg-navy-soft">
              שמור שינויים
            </Button>
          </>
        ) : (
          <>
            <Button size="sm" variant="ghost" onClick={() => setEditing(true)}>
              <Edit2 className="w-3.5 h-3.5 me-1" />
              ערוך (E)
            </Button>
            <Button size="sm" variant="ghost"
              onClick={onReject}
              className="text-danger hover:text-danger hover:bg-danger-bg">
              <X className="w-3.5 h-3.5 me-1" />
              דחה (R)
            </Button>
            <Button size="sm" onClick={onApprove}
              className="bg-gold text-navy hover:bg-gold-deep">
              <Check className="w-3.5 h-3.5 me-1" />
              אשר (A)
            </Button>
          </>
        )}
      </div>
    </div>
  );
}

type Group = {
  caseLawId: string;
  caseNumber: string;
  court: string;
  decisionDate: string | null;
  precedentLevel: string;
  items: Halacha[];
};

export function HalachaReviewPanel() {
  const { data, isPending, error } = useHalachotPending(500);
  const update = useUpdateHalacha();
  const [expandedIds, setExpandedIds] = useState<Set<string>>(new Set());
  const [focusedId, setFocusedId] = useState<string | null>(null);

  // Group by precedent. Within each group, items sorted by confidence ascending
  // so the chair sees doubtful entries first. Groups themselves sort by item
  // count descending — biggest piles surface first.
  const groups = useMemo<Group[]>(() => {
    const map = new Map<string, Group>();
    for (const h of data?.items ?? []) {
      const k = h.case_law_id;
      let g = map.get(k);
      if (!g) {
        g = {
          caseLawId: k,
          caseNumber: h.case_number ?? "",
          court: h.court ?? "",
          decisionDate: h.decision_date ?? null,
          precedentLevel: h.precedent_level ?? "",
          items: [],
        };
        map.set(k, g);
      }
      g.items.push(h);
    }
    for (const g of map.values()) {
      g.items.sort((a, b) => a.confidence - b.confidence);
    }
    return Array.from(map.values()).sort((a, b) => b.items.length - a.items.length);
  }, [data]);

  const totalCount = data?.items.length ?? 0;

  // Items the keyboard handler can navigate. Only items inside expanded
  // groups are "visible" — collapsed groups hide their items from J/K.
  const visibleItems = useMemo<Halacha[]>(() => {
    const out: Halacha[] = [];
    for (const g of groups) {
      if (expandedIds.has(g.caseLawId)) out.push(...g.items);
    }
    return out;
  }, [groups, expandedIds]);

  // If the focused item disappears (approved/rejected/group-collapsed), pick
  // a sensible neighbour so the highlight doesn't vanish silently.
  useEffect(() => {
    if (focusedId === null) return;
    if (visibleItems.some((h) => h.id === focusedId)) return;
    // eslint-disable-next-line react-hooks/set-state-in-effect
    setFocusedId(visibleItems[0]?.id ?? null);
  }, [focusedId, visibleItems]);

  // Scroll the focused row into view
  useEffect(() => {
    if (!focusedId) return;
    const el = document.querySelector(`[data-halacha-id="${focusedId}"]`);
    el?.scrollIntoView({ block: "nearest", behavior: "smooth" });
  }, [focusedId]);

  const focused = focusedId
    ? visibleItems.find((h) => h.id === focusedId) ?? null
    : null;

  const moveFocus = (delta: 1 | -1) => {
    if (visibleItems.length === 0) return;
    const idx = focusedId
      ? visibleItems.findIndex((h) => h.id === focusedId)
      : -1;
    const next = idx < 0
      ? (delta > 0 ? 0 : visibleItems.length - 1)
      : Math.max(0, Math.min(visibleItems.length - 1, idx + delta));
    setFocusedId(visibleItems[next].id);
  };

  const review = async (
    h: Halacha,
    status: "approved" | "rejected",
    extra?: Partial<EditState>,
  ) => {
    try {
      await update.mutateAsync({
        id: h.id,
        patch: { review_status: status, ...extra },
      });
      toast.success(status === "approved" ? "אושר" : "נדחה");
    } catch (e) {
      toast.error(e instanceof Error ? e.message : "שגיאה");
    }
  };

  const toggleGroup = (caseLawId: string) => {
    setExpandedIds((prev) => {
      const next = new Set(prev);
      if (next.has(caseLawId)) {
        next.delete(caseLawId);
      } else {
        next.add(caseLawId);
        // Auto-focus first item of the just-opened group
        const g = groups.find((x) => x.caseLawId === caseLawId);
        if (g && g.items.length) {
          setTimeout(() => setFocusedId(g.items[0].id), 0);
        }
      }
      return next;
    });
  };

  // Keyboard navigation — only acts when something is focused (i.e. at
  // least one group is open).
  useEffect(() => {
    const onKey = (e: KeyboardEvent) => {
      const tag = (e.target as HTMLElement)?.tagName?.toLowerCase();
      if (tag === "input" || tag === "textarea") return;
      if (e.key === "j") {
        e.preventDefault();
        moveFocus(1);
      } else if (e.key === "k") {
        e.preventDefault();
        moveFocus(-1);
      } else if ((e.key === "a" || e.key === "A") && focused) {
        e.preventDefault();
        review(focused, "approved");
      } else if ((e.key === "r" || e.key === "R") && focused) {
        e.preventDefault();
        if (window.confirm("לדחות הלכה זו?")) review(focused, "rejected");
      }
    };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [focused, visibleItems]);

  if (error) {
    return (
      <div className="rounded bg-danger-bg border border-danger/40 px-6 py-5 text-danger text-center">
        {error.message}
      </div>
    );
  }

  if (isPending) {
    return (
      <div className="space-y-3">
        {[...Array(3)].map((_, i) => <Skeleton key={i} className="h-24 w-full" />)}
      </div>
    );
  }

  if (!groups.length) {
    return (
      <div className="text-center text-ink-muted py-16">
        <p className="text-lg">אין הלכות הממתינות לאישור.</p>
        <p className="text-sm mt-2">העלה פסיקה חדשה — ההלכות שיחולצו ממנה יופיעו כאן.</p>
      </div>
    );
  }

  return (
    <div className="space-y-4">
      <div className="flex items-center gap-3 text-sm text-ink-muted flex-wrap">
        <span>
          <span className="text-navy font-semibold">{totalCount}</span> ממתינות
          ב-<span className="text-navy font-semibold">{groups.length}</span> פסיקות
        </span>
        <span className="me-auto text-[0.72rem]">
          ניווט: <kbd className="bg-rule-soft px-1.5 rounded">J</kbd>/<kbd className="bg-rule-soft px-1.5 rounded">K</kbd>
          {" "}· אישור: <kbd className="bg-rule-soft px-1.5 rounded">A</kbd>
          {" "}· דחייה: <kbd className="bg-rule-soft px-1.5 rounded">R</kbd>
          {" "}· עריכה: <kbd className="bg-rule-soft px-1.5 rounded">E</kbd>
        </span>
        {expandedIds.size > 0 && (
          <Button
            size="sm" variant="ghost"
            onClick={() => setExpandedIds(new Set())}
          >
            סגור הכל
          </Button>
        )}
      </div>

      <div className="space-y-3">
        {groups.map((g) => {
          const isOpen = expandedIds.has(g.caseLawId);
          return (
            <div
              key={g.caseLawId}
              className="rounded-lg border border-rule bg-surface overflow-hidden"
            >
              <button
                type="button"
                onClick={() => toggleGroup(g.caseLawId)}
                className={`
                  w-full flex items-center gap-3 px-4 py-3 text-right
                  hover:bg-gold-wash/30 transition-colors
                  ${isOpen ? "bg-gold-wash/40 border-b border-rule" : ""}
                `}
                aria-expanded={isOpen}
              >
                {isOpen ? (
                  <ChevronDown className="w-4 h-4 text-ink-muted shrink-0" />
                ) : (
                  <ChevronLeft className="w-4 h-4 text-ink-muted shrink-0" />
                )}
                <div className="flex-1 min-w-0 text-right">
                  <div className="font-semibold text-navy truncate">
                    {cleanCitation(g.caseNumber)}
                  </div>
                  <div className="text-[0.72rem] text-ink-muted flex items-center gap-2 flex-wrap mt-0.5">
                    {g.court && <span>{g.court}</span>}
                    {g.decisionDate && <span>· {formatDate(g.decisionDate)}</span>}
                    {g.precedentLevel && <span>· {g.precedentLevel}</span>}
                  </div>
                </div>
                <Badge
                  variant="outline"
                  className="bg-gold-wash text-gold-deep border-gold/40 tabular-nums"
                >
                  {g.items.length} ממתינות
                </Badge>
              </button>

              {isOpen && (
                <div className="p-4 space-y-3 bg-rule-soft/20">
                  {g.items.map((h) => (
                    <HalachaCard
                      key={h.id}
                      h={h}
                      focused={h.id === focusedId}
                      onApprove={() => review(h, "approved")}
                      onReject={() => {
                        if (window.confirm("לדחות הלכה זו?")) review(h, "rejected");
                      }}
                      onSave={async (patch) => {
                        try {
                          await update.mutateAsync({ id: h.id, patch });
                          toast.success("נשמר");
                        } catch (e) {
                          toast.error(e instanceof Error ? e.message : "שגיאה");
                        }
                      }}
                    />
                  ))}
                </div>
              )}
            </div>
          );
        })}
      </div>
    </div>
  );
}
