import type { LucideIcon } from "lucide-react";
import ReactMarkdown from "react-markdown";
import remarkGfm from "remark-gfm";
import { useEffect, useState, type FormEvent } from "react";
import {
  FolderOpen,
  Files,
  MessageSquareText,
  FileCheck2,
  ShieldCheck,
  Settings2,
  Plus,
  Upload,
  Search,
  ArrowUpLeft,
  LogOut,
  Download,
  CheckCircle2,
  Server,
  WifiOff,
  Loader2,
  Trash2,
  ChevronLeft,
  LayoutDashboard,
  Users,
  BookOpen,
} from "lucide-react";
import "./workspace.css";
type Tab = "overview" | "documents" | "chat" | "reports" | "audit" | "settings" | "users";
interface AuditRow {
  id: string;
  actor: string;
  action: string;
  entity: string;
  created_at: number;
  name?: string;
}
interface UserRow {
  id: string;
  name: string;
  email: string;
  role: string;
  active: number;
}
interface Project {
  id: string;
  name: string;
}
interface Doc {
  id: string;
  name: string;
  characters: number;
  sha256: string;
  created_at: number;
}
interface Report {
  id: string;
  title: string;
  mode: string;
  reviewStatus: string;
  created_at: number;
}
interface FullReport {
  id: string;
  title: string;
  markdown: string;
  mode: string;
  model: string;
  reviewStatus: string;
  sources: { name: string; sha256: string }[];
}
interface Answer {
  answer: string;
  mode: string;
  model: string;
  evidence: { document: string; line: number; quote: string }[];
  fallbackReason?: string;
}
interface Status {
  version: string;
  account: { id: string; name: string; email: string; role: string };
  cloudConfigured: boolean;
  localModelConfigured: boolean;
}
async function api(path: string, method = "GET", data?: unknown) {
  const r = await fetch("/api/enterprise/" + path, {
    method,
    headers: data ? { "content-type": "application/json" } : undefined,
    body: data ? JSON.stringify(data) : undefined,
  });
  if (r.status === 401) {
    location.href = "/auth/login";
    throw new Error("نشست شما پایان یافته است.");
  }
  const j = await r.json();
  if (!r.ok) throw new Error(j.error || "عملیات انجام نشد.");
  return j;
}
const date = (v: number) => new Intl.DateTimeFormat("fa-IR", { dateStyle: "medium" }).format(v);
const number = (v: number) => v.toLocaleString("fa-IR");
const modes: Record<string, string> = {
  cloud: "مدل ابری",
  deterministic: "تحلیل قطعی محلی",
  extractive: "بازیابی محلی",
  "local-llm": "مدل زبانی محلی",
};
export default function Workspace() {
  const [tab, setTab] = useState<Tab>("overview"),
    [status, setStatus] = useState<Status | null>(null),
    [projects, setProjects] = useState<Project[]>([]),
    [project, setProject] = useState(""),
    [docs, setDocs] = useState<Doc[]>([]),
    [reports, setReports] = useState<Report[]>([]),
    [selected, setSelected] = useState<string[]>([]),
    [search, setSearch] = useState(""),
    [mode, setMode] = useState("auto"),
    [busy, setBusy] = useState(""),
    [error, setError] = useState(""),
    [notice, setNotice] = useState(""),
    [question, setQuestion] = useState(""),
    [answer, setAnswer] = useState<Answer | null>(null),
    [report, setReport] = useState<FullReport | null>(null),
    [reportType, setReportType] = useState("FULL"),
    [title, setTitle] = useState("گزارش بررسی اسناد پروژه"),
    [projectName, setProjectName] = useState(""),
    [newProject, setNewProject] = useState(false),
    [auditRows, setAuditRows] = useState<AuditRow[]>([]),
    [users, setUsers] = useState<UserRow[]>([]),
    [preview, setPreview] = useState<{ name: string; text: string } | null>(null),
    [reviewNote, setReviewNote] = useState("");
  const writable = status?.account.role === "admin" || status?.account.role === "analyst";
  const reviewer = status?.account.role === "admin" || status?.account.role === "reviewer";
  const go = (t: Tab) => {
    setTab(t);
    setError("");
    setNotice("");
  };
  async function run(label: string, action: () => Promise<void>) {
    setBusy(label);
    setError("");
    setNotice("");
    try {
      await action();
    } catch (e) {
      setError(e instanceof Error ? e.message : "خطای غیرمنتظره");
    } finally {
      setBusy("");
    }
  }
  async function refresh(p: string) {
    if (!p) return;
    const [d, r] = await Promise.all([
      api("documents?projectId=" + p),
      api("reports?projectId=" + p),
    ]);
    setDocs(d);
    setReports(r);
    setSelected((s) => s.filter((id) => d.some((x: Doc) => x.id === id)));
  }
  useEffect(() => {
    document.documentElement.lang = "fa";
    document.documentElement.dir = "rtl";
    document.body.classList.add("enterprise-body");
    run("بارگذاری", async () => {
      const [s, p] = await Promise.all([api("status"), api("projects")]);
      setStatus(s);
      setProjects(p);
      if (p.length) setProject(p[0].id);
    });
    return () => document.body.classList.remove("enterprise-body");
  }, []);
  useEffect(() => {
    setDocs([]);
    setReports([]);
    setSelected([]);
    setAnswer(null);
    setReport(null);
    if (project) run("بارگذاری اسناد", () => refresh(project));
  }, [project]);
  useEffect(() => {
    if (tab === "audit") run("بارگذاری رویدادها", async () => setAuditRows(await api("audit")));
    if (tab === "users") run("بارگذاری کاربران", async () => setUsers(await api("users")));
  }, [tab]);
  useEffect(() => {
    if (!preview) return;
    const previous = document.activeElement as HTMLElement | null;
    const dialog = document.querySelector<HTMLElement>('[role="dialog"]');
    const controls = () =>
      Array.from(
        dialog?.querySelectorAll<HTMLElement>('button,a,input,textarea,select,[tabindex="0"]') ||
          [],
      );
    controls()[0]?.focus();
    const keydown = (event: KeyboardEvent) => {
      if (event.key === "Escape") setPreview(null);
      if (event.key === "Tab") {
        const items = controls();
        const first = items[0],
          last = items[items.length - 1];
        if (event.shiftKey && document.activeElement === first) {
          event.preventDefault();
          last?.focus();
        } else if (!event.shiftKey && document.activeElement === last) {
          event.preventDefault();
          first?.focus();
        }
      }
    };
    document.addEventListener("keydown", keydown);
    return () => {
      document.removeEventListener("keydown", keydown);
      previous?.focus();
    };
  }, [preview]);
  const nav: [Tab, string, LucideIcon][] = [
    ["overview", "نمای کلی", LayoutDashboard],
    ["documents", "کتابخانه اسناد", Files],
    ["chat", "پرسش مستند", MessageSquareText],
    ["reports", "گزارش و بازبینی", FileCheck2],
    ...(reviewer ? [["audit", "ردپای عملیات", ShieldCheck] as [Tab, string, LucideIcon]] : []),
    ...(status?.account.role === "admin"
      ? [["users", "کاربران و نقش‌ها", Users] as [Tab, string, LucideIcon]]
      : []),
    ["settings", "وضعیت و راهنما", Settings2],
  ];
  const counts = [
    { label: "اسناد پروژه", value: docs.length, icon: Files, detail: "متن ذخیره‌شده در دیتابیس" },
    {
      label: "اسناد انتخاب‌شده",
      value: selected.length,
      icon: BookOpen,
      detail: "دامنهٔ پرسش و گزارش",
    },
    {
      label: "گزارش‌های پروژه",
      value: reports.length,
      icon: FileCheck2,
      detail: "خروجی‌های قابل دریافت",
    },
    {
      label: "در انتظار بازبینی",
      value: reports.filter((r) => r.reviewStatus === "draft").length,
      icon: ShieldCheck,
      detail: "پیش‌نویس؛ نه نظر قطعی حقوقی",
    },
  ];
  const chosen = () => ({ projectId: project, documentIds: selected, mode });
  function exportFile(value: unknown, name: string, type: string) {
    const b = new Blob([typeof value === "string" ? value : JSON.stringify(value, null, 2)], {
      type,
    });
    const u = URL.createObjectURL(b),
      a = document.createElement("a");
    a.href = u;
    a.download = name;
    a.click();
    setTimeout(() => URL.revokeObjectURL(u), 1000);
  }
  async function upload(list: FileList | null) {
    if (!list || !project) return;
    await run("استخراج و ذخیره اسناد", async () => {
      let created = 0,
        duplicate = 0;
      const failed: string[] = [];
      for (const file of Array.from(list)) {
        try {
          if (file.size > 20 * 1024 * 1024) throw new Error("حداکثر حجم هر فایل ۲۰ مگابایت است.");
          let text = "";
          const ext = file.name.split(".").pop()?.toLowerCase();
          if (["txt", "md", "csv", "json", "xml", "xer", "log"].includes(ext || ""))
            text = await file.text();
          else if (ext === "docx") {
            const { unzipSync, strFromU8 } = await import("fflate");
            const buffer = new Uint8Array(await file.arrayBuffer());
            const entries = unzipSync(buffer, {
              filter: (file) =>
                file.originalSize < 20 * 1024 * 1024 && file.name === "word/document.xml",
            });
            const xml = entries["word/document.xml"];
            if (!xml) throw new Error("ساختار Word معتبر نیست.");
            const dom = new DOMParser().parseFromString(strFromU8(xml), "application/xml");
            text = Array.from(dom.getElementsByTagName("w:p"))
              .map((p) =>
                Array.from(p.getElementsByTagName("w:t"))
                  .map((t) => t.textContent)
                  .join(""),
              )
              .join("\n");
          } else if (ext === "pdf") {
            const pdf = await import("pdfjs-dist/build/pdf.mjs");
            pdf.GlobalWorkerOptions.workerSrc = (
              await import("pdfjs-dist/build/pdf.worker.mjs?url")
            ).default;
            const loadingTask = pdf.getDocument({
              data: new Uint8Array(await file.arrayBuffer()),
              isEvalSupported: false,
            });
            const document = await loadingTask.promise;
            try {
              if (document.numPages > 300) throw new Error("حداکثر ۳۰۰ صفحه در هر بار ورود.");
              for (let i = 1; i <= document.numPages; i++) {
                const page = await document.getPage(i);
                const content = await page.getTextContent();
                text +=
                  `\n[صفحه ${i}]\n` +
                  content.items
                    .map((x: { str?: string; hasEOL?: boolean }) =>
                      x.str ? x.str + (x.hasEOL ? "\n" : " ") : "",
                    )
                    .join("");
                if (text.length > 400000)
                  throw new Error("متن بیش از ۴۰۰ هزار نویسه است؛ فایل را تقسیم کنید.");
              }
            } finally {
              await loadingTask.destroy();
            }
          } else
            throw new Error(
              "در کتابخانه: متن، PDF متنی و DOCX پشتیبانی می‌شوند. قالب‌های دیگر در ابزار تخصصی اصلی موجودند.",
            );
          if (text.replace(/\[صفحه \d+\]/g, "").trim().length < 10)
            throw new Error("متن خوانا یافت نشد؛ برای اسکن، ابتدا OCR انجام دهید.");
          const r = await api("documents", "POST", { projectId: project, name: file.name, text });
          if (r.duplicate) duplicate++;
          else created++;
        } catch (e) {
          failed.push(file.name + ": " + (e instanceof Error ? e.message : "خطا"));
        }
      }
      await refresh(project);
      setNotice(`${number(created)} سند ذخیره شد؛ ${number(duplicate)} مورد تکراری.`);
      if (failed.length) setError(failed.join("\n"));
    });
  }
  return (
    <div className="cm-workspace" dir="rtl">
      <aside className="cm-sidebar">
        <a className="cm-brand" href="/workspace">
          <div className="cm-logo">
            <FolderOpen size={26} />
          </div>
          <div>
            <strong dir="ltr">ClaimManager</strong>
            <small>فضای کاری مستند</small>
          </div>
        </a>
        <div className="cm-nav-label">مدیریت دانش و ادعا</div>
        <nav aria-label="بخش‌های برنامه">
          {nav.map(([key, label, Icon]) => (
            <button
              key={key}
              aria-current={tab === key ? "page" : undefined}
              className={tab === key ? "active" : ""}
              onClick={() => go(key)}
            >
              <Icon size={20} />
              {label}
              {key === "reports" && reports.length > 0 && <span>{number(reports.length)}</span>}
            </button>
          ))}
        </nav>
        <div className="cm-side-note">
          <ShieldCheck size={22} />
          <strong>قابل ردیابی، نه حدس‌محور</strong>
          <p>منبع هر پاسخ را بررسی کنید. گزارش‌های مدل نیازمند تأیید کارشناس هستند.</p>
        </div>
        <a className="cm-legacy" href="/">
          ابزارهای تخصصی نسخهٔ اصلی <ArrowUpLeft size={18} />
        </a>
        <div className="cm-profile">
          <div className="cm-avatar">{status?.account.name.slice(0, 1) || "م"}</div>
          <div>
            <strong>{status?.account.name || "در حال اتصال"}</strong>
            <small>{status?.account.role || "—"}</small>
          </div>
          <button
            aria-label="خروج"
            onClick={() =>
              run("خروج", async () => {
                await fetch("/auth/logout", { method: "POST" });
                location.href = "/auth/login";
              })
            }
          >
            <LogOut size={18} />
          </button>
        </div>
      </aside>
      <div className="cm-main">
        <header className="cm-topbar">
          <div className="cm-breadcrumb">
            فضای کاری <ChevronLeft size={16} />
            <strong>{nav.find((n) => n[0] === tab)?.[1]}</strong>
          </div>
          <div className="cm-status">
            <span className="cm-dot" /> ذخیره‌سازی پایدار{" "}
            <span className="cm-version" dir="ltr">
              v2.0 · Pilot
            </span>
          </div>
        </header>
        <main>
          <div className="cm-page-heading">
            <div>
              <div className="cm-eyebrow">WORKSPACE / EVIDENCE FIRST</div>
              <h1>{nav.find((n) => n[0] === tab)?.[1]}</h1>
              <p>اسناد یک پروژه را انتخاب کنید؛ پاسخ و گزارش را همراه با شواهد دریافت کنید.</p>
            </div>
            <div className="cm-project-picker">
              <label htmlFor="project">پروژهٔ فعال</label>
              <div>
                <select id="project" value={project} onChange={(e) => setProject(e.target.value)}>
                  <option value="">انتخاب پروژه</option>
                  {projects.map((p) => (
                    <option value={p.id} key={p.id}>
                      {p.name}
                    </option>
                  ))}
                </select>
                {writable && (
                  <button
                    className="cm-icon-button"
                    title="پروژه جدید"
                    aria-label="پروژه جدید"
                    onClick={() => setNewProject(!newProject)}
                  >
                    <Plus size={20} />
                  </button>
                )}
              </div>
            </div>
          </div>
          {newProject && (
            <form
              className="cm-panel cm-inline"
              onSubmit={(e) => {
                e.preventDefault();
                run("ایجاد پروژه", async () => {
                  const p = await api("projects", "POST", { name: projectName });
                  setProjects((s) => [p, ...s]);
                  setProject(p.id);
                  setNewProject(false);
                  setProjectName("");
                });
              }}
            >
              <label htmlFor="project-name">نام پروژه جدید</label>
              <input
                id="project-name"
                value={projectName}
                onChange={(e) => setProjectName(e.target.value)}
                minLength={2}
                required
              />
              <button className="cm-button" disabled={!!busy}>
                ایجاد پروژه
              </button>
            </form>
          )}
          {error && (
            <div className="cm-alert cm-error" role="alert">
              {error}
            </div>
          )}
          {notice && (
            <div className="cm-alert cm-success" role="status">
              {notice}
            </div>
          )}
          {busy && (
            <div className="cm-loading" role="status">
              <Loader2 size={18} className="cm-spin" />
              {busy}…
            </div>
          )}
          {tab === "overview" && (
            <>
              <section className="cm-hero">
                <div>
                  <span className="cm-pill">
                    <WifiOff size={15} /> حالت بدون کلید در دسترس است
                  </span>
                  <h2>
                    از سند تا تصمیم،
                    <br />
                    با شواهد قابل بررسی.
                  </h2>
                  <p>
                    کلید ابری، مدل محلیِ اختیاری یا استخراج قطعی.
                    <br />
                    تمام مسیرها با محدودیت‌های روشن و خروجی قابل دریافت.
                  </p>
                  <div className="cm-actions">
                    <button className="cm-button" onClick={() => go("documents")}>
                      <Upload size={18} /> ورود اسناد
                    </button>
                    <button className="cm-button cm-secondary" onClick={() => go("chat")}>
                      پرسش از اسناد <ArrowUpLeft size={18} />
                    </button>
                  </div>
                </div>
                <div className="cm-flow">
                  <div>
                    <span>۱</span>
                    <div>
                      <strong>کتابخانهٔ پروژه</strong>
                      <small>متن + نام فایل + اثرانگشت SHA-256</small>
                    </div>
                    <CheckCircle2 size={18} />
                  </div>
                  <div>
                    <span>۲</span>
                    <div>
                      <strong>بازیابی و تحلیل</strong>
                      <small>ابری ← مدل محلی ← مسیر قطعی</small>
                    </div>
                    <CheckCircle2 size={18} />
                  </div>
                  <div>
                    <span>۳</span>
                    <div>
                      <strong>گزارش و بازبینی</strong>
                      <small>پیش‌نویس، منابع و ثبت نظر کارشناس</small>
                    </div>
                    <ShieldCheck size={18} />
                  </div>
                </div>
              </section>
              <section className="cm-metrics">
                {counts.map((c) => (
                  <div className="cm-panel" key={c.label}>
                    <div className="cm-metric-label">
                      {c.label}
                      <c.icon size={20} />
                    </div>
                    <strong className="cm-metric-value">{number(c.value)}</strong>
                    <small>{c.detail}</small>
                  </div>
                ))}
              </section>
              <section className="cm-two">
                <div className="cm-panel">
                  <div className="cm-section-head">
                    <h2>گزارش‌های اخیر</h2>
                    <button className="cm-text-button" onClick={() => go("reports")}>
                      همهٔ گزارش‌ها <ChevronLeft size={16} />
                    </button>
                  </div>
                  {reports.length ? (
                    reports.slice(0, 4).map((r) => (
                      <button
                        className="cm-row"
                        key={r.id}
                        onClick={() =>
                          run("دریافت گزارش", async () => {
                            setReport(await api("report?id=" + r.id));
                            go("reports");
                          })
                        }
                      >
                        <FileCheck2 size={20} />
                        <div>
                          <strong>{r.title}</strong>
                          <small>
                            {date(r.created_at)} · {modes[r.mode] || r.mode}
                          </small>
                        </div>
                        <span className="cm-tag">
                          {r.reviewStatus === "draft" ? "پیش‌نویس" : "بازبینی‌شده"}
                        </span>
                      </button>
                    ))
                  ) : (
                    <Empty text="هنوز گزارشی برای این پروژه ثبت نشده است." />
                  )}
                </div>
                <div className="cm-panel">
                  <h2>مسیر شروع</h2>
                  <ol className="cm-steps">
                    <li>یک پروژه ایجاد یا انتخاب کنید.</li>
                    <li>متن، PDF متنی یا Word وارد کنید.</li>
                    <li>اسناد مرتبط را تیک بزنید و پرسش بپرسید.</li>
                    <li>گزارش را بسازید، دریافت و بازبینی کنید.</li>
                  </ol>
                  <p className="cm-muted">
                    اطلاعات پروژه‌های مختلف بدون انتخاب شما ترکیب نمی‌شوند.
                  </p>
                </div>
              </section>
            </>
          )}
          {tab === "documents" && (
            <>
              <div className="cm-toolbar">
                <div className="cm-search">
                  <Search size={18} />
                  <input
                    aria-label="جست‌وجوی نام سند"
                    placeholder="جست‌وجو در نام اسناد…"
                    value={search}
                    onChange={(e) => setSearch(e.target.value)}
                  />
                </div>
                <span className="cm-muted">{number(selected.length)} سند انتخاب شده</span>
                {writable && (
                  <label className={"cm-button " + (!project || busy ? "cm-disabled" : "")}>
                    <Upload size={18} /> بارگذاری اسناد
                    <input
                      type="file"
                      multiple
                      hidden
                      disabled={!project || !!busy}
                      accept=".txt,.md,.csv,.json,.xml,.xer,.log,.pdf,.docx"
                      onChange={(e) => {
                        upload(e.target.files);
                        e.target.value = "";
                      }}
                    />
                  </label>
                )}
              </div>
              <div className="cm-panel">
                <div className="cm-section-head">
                  <h2>کتابخانهٔ پروژه</h2>
                  <button
                    className="cm-text-button"
                    disabled={!docs.length}
                    onClick={() =>
                      setSelected(selected.length === docs.length ? [] : docs.map((d) => d.id))
                    }
                  >
                    {selected.length === docs.length ? "لغو انتخاب همه" : "انتخاب همه"}
                  </button>
                </div>
                {docs.length ? (
                  <div className="cm-table-wrap">
                    <table>
                      <thead>
                        <tr>
                          <th>انتخاب</th>
                          <th>نام سند</th>
                          <th>حجم متن</th>
                          <th>تاریخ ورود</th>
                          <th>عملیات</th>
                        </tr>
                      </thead>
                      <tbody>
                        {docs
                          .filter((d) => d.name.toLowerCase().includes(search.toLowerCase()))
                          .map((d) => (
                            <tr key={d.id}>
                              <td>
                                <input
                                  type="checkbox"
                                  aria-label={"انتخاب " + d.name}
                                  checked={selected.includes(d.id)}
                                  onChange={(e) =>
                                    setSelected((s) =>
                                      e.target.checked
                                        ? [...s, d.id]
                                        : s.filter((id) => id !== d.id),
                                    )
                                  }
                                />
                              </td>
                              <td>
                                <strong>{d.name}</strong>
                                <small className="cm-hash" dir="ltr">
                                  SHA-256: {d.sha256.slice(0, 16)}…
                                </small>
                              </td>
                              <td>{number(d.characters)} نویسه</td>
                              <td>{date(d.created_at)}</td>
                              <td>
                                <div className="cm-actions">
                                  <button
                                    className="cm-icon-button"
                                    aria-label={"نمایش " + d.name}
                                    onClick={() =>
                                      run("نمایش متن", async () =>
                                        setPreview(await api("document?id=" + d.id)),
                                      )
                                    }
                                  >
                                    <BookOpen size={18} />
                                  </button>
                                  {writable && (
                                    <button
                                      className="cm-icon-button"
                                      aria-label={"حذف " + d.name}
                                      disabled={!!busy}
                                      onClick={() => {
                                        if (
                                          confirm("این سند حذف شود؟ گزارش‌های قبلی باقی می‌مانند.")
                                        )
                                          run("حذف سند", async () => {
                                            await api("documents?id=" + d.id, "DELETE");
                                            await refresh(project);
                                          });
                                      }}
                                    >
                                      <Trash2 size={18} />
                                    </button>
                                  )}
                                </div>
                              </td>
                            </tr>
                          ))}
                      </tbody>
                    </table>
                  </div>
                ) : (
                  <Empty
                    text={
                      project
                        ? "هنوز سندی وارد نشده است. اولین سند پروژه را بارگذاری کنید."
                        : "برای شروع، یک پروژه انتخاب یا ایجاد کنید."
                    }
                  />
                )}
                <p className="cm-muted">
                  حداکثر فایل: ۲۰ مگابایت · متن: ۴۰۰ هزار نویسه · PDF: ۳۰۰ صفحه. اصل فایل باینری در
                  این کتابخانه ذخیره نمی‌شود؛ متن استخراج‌شده نگهداری می‌شود. اسکن‌ها نیازمند OCR
                  جداگانه‌اند.
                </p>
              </div>
              <div className="cm-actions">
                <button
                  className="cm-button"
                  disabled={!selected.length}
                  onClick={() => go("chat")}
                >
                  پرسش از اسناد منتخب <ArrowUpLeft size={18} />
                </button>
                <button
                  className="cm-button cm-secondary"
                  disabled={!selected.length}
                  onClick={() => go("reports")}
                >
                  ساخت گزارش
                </button>
              </div>
            </>
          )}
          {tab === "chat" && (
            <div className="cm-two cm-chat-layout">
              <section className="cm-panel">
                <div className="cm-section-head">
                  <h2>دستیار مستند پروژه</h2>
                  <span className="cm-tag">{number(selected.length)} سند</span>
                </div>
                <p className="cm-muted">
                  پرسش شما فقط در اسناد انتخاب‌شده بررسی می‌شود. انتخاب اسناد در کتابخانه است.
                </p>
                <Mode value={mode} onChange={setMode} />
                <form
                  onSubmit={(e) => {
                    e.preventDefault();
                    run("بازیابی شواهد و پاسخ", async () =>
                      setAnswer(await api("chat", "POST", { ...chosen(), question })),
                    );
                  }}
                >
                  <label htmlFor="question">پرسش</label>
                  <textarea
                    id="question"
                    value={question}
                    onChange={(e) => setQuestion(e.target.value)}
                    placeholder="برای مثال: دربارهٔ تعلیق و پرداخت چه شواهدی وجود دارد؟"
                    required
                    minLength={2}
                    maxLength={2000}
                    rows={4}
                  />
                  <div className="cm-actions">
                    <button className="cm-button" disabled={!!busy || !selected.length}>
                      <MessageSquareText size={18} /> دریافت پاسخ مستند
                    </button>
                    <button
                      type="button"
                      className="cm-text-button"
                      onClick={() => go("documents")}
                    >
                      تغییر اسناد
                    </button>
                  </div>
                </form>
                {answer && (
                  <div className="cm-answer">
                    <div className="cm-section-head">
                      <h3>پاسخ</h3>
                      <span className="cm-tag">{modes[answer.mode] || answer.mode}</span>
                    </div>
                    <p className="cm-muted">{answer.model}</p>
                    <div className="cm-prose">{answer.answer}</div>
                    {answer.fallbackReason && <p className="cm-alert">{answer.fallbackReason}</p>}
                    <button
                      className="cm-text-button"
                      onClick={() => exportFile(answer, "answer.json", "application/json")}
                    >
                      دریافت پاسخ و شواهد <Download size={16} />
                    </button>
                  </div>
                )}
              </section>
              <aside className="cm-panel">
                <h2>شواهد بازیابی‌شده</h2>
                {answer?.evidence.length ? (
                  answer.evidence.map((e, i) => (
                    <div className="cm-evidence" key={i}>
                      <strong>
                        [{i + 1}] {e.document}
                      </strong>
                      <small>خط {number(e.line)}</small>
                      <blockquote>{e.quote}</blockquote>
                    </div>
                  ))
                ) : (
                  <Empty text="پس از پرسش، نقل‌قول و موقعیت هر شاهد اینجا نمایش داده می‌شود." />
                )}
                <p className="cm-muted">
                  نمرهٔ بازیابی، احتمال صحت حقوقی نیست. خروجی مدل را با شاهد تطبیق دهید؛ وجود فهرست
                  منابع به‌تنهایی صحت همهٔ ادعاها را تضمین نمی‌کند.
                </p>
              </aside>
            </div>
          )}
          {tab === "reports" && (
            <>
              <div className="cm-two">
                <section className="cm-panel">
                  <h2>گزارش جدید</h2>
                  <form
                    onSubmit={(e) => {
                      e.preventDefault();
                      run("تولید و ثبت گزارش", async () => {
                        setReport(
                          await api("reports", "POST", { ...chosen(), type: reportType, title }),
                        );
                        await refresh(project);
                      });
                    }}
                  >
                    <label htmlFor="title">عنوان گزارش</label>
                    <input
                      id="title"
                      value={title}
                      onChange={(e) => setTitle(e.target.value)}
                      required
                      minLength={2}
                      maxLength={200}
                    />
                    <label htmlFor="report-type">نوع تحلیل</label>
                    <select
                      id="report-type"
                      value={reportType}
                      onChange={(e) => setReportType(e.target.value)}
                    >
                      <option value="FULL">بررسی جامع</option>
                      <option value="DELAY">تأخیرات</option>
                      <option value="DAMAGE">ضرر و زیان</option>
                      <option value="TENDER">مناقصه</option>
                    </select>
                    <Mode value={mode} onChange={setMode} />
                    <p className="cm-muted">
                      {number(selected.length)} سند منتخب · محاسبات و استخراج قطعی حفظ می‌شوند؛ در
                      حالت خودکار، یادداشت مدل در بخش جداگانه اضافه می‌شود.
                    </p>
                    <button
                      className="cm-button"
                      disabled={!writable || !!busy || !selected.length}
                    >
                      <FileCheck2 size={18} /> تولید پیش‌نویس گزارش
                    </button>
                  </form>
                </section>
                <section className="cm-panel">
                  <h2>آرشیو پروژه</h2>
                  {reports.length ? (
                    reports.map((r) => (
                      <button
                        className="cm-row"
                        key={r.id}
                        onClick={() =>
                          run("دریافت گزارش", async () => setReport(await api("report?id=" + r.id)))
                        }
                      >
                        <FileCheck2 size={20} />
                        <div>
                          <strong>{r.title}</strong>
                          <small>
                            {date(r.created_at)} · {modes[r.mode] || r.mode}
                          </small>
                        </div>
                        <span className="cm-tag">
                          {r.reviewStatus === "draft"
                            ? "پیش‌نویس"
                            : r.reviewStatus === "reviewed"
                              ? "بازبینی"
                              : "ردشده"}
                        </span>
                      </button>
                    ))
                  ) : (
                    <Empty text="آرشیو گزارش این پروژه خالی است." />
                  )}
                </section>
              </div>
              {report && (
                <section className="cm-panel cm-report">
                  <div className="cm-section-head">
                    <div>
                      <h2>{report.title}</h2>
                      <p className="cm-muted">
                        {report.model} · وضعیت: {report.reviewStatus}
                      </p>
                    </div>
                    <div className="cm-actions">
                      <button
                        className="cm-button cm-secondary"
                        onClick={() =>
                          exportFile(
                            report.markdown,
                            "report-" + report.id + ".md",
                            "text/markdown",
                          )
                        }
                      >
                        <Download size={16} /> Markdown
                      </button>
                      <button
                        className="cm-button cm-secondary"
                        onClick={() =>
                          exportFile(report, "report-" + report.id + ".json", "application/json")
                        }
                      >
                        JSON
                      </button>
                      <button className="cm-button cm-secondary" onClick={() => window.print()}>
                        چاپ / PDF
                      </button>
                    </div>
                  </div>
                  <div className="cm-alert">
                    این گزارش جایگزین کارشناسی حقوقی یا فنی نیست. مبانی قراردادی، تقویم، واحد پول و
                    مدارک باید کنترل شوند.
                  </div>
                  <div className="cm-report-body">
                    <ReactMarkdown remarkPlugins={[remarkGfm]} skipHtml>
                      {report.markdown}
                    </ReactMarkdown>
                  </div>
                  <details>
                    <summary>منابع و اثرانگشت اسناد</summary>
                    {report.sources.map((s, i) => (
                      <p key={i}>
                        {s.name}
                        <small className="cm-hash" dir="ltr">
                          {s.sha256}
                        </small>
                      </p>
                    ))}
                  </details>
                  {reviewer && (
                    <form
                      className="cm-review"
                      onSubmit={(e) => {
                        e.preventDefault();
                        run("ثبت بازبینی", async () => {
                          setReport(
                            await api("review", "POST", {
                              id: report.id,
                              status: "reviewed",
                              note: reviewNote,
                            }),
                          );
                          await refresh(project);
                          setNotice("بازبینی ثبت شد.");
                        });
                      }}
                    >
                      <label htmlFor="review">یادداشت بازبین (حداقل ۱۰ نویسه)</label>
                      <textarea
                        id="review"
                        value={reviewNote}
                        onChange={(e) => setReviewNote(e.target.value)}
                        required
                        minLength={10}
                        maxLength={3000}
                      />
                      <div className="cm-actions">
                        <button className="cm-button" disabled={!!busy}>
                          ثبت بازبینی
                        </button>
                        <button
                          type="button"
                          className="cm-button cm-secondary"
                          disabled={!!busy || reviewNote.length < 10}
                          onClick={() =>
                            run("ثبت رد گزارش", async () => {
                              setReport(
                                await api("review", "POST", {
                                  id: report.id,
                                  status: "rejected",
                                  note: reviewNote,
                                }),
                              );
                              await refresh(project);
                            })
                          }
                        >
                          رد با توضیح
                        </button>
                      </div>
                    </form>
                  )}
                </section>
              )}
            </>
          )}
          {tab === "audit" && (
            <section className="cm-panel">
              <h2>رویدادهای ثبت‌شده</h2>
              <p className="cm-muted">
                ۲۰۰ رویداد اخیر؛ متن اسناد، پرسش‌ها، پاسخ‌ها و کلیدها در این لاگ ثبت نمی‌شوند. این
                لاگ ضد دستکاری نیست.
              </p>
              <div className="cm-table-wrap">
                <table>
                  <thead>
                    <tr>
                      <th>عامل</th>
                      <th>عملیات</th>
                      <th>زمان</th>
                      <th>شناسهٔ مرجع</th>
                    </tr>
                  </thead>
                  <tbody>
                    {auditRows.map((r) => (
                      <tr key={r.id}>
                        <td>{r.name || r.actor}</td>
                        <td dir="ltr">{r.action}</td>
                        <td>{new Date(r.created_at).toLocaleString("fa-IR")}</td>
                        <td className="cm-hash">{r.entity || "—"}</td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            </section>
          )}
          {tab === "users" && (
            <section className="cm-panel">
              <h2>کاربران سازمان</h2>
              <p className="cm-muted">
                مدیر: همهٔ عملیات · تحلیلگر: ورود سند و گزارش · بازبین: پرسش و بازبینی · خواننده:
                مشاهده و پرسش. تمام کاربران این نصب، اسناد همهٔ پروژه‌ها را می‌بینند.
              </p>
              <UserForm
                busy={!!busy}
                onCreate={(d) =>
                  run("ایجاد کاربر", async () => {
                    await api("users", "POST", d);
                    setUsers(await api("users"));
                    setNotice("کاربر ایجاد شد.");
                  })
                }
              />
              <div className="cm-table-wrap">
                <table>
                  <thead>
                    <tr>
                      <th>نام</th>
                      <th>ایمیل</th>
                      <th>نقش</th>
                      <th>وضعیت</th>
                    </tr>
                  </thead>
                  <tbody>
                    {users.map((u) => (
                      <tr key={u.id}>
                        <td>{u.name}</td>
                        <td dir="ltr">{u.email}</td>
                        <td>{u.role}</td>
                        <td>
                          <button
                            className="cm-button cm-secondary"
                            disabled={!!busy || u.id === status?.account.id}
                            onClick={() =>
                              run("تغییر وضعیت", async () => {
                                await api("users", "PATCH", { id: u.id, active: !u.active });
                                setUsers(await api("users"));
                              })
                            }
                          >
                            {u.active ? "فعال — غیرفعال کردن" : "غیرفعال — فعال کردن"}
                          </button>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            </section>
          )}
          {tab === "settings" && (
            <>
              <section className="cm-two">
                <div className="cm-panel">
                  <h2>
                    <Server size={22} /> وضعیت پیکربندی
                  </h2>
                  <dl className="cm-definitions">
                    <dt>ذخیره‌سازی</dt>
                    <dd>SQLite با WAL، روی دیسک پایدار</dd>
                    <dt>کلید ابری</dt>
                    <dd>
                      {status?.cloudConfigured ? "تنظیم شده؛ اتصال هنوز تأیید نشده" : "تنظیم نشده"}
                    </dd>
                    <dt>مدل محلی</dt>
                    <dd>
                      {status?.localModelConfigured
                        ? "تنظیم شده؛ اتصال هنوز تأیید نشده"
                        : "اختیاری؛ تنظیم نشده"}
                    </dd>
                    <dt>مسیر بدون کلید</dt>
                    <dd>استخراج قطعی + بازیابی واژگانی</dd>
                    <dt>دامنهٔ نصب</dt>
                    <dd>تک‌سازمانی؛ یک نمونهٔ سرور</dd>
                  </dl>
                </div>
                <div className="cm-panel">
                  <h2>نکات ضروری پیش از انتشار</h2>
                  <ul className="cm-steps">
                    <li>HTTPS، دیسک پایدار و بکاپ روزانه الزامی است.</li>
                    <li>کلیدها فقط در متغیر محیطی سرور قرار می‌گیرند.</li>
                    <li>
                      حالت خودکار ممکن است متن منتخب را به سرویس ابری ارسال کند؛ برای اسناد محرمانه،
                      حالت بدون شبکه را انتخاب کنید.
                    </li>
                    <li>مدل محلی نیاز به نصب جداگانه و منابع سخت‌افزاری دارد.</li>
                    <li>پیش‌نویس‌ها باید بازبینی کارشناسی شوند.</li>
                  </ul>
                </div>
              </section>
              <section className="cm-panel">
                <h2>محدودیت‌های شفاف</h2>
                <p className="cm-prose">
                  این بسته یک پایلوت قابل تست و میزبانی است؛ گواهی امنیت یا انطباق سازمانی ندارد.
                  SSO/MFA، چندمستاجری، صف توزیع‌شده و HA پیاده‌سازی نشده‌اند. استخراج محلی جایگزین
                  استدلال مدل زبانی نیست. OCR فارسی در کتابخانهٔ جدید بسته‌بندی نشده است. پرداخت و
                  اشتراک نسخهٔ اصلی، سامانهٔ صورتحساب واقعی نیستند.
                </p>
              </section>
            </>
          )}
          <footer className="cm-footer">
            ClaimManager · نسخهٔ پایلوت ۲.۰ <span>شواهد اول؛ تصمیم با کارشناس.</span>
          </footer>
        </main>
      </div>
      {preview && (
        <div className="cm-modal-backdrop" onClick={() => setPreview(null)}>
          <section
            role="dialog"
            aria-modal="true"
            aria-label="متن سند"
            className="cm-panel cm-modal"
            onClick={(e) => e.stopPropagation()}
          >
            <div className="cm-section-head">
              <h2>{preview.name}</h2>
              <button className="cm-button cm-secondary" onClick={() => setPreview(null)}>
                بستن
              </button>
            </div>
            <div className="cm-prose">{preview.text}</div>
          </section>
        </div>
      )}
    </div>
  );
}
function Empty({ text }: { text: string }) {
  return (
    <div className="cm-empty">
      <FolderOpen size={30} />
      <p>{text}</p>
    </div>
  );
}
function Mode({ value, onChange }: { value: string; onChange: (v: string) => void }) {
  return (
    <div className="cm-mode">
      <label>
        <input
          type="radio"
          name="mode"
          value="auto"
          checked={value === "auto"}
          onChange={() => onChange("auto")}
        />{" "}
        خودکار: ابری ← محلی ← قطعی
      </label>
      <label>
        <input
          type="radio"
          name="mode"
          value="offline"
          checked={value === "offline"}
          onChange={() => onChange("offline")}
        />{" "}
        بدون شبکه: فقط استخراج / بازیابی
      </label>
    </div>
  );
}
function UserForm({ onCreate, busy }: { onCreate: (d: unknown) => Promise<void>; busy: boolean }) {
  return (
    <form
      className="cm-user-form"
      onSubmit={async (e: FormEvent<HTMLFormElement>) => {
        e.preventDefault();
        const form = e.currentTarget;
        const values = Object.fromEntries(new FormData(form));
        await onCreate(values);
        form.reset();
      }}
    >
      <label>
        نام
        <input name="name" required minLength={2} maxLength={100} />
      </label>
      <label>
        ایمیل
        <input type="email" name="email" required dir="ltr" />
      </label>
      <label>
        گذرواژه
        <input
          type="password"
          name="password"
          minLength={12}
          maxLength={256}
          autoComplete="new-password"
          required
          dir="ltr"
        />
      </label>
      <label>
        نقش
        <select name="role">
          <option value="analyst">تحلیلگر</option>
          <option value="reviewer">بازبین</option>
          <option value="reader">خواننده</option>
          <option value="admin">مدیر</option>
        </select>
      </label>
      <button className="cm-button" disabled={busy}>
        ایجاد کاربر
      </button>
    </form>
  );
}
