// Retention Module UI — admin-only
//   • RetentionSettingsSection : panel embedded inside SettingsPage
//   • RetentionArchivePage     : standalone page accessible from "ระบบ" → "ไฟล์ลบชั่วคราว"
//   • RetentionAuditList       : small audit-log table reused in both
//
// Backed by /api/tenants/:tid/retention/*  (see src/api/index.js)

const RETENTION_SCOPE_META = {
  pr_attachments: {
    label: "ไฟล์แนบของ PR (Purchase Request)",
    short: "PR attachments",
    iconBg: "bg-indigo-100 text-indigo-700",
    badgeColor: "indigo",
  },
  pc_attachments: {
    label: "ไฟล์แนบของ PC (Price Comparison)",
    short: "PC attachments",
    iconBg: "bg-emerald-100 text-emerald-700",
    badgeColor: "emerald",
  },
  supplier_documents: {
    label: "เอกสารผู้จำหน่ายที่ถูกแทนที่ (Vendor Master)",
    short: "Supplier docs (replaced)",
    iconBg: "bg-violet-100 text-violet-700",
    badgeColor: "violet",
    note: "ลบเฉพาะเอกสารที่ถูกแทนที่ด้วยไฟล์ใหม่ — เอกสารปัจจุบันจะไม่ถูกแตะ",
  },
};

// formatBytes is provided by src/ui.jsx (canonical implementation, attached to window).

// =============================================================================
// SETTINGS SECTION — embedded inside SettingsPage
// =============================================================================
const RetentionSettingsSection = ({ tenant, currentRole }) => {
  const toast = useToast();
  const isAdmin = isTenantAdminRole(currentRole);
  const [policies, setPolicies] = useState([]);
  const [usage, setUsage] = useState(null);
  const [loading, setLoading] = useState(false);
  const [previews, setPreviews] = useState({});  // scope → preview object
  const [runState, setRunState] = useState({});  // scope → "preview"|"running"
  const [confirmEnable, setConfirmEnable] = useState(null); // { scope, months, graceDays }
  const [confirmRun, setConfirmRun] = useState(null);       // { scope, preview }

  const load = async () => {
    if (!tenant?.id || !window.apiClient || !isAdmin) return;
    setLoading(true);
    try {
      const [pols, use] = await Promise.all([
        window.apiClient.retentionListPolicies(tenant.id),
        window.apiClient.retentionUsage(tenant.id),
      ]);
      setPolicies(Array.isArray(pols) ? pols : []);
      setUsage(use || null);
    } catch (e) {
      toast({ kind: "error", msg: e.message || "โหลดข้อมูลไม่สำเร็จ" });
    } finally { setLoading(false); }
  };
  useEffect(() => { load(); /* eslint-disable-next-line */ }, [tenant?.id, isAdmin]);

  if (!isAdmin) {
    return (
      <div className="bg-white border border-ink-100 rounded-2xl p-6">
        <div className="flex items-start gap-3">
          <Icon name="ban" size={16} className="text-ink-400 mt-0.5"/>
          <div>
            <div className="text-[14px] font-semibold text-ink-900">การเก็บข้อมูล (Data Retention)</div>
            <div className="text-[12.5px] text-ink-500 mt-0.5">
              สงวนสิทธิ์เฉพาะ <strong>Admin / Super Admin</strong> ของบริษัท
            </div>
          </div>
        </div>
      </div>
    );
  }

  const updatePolicy = async (scope, patch) => {
    const cur = policies.find(p => p.scope === scope);
    const merged = { ...(cur || {}), ...patch };
    try {
      await window.apiClient.retentionUpdatePolicy(tenant.id, scope, {
        retention_months: merged.retention_months,
        soft_delete_days: merged.soft_delete_days,
        enabled: merged.enabled ? 1 : 0,
      });
      toast({ kind: "success", msg: "บันทึกการตั้งค่าแล้ว" });
      await load();
    } catch (e) {
      toast({ kind: "error", msg: e.message || "บันทึกไม่สำเร็จ" });
    }
  };

  const previewPolicy = async (scope, months) => {
    try {
      setRunState(s => ({ ...s, [scope]: "preview" }));
      const r = await window.apiClient.retentionPreview(tenant.id, scope, months);
      setPreviews(p => ({ ...p, [scope]: r }));
      return r;
    } catch (e) {
      toast({ kind: "error", msg: e.message || "ดูตัวอย่างไม่สำเร็จ" });
    } finally {
      setRunState(s => ({ ...s, [scope]: null }));
    }
  };

  const runSweep = async (scope) => {
    try {
      setRunState(s => ({ ...s, [scope]: "running" }));
      const r = await window.apiClient.retentionRun(tenant.id, scope, false);
      toast({
        kind: "success",
        msg: `ลบชั่วคราว ${r.archived || 0} ไฟล์ · ลบถาวร ${r.hard_deleted || 0} ไฟล์ · ประหยัด ${formatBytes(r.bytes_freed || 0)}`,
      });
      await load();
    } catch (e) {
      toast({ kind: "error", msg: e.message || "รันไม่สำเร็จ" });
    } finally {
      setRunState(s => ({ ...s, [scope]: null }));
    }
  };

  const totalBytes = (usage?.pr_attachments?.bytes || 0) + (usage?.pc_attachments?.bytes || 0);

  return (
    <div className="space-y-4">
      {/* Header */}
      <div className="bg-white border border-ink-100 rounded-2xl p-5">
        <div className="flex items-start gap-3">
          <div className="w-9 h-9 rounded-xl bg-amber-100 text-amber-700 flex items-center justify-center shrink-0">
            <Icon name="trash" size={16}/>
          </div>
          <div className="flex-1 min-w-0">
            <div className="text-[15px] font-bold text-ink-900">นโยบายการลบไฟล์แนบอัตโนมัติ (Data Retention)</div>
            <div className="text-[12.5px] text-ink-500 mt-1 leading-snug">
              ตั้งค่าให้ระบบลบไฟล์แนบที่อายุเกินกำหนดแบบ <strong>ลบชั่วคราว</strong> เพื่อประหยัดพื้นที่ — ไฟล์จะอยู่ในถังลบชั่วคราว {policies[0]?.soft_delete_days || 30} วันก่อนถูก <strong>ลบถาวร</strong> (กู้กลับได้ในช่วงนี้) · <strong>เอกสาร PR / PC จะไม่ถูกลบ</strong> — ลบเฉพาะไฟล์แนบเท่านั้น
            </div>
          </div>
        </div>
        {usage && (
          <div className="mt-4 grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-3">
            <UsageStat label="PR — ไฟล์ทั้งหมด"    count={usage.pr_attachments.count} bytes={usage.pr_attachments.bytes}/>
            <UsageStat label="PR — ในถังลบชั่วคราว" count={usage.pr_attachments.archived_count} bytes={usage.pr_attachments.archived_bytes} archived/>
            <UsageStat label="PC — ไฟล์ทั้งหมด"    count={usage.pc_attachments.count} bytes={usage.pc_attachments.bytes}/>
            <UsageStat label="PC — ในถังลบชั่วคราว" count={usage.pc_attachments.archived_count} bytes={usage.pc_attachments.archived_bytes} archived/>
            <UsageStat label="Supplier — Replaced docs" count={usage.supplier_documents?.count || 0} bytes={usage.supplier_documents?.bytes || 0}/>
            <UsageStat label="Supplier — ในถังลบชั่วคราว" count={usage.supplier_documents?.archived_count || 0} bytes={usage.supplier_documents?.archived_bytes || 0} archived/>
          </div>
        )}
      </div>

      {/* Policy cards */}
      {loading ? (
        <div className="bg-white border border-ink-100 rounded-2xl p-8 text-center text-ink-500 text-sm">กำลังโหลด…</div>
      ) : (
        ["pr_attachments", "pc_attachments", "supplier_documents"].map(scope => {
          const p = policies.find(x => x.scope === scope) || {
            scope, retention_months: 24, soft_delete_days: 30, enabled: 0,
          };
          const meta = RETENTION_SCOPE_META[scope];
          return (
            <PolicyCard
              key={scope}
              policy={p}
              meta={meta}
              busy={runState[scope]}
              preview={previews[scope]}
              onPreview={(months) => previewPolicy(scope, months)}
              onSaveDraft={(patch) => {
                // Edit draft locally — only saved when toggling enabled or hitting save
                setPolicies(prev => prev.map(x => x.scope === scope ? { ...x, ...patch } : x));
              }}
              onSave={(patch) => updatePolicy(scope, patch)}
              onConfirmEnable={(months, graceDays) => setConfirmEnable({ scope, months, graceDays })}
              onConfirmRun={async () => {
                const pv = previews[scope] || await previewPolicy(scope, p.retention_months || 24);
                if (pv) setConfirmRun({ scope, preview: pv });
              }}
            />
          );
        })
      )}

      {/* Audit list */}
      <RetentionAuditList tenant={tenant} reloadSignal={policies.length + Object.values(runState).filter(Boolean).length}/>

      {/* Confirm enable */}
      <Modal open={!!confirmEnable} onClose={() => setConfirmEnable(null)} width={520}
        title="ยืนยันการเปิดใช้นโยบาย"
        subtitle={confirmEnable ? RETENTION_SCOPE_META[confirmEnable.scope]?.label : ""}
        footer={<>
          <Button variant="secondary" onClick={() => setConfirmEnable(null)}>ยกเลิก</Button>
          <Button variant="primary" icon="check" onClick={() => {
            if (!confirmEnable) return;
            updatePolicy(confirmEnable.scope, {
              enabled: 1,
              retention_months: confirmEnable.months,
              soft_delete_days: confirmEnable.graceDays,
            });
            setConfirmEnable(null);
          }}>เปิดใช้</Button>
        </>}>
        {confirmEnable && (
          <div className="space-y-2 text-[12.5px] text-ink-700">
            <div>เมื่อเปิดใช้งาน ระบบจะเริ่ม:</div>
            <ul className="list-disc list-inside pl-1 space-y-1 text-ink-600">
              <li>ลบชั่วคราวไฟล์แนบที่อายุเกิน <strong>{confirmEnable.months} เดือน</strong> ทุกคืน (02:00)</li>
              <li>ไฟล์ที่ลบชั่วคราวจะอยู่ในถังลบชั่วคราว <strong>{confirmEnable.graceDays} วัน</strong> ก่อนถูกลบจริง</li>
              <li>คุณสามารถกู้กลับได้ในระหว่างช่วงนี้</li>
              <li>เอกสารที่ยัง pending / approved / draft จะไม่ถูกแตะต้อง</li>
            </ul>
          </div>
        )}
      </Modal>

      {/* Confirm manual run */}
      <Modal open={!!confirmRun} onClose={() => setConfirmRun(null)} width={520}
        title="ยืนยันการรันตอนนี้"
        subtitle={confirmRun ? RETENTION_SCOPE_META[confirmRun.scope]?.label : ""}
        footer={<>
          <Button variant="secondary" onClick={() => setConfirmRun(null)}>ยกเลิก</Button>
          <Button variant="warn" icon="trash" onClick={() => {
            if (!confirmRun) return;
            runSweep(confirmRun.scope);
            setConfirmRun(null);
          }}>รันตอนนี้</Button>
        </>}>
        {confirmRun && confirmRun.preview && (
          <div className="space-y-2 text-[12.5px] text-ink-700">
            <div>การรันรอบนี้จะ:</div>
            <ul className="list-disc list-inside pl-1 space-y-1 text-ink-600">
              <li>ลบชั่วคราว <strong>{confirmRun.preview.eligible_count}</strong> ไฟล์ ({formatBytes(confirmRun.preview.eligible_bytes)})</li>
              <li>ลบถาวรไฟล์ที่อยู่ในถังลบชั่วคราวเกินช่วง grace</li>
            </ul>
            <div className="mt-3 text-amber-700 bg-amber-50 border border-amber-200 rounded-lg p-3 text-[12px]">
              <Icon name="warning" size={12} className="inline mr-1"/>
              ไฟล์ที่ถูกลบชั่วคราวจะหายไปจากหน้ารายการของเอกสาร แต่ยัง <strong>กู้กลับได้</strong> จากหน้า “ไฟล์ลบชั่วคราว” ภายในช่วง grace
            </div>
          </div>
        )}
      </Modal>
    </div>
  );
};

const UsageStat = ({ label, count, bytes, archived }) => (
  <div className={`rounded-xl border p-3 ${archived ? "border-amber-200 bg-amber-50/40" : "border-ink-100 bg-white"}`}>
    <div className="text-[10.5px] text-ink-500">{label}</div>
    <div className="text-[18px] font-bold text-ink-900 mt-0.5 font-mono">{count || 0}</div>
    <div className="text-[10.5px] text-ink-500 font-mono">{formatBytes(bytes)}</div>
  </div>
);

const PolicyCard = ({ policy, meta, busy, preview, onPreview, onSaveDraft, onSave, onConfirmEnable, onConfirmRun }) => {
  const [months, setMonths] = useState(policy.retention_months || 24);
  const [graceDays, setGraceDays] = useState(policy.soft_delete_days || 30);
  const [showPreview, setShowPreview] = useState(false);
  useEffect(() => {
    setMonths(policy.retention_months || 24);
    setGraceDays(policy.soft_delete_days || 30);
  }, [policy.id, policy.retention_months, policy.soft_delete_days]);

  const handleToggle = () => {
    if (policy.enabled) {
      onSave({ enabled: 0 });
    } else {
      onConfirmEnable(months, graceDays);
    }
  };
  const handlePreview = async () => {
    await onPreview(months);
    setShowPreview(true);
  };

  return (
    <div className={`bg-white rounded-2xl border ${policy.enabled ? "border-emerald-200 shadow-sm" : "border-ink-100"} p-5`}>
      <div className="flex items-start gap-3">
        <div className={`w-9 h-9 rounded-xl ${meta.iconBg} flex items-center justify-center shrink-0`}>
          <Icon name="paperclip" size={16}/>
        </div>
        <div className="flex-1 min-w-0">
          <div className="flex items-center gap-2 flex-wrap">
            <div className="text-[14px] font-bold text-ink-900">{meta.label}</div>
            {policy.enabled ? (
              <Badge color="emerald">เปิดใช้งาน</Badge>
            ) : (
              <Badge color="slate">ปิด</Badge>
            )}
          </div>
          <div className="text-[11.5px] text-ink-500 mt-0.5">
            ระบบจะลบไฟล์แนบ {meta.short} ที่อายุเกินกำหนดแบบชั่วคราว — กู้กลับได้ในช่วง grace
          </div>
          {meta.note && (
            <div className="text-[11px] text-violet-700 bg-violet-50 border border-violet-200 rounded-md px-2 py-1 mt-1.5 inline-block">
              <Icon name="warning" size={10} className="inline mr-1"/>{meta.note}
            </div>
          )}

          {/* Config row */}
          <div className="grid grid-cols-1 md:grid-cols-3 gap-3 mt-3">
            <Field label="อายุที่จะลบชั่วคราว" hint="1–120 เดือน">
              <div className="flex items-center gap-1">
                <Input type="number" min="1" max="120" value={months}
                  onChange={e => setMonths(Math.max(1, Math.min(120, Number(e.target.value) || 24)))}
                  className="w-20 text-right font-mono"/>
                <span className="text-[12.5px] text-ink-600">เดือน</span>
              </div>
            </Field>
            <Field label="ระยะกู้กลับ (grace)" hint="0–180 วัน">
              <div className="flex items-center gap-1">
                <Input type="number" min="0" max="180" value={graceDays}
                  onChange={e => setGraceDays(Math.max(0, Math.min(180, Number(e.target.value) || 30)))}
                  className="w-20 text-right font-mono"/>
                <span className="text-[12.5px] text-ink-600">วัน</span>
              </div>
            </Field>
            <Field label="สถานะ">
              <Toggle checked={!!policy.enabled} onChange={handleToggle}
                label={policy.enabled ? "เปิดใช้งาน" : "ปิด"}/>
            </Field>
          </div>

          {/* Actions */}
          <div className="flex items-center gap-2 mt-3 flex-wrap">
            <Button variant="secondary" size="sm" icon="eye" onClick={handlePreview} disabled={busy === "preview"}>
              {busy === "preview" ? "กำลังคำนวณ…" : "ดูตัวอย่าง"}
            </Button>
            <Button variant="warn" size="sm" icon="trash" onClick={onConfirmRun} disabled={busy === "running"}>
              {busy === "running" ? "กำลังรัน…" : "รันตอนนี้"}
            </Button>
            {(months !== policy.retention_months || graceDays !== policy.soft_delete_days) && (
              <Button variant="primary" size="sm" icon="check" onClick={() => onSave({ retention_months: months, soft_delete_days: graceDays })}>
                บันทึกการตั้งค่า
              </Button>
            )}
          </div>

          {/* Preview result */}
          {showPreview && preview && (
            <div className="mt-3 bg-ink-50/60 border border-ink-100 rounded-xl p-3 text-[12px]">
              <div className="flex items-center justify-between">
                <div className="font-semibold text-ink-800">
                  หากเปิดใช้นโยบายอายุ {preview.months} เดือนตอนนี้:
                </div>
                <button onClick={() => setShowPreview(false)} className="text-ink-400 hover:text-ink-700">
                  <Icon name="x" size={12}/>
                </button>
              </div>
              <div className="mt-1.5 text-ink-700">
                จะลบชั่วคราว <strong>{preview.eligible_count}</strong> ไฟล์ ({formatBytes(preview.eligible_bytes)})
              </div>
              {preview.sample && preview.sample.length > 0 && (
                <div className="mt-2 space-y-1">
                  {preview.sample.map(s => (
                    <div key={s.id} className="text-[11px] text-ink-500 flex justify-between gap-2">
                      <span className="truncate">{s.doc_number} · {s.filename}</span>
                      <span className="font-mono shrink-0">{formatBytes(s.file_size)}</span>
                    </div>
                  ))}
                  {preview.eligible_count > preview.sample.length && (
                    <div className="text-[11px] text-ink-400 italic">…และอีก {preview.eligible_count - preview.sample.length} รายการ</div>
                  )}
                </div>
              )}
            </div>
          )}

          {/* Last run stats */}
          {policy.last_run_at && (
            <div className="mt-3 text-[11px] text-ink-500 border-t border-ink-100 pt-2">
              รันครั้งล่าสุด: {formatDateTime(policy.last_run_at)} ·
              ลบชั่วคราว {policy.last_run_archived || 0} · ลบถาวร {policy.last_run_hard_deleted || 0} · ประหยัด {formatBytes(policy.last_run_bytes_freed)}
            </div>
          )}
        </div>
      </div>
    </div>
  );
};

const RetentionAuditList = ({ tenant, reloadSignal }) => {
  const toast = useToast();
  const [rows, setRows] = useState([]);
  const [loading, setLoading] = useState(false);
  const load = async () => {
    if (!tenant?.id || !window.apiClient) return;
    setLoading(true);
    try {
      const list = await window.apiClient.retentionAuditLog(tenant.id);
      setRows(Array.isArray(list) ? list : []);
    } catch (e) {
      toast({ kind: "error", msg: e.message || "โหลด audit log ไม่สำเร็จ" });
    } finally { setLoading(false); }
  };
  useEffect(() => { load(); /* eslint-disable-next-line */ }, [tenant?.id, reloadSignal]);

  const ACTION_META = {
    policy_change:  { label: "เปลี่ยนนโยบาย", color: "slate" },
    manual_run:     { label: "รันแบบ manual",  color: "indigo" },
    soft_delete:    { label: "ลบชั่วคราว",       color: "amber" },
    hard_delete:    { label: "ลบถาวร",         color: "rose" },
    restore:        { label: "กู้กลับ",        color: "emerald" },
    lock:           { label: "ล็อก",           color: "violet" },
    unlock:         { label: "ปลดล็อก",        color: "slate" },
    cron_error:     { label: "⚠ Cron ล้มเหลว", color: "rose" },
  };

  return (
    <div className="bg-white border border-ink-100 rounded-2xl p-5">
      <div className="flex items-center gap-2 mb-3">
        <Icon name="history" size={14} className="text-ink-500"/>
        <div className="text-[14px] font-semibold text-ink-900">ประวัติการลบ (Retention Audit Log)</div>
        <div className="text-[11px] text-ink-500 ml-auto">{rows.length} รายการล่าสุด</div>
      </div>
      {loading ? (
        <div className="text-center text-ink-500 text-sm py-6">กำลังโหลด…</div>
      ) : rows.length === 0 ? (
        <div className="text-center text-ink-500 text-sm py-6">ยังไม่มีกิจกรรม</div>
      ) : (
        <div className="max-h-[320px] overflow-y-auto thin-scroll">
          <div className="space-y-1">
            {rows.map(r => {
              const meta = ACTION_META[r.action] || { label: r.action, color: "slate" };
              return (
                <div key={r.id} className="flex items-start gap-2 py-2 border-b border-ink-50 last:border-b-0">
                  <Badge color={meta.color}>{meta.label}</Badge>
                  <div className="flex-1 min-w-0">
                    <div className="text-[12px] text-ink-700">{r.target_summary || "—"}</div>
                    <div className="text-[10.5px] text-ink-500">
                      {formatDateTime(r.performed_at)} · {r.performed_by === "cron" ? "ระบบอัตโนมัติ" : r.performed_by}
                      {r.bytes_freed > 0 && ` · ประหยัด ${formatBytes(r.bytes_freed)}`}
                    </div>
                  </div>
                </div>
              );
            })}
          </div>
        </div>
      )}
    </div>
  );
};

// =============================================================================
// ARCHIVE BIN PAGE — list of soft-deleted attachments with restore/delete-now
// =============================================================================
const RetentionArchivePage = ({ tenant, currentRole }) => {
  const toast = useToast();
  const isAdmin = isTenantAdminRole(currentRole);
  const [rows, setRows] = useState([]);
  const [loading, setLoading] = useState(false);
  const [scopeFilter, setScopeFilter] = useState("__all__");
  const [q, setQ] = useState("");
  const [confirmDelete, setConfirmDelete] = useState(null);  // row to delete

  const load = async () => {
    if (!tenant?.id || !window.apiClient || !isAdmin) return;
    setLoading(true);
    try {
      const list = await window.apiClient.retentionListArchived(tenant.id);
      setRows(Array.isArray(list) ? list : []);
    } catch (e) {
      toast({ kind: "error", msg: e.message || "โหลดรายการที่ลบชั่วคราวไม่สำเร็จ" });
    } finally { setLoading(false); }
  };
  useEffect(() => { load(); /* eslint-disable-next-line */ }, [tenant?.id, isAdmin]);

  if (!isAdmin) {
    return (
      <div className="p-10 max-w-3xl mx-auto">
        <EmptyState icon="ban" title="ดูได้เฉพาะ Admin / Super Admin"
          subtitle="หน้านี้จัดการไฟล์ที่กระทบทุก user — สงวนสิทธิ์เฉพาะ Admin / Super Admin"/>
      </div>
    );
  }

  const filtered = useMemo(() => {
    const ql = q.trim().toLowerCase();
    return rows.filter(r => {
      if (scopeFilter !== "__all__" && r.scope !== scopeFilter) return false;
      if (!ql) return true;
      return (r.filename || "").toLowerCase().includes(ql)
          || (r.doc_number || "").toLowerCase().includes(ql);
    });
  }, [rows, scopeFilter, q]);

  const summary = useMemo(() => {
    const totalBytes = filtered.reduce((s, r) => s + (Number(r.file_size) || 0), 0);
    const overdue = filtered.filter(r => r.days_remaining < 0).length;
    return { count: filtered.length, bytes: totalBytes, overdue };
  }, [filtered]);

  const doRestore = async (r) => {
    try {
      await window.apiClient.retentionRestore(tenant.id, r.scope, r.id);
      toast({ kind: "success", msg: `กู้ ${r.filename} กลับมาแล้ว` });
      await load();
    } catch (e) {
      toast({ kind: "error", msg: e.message || "กู้ไม่สำเร็จ" });
    }
  };
  const doDeleteNow = async (r) => {
    try {
      const res = await window.apiClient.retentionDeleteNow(tenant.id, r.scope, r.id);
      toast({ kind: "warn", msg: `ลบ ${r.filename} ถาวรแล้ว · ประหยัด ${formatBytes(res.bytes_freed || 0)}` });
      setConfirmDelete(null);
      await load();
    } catch (e) {
      toast({ kind: "error", msg: e.message || "ลบไม่สำเร็จ" });
    }
  };

  return (
    <div className="p-6 max-w-[1400px] mx-auto">
      <div className="text-[11px] tracking-wider text-ink-500 font-bold mb-1">↕ ระบบ · ไฟล์ลบชั่วคราว</div>
      <div className="flex items-start justify-between gap-3 mb-4">
        <div>
          <div className="text-[24px] font-bold text-ink-900 leading-tight">ไฟล์ลบชั่วคราว (Recycle Bin)</div>
          <div className="text-[13px] text-ink-500 mt-1 leading-snug">
            ไฟล์แนบที่ถูกลบชั่วคราวตามนโยบาย Data Retention — พักไว้ในถังช่วง grace ก่อนระบบจะ <strong>ลบถาวร</strong> · Admin สามารถ <strong>กู้กลับ</strong> หรือ <strong>ลบถาวรทันที</strong> ได้
          </div>
        </div>
      </div>

      {/* Summary */}
      <div className="grid grid-cols-2 md:grid-cols-4 gap-3 mb-4">
        <KpiCard icon="paperclip" tone="indigo"  label="ไฟล์ที่ลบชั่วคราว"      value={summary.count}/>
        <KpiCard icon="package"   tone="violet"  label="ขนาดรวม"            value={formatBytes(summary.bytes)}/>
        <KpiCard icon="warning"   tone="rose"    label="เกินช่วง grace แล้ว" value={summary.overdue} trend="รอ cron มาลบถาวร"/>
        <KpiCard icon="check"     tone="emerald" label="กู้กลับได้"          value={summary.count - summary.overdue}/>
      </div>

      {/* Filters */}
      <div className="flex items-center gap-2 mb-3">
        <div className="relative flex-1 max-w-[460px]">
          <Icon name="search" size={14} className="absolute left-3 top-1/2 -translate-y-1/2 text-ink-400"/>
          <input type="text" value={q} onChange={e => setQ(e.target.value)}
            placeholder="ค้นหาเลขเอกสาร / ชื่อไฟล์"
            className="w-full h-9 pl-9 pr-3 text-[13px] border border-ink-200 rounded-lg bg-white focus:border-brand-500 ring-focus"/>
        </div>
        <Select className="w-[240px]" value={scopeFilter} onChange={e => setScopeFilter(e.target.value)}>
          <option value="__all__">Scope: ทั้งหมด</option>
          <option value="pr_attachments">ไฟล์แนบ PR</option>
          <option value="pc_attachments">ไฟล์แนบ PC</option>
          <option value="supplier_documents">เอกสาร Supplier (replaced)</option>
        </Select>
      </div>

      {/* Table */}
      <div className="bg-white rounded-2xl border border-ink-100 overflow-hidden">
        {loading ? (
          <div className="p-10 text-center text-ink-500 text-sm">กำลังโหลด…</div>
        ) : filtered.length === 0 ? (
          <EmptyState icon="paperclip" title="ถังว่าง — ยังไม่มีไฟล์ที่ถูกลบชั่วคราว"
            subtitle="เมื่อ cron รันตามนโยบาย ไฟล์แนบเก่าจะมาพักไว้ที่นี่ก่อนถูกลบถาวร"/>
        ) : (
          <table className="w-full text-[12.5px]">
            <thead className="bg-ink-50/60 text-ink-500 text-[11px] uppercase">
              <tr>
                <th className="text-left px-4 py-2.5 font-semibold">Scope</th>
                <th className="text-left px-3 py-2.5 font-semibold">เอกสาร</th>
                <th className="text-left px-3 py-2.5 font-semibold">ไฟล์แนบ</th>
                <th className="text-right px-3 py-2.5 font-semibold">ขนาด</th>
                <th className="text-left px-3 py-2.5 font-semibold">วันที่ลบชั่วคราว</th>
                <th className="text-left px-3 py-2.5 font-semibold">คงเหลือ (วัน)</th>
                <th className="text-center px-3 py-2.5 font-semibold">การดำเนินการ</th>
              </tr>
            </thead>
            <tbody>
              {filtered.map(r => {
                const meta = RETENTION_SCOPE_META[r.scope];
                const overdue = r.days_remaining < 0;
                return (
                  <tr key={r.id} className={`border-t border-ink-100 ${overdue ? "bg-rose-50/40" : "hover:bg-ink-50/40"} transition`}>
                    <td className="px-4 py-2.5"><Badge color={meta.badgeColor}>{meta.short}</Badge></td>
                    <td className="px-3 py-2.5 font-mono text-emerald-700">{r.doc_number || "—"}</td>
                    <td className="px-3 py-2.5">
                      <div className="flex items-center gap-1.5">
                        <Icon name="paperclip" size={11} className="text-ink-400"/>
                        <span className="text-ink-800 truncate max-w-[280px]">{r.filename}</span>
                      </div>
                    </td>
                    <td className="px-3 py-2.5 text-right text-ink-700 font-mono">{formatBytes(r.file_size)}</td>
                    <td className="px-3 py-2.5 text-ink-500 whitespace-nowrap">{formatDateTime(r.archived_at)}</td>
                    <td className="px-3 py-2.5">
                      {overdue ? (
                        <Badge color="rose">เกิน {Math.abs(r.days_remaining)} วัน</Badge>
                      ) : r.days_remaining <= 3 ? (
                        <Badge color="amber">{r.days_remaining} วัน</Badge>
                      ) : (
                        <Badge color="emerald">{r.days_remaining} วัน</Badge>
                      )}
                    </td>
                    <td className="px-3 py-2.5">
                      <div className="flex items-center justify-center gap-1">
                        <Tip tip="กู้กลับ"><button onClick={() => doRestore(r)}
                          className="p-1.5 rounded-md text-emerald-700 hover:bg-emerald-50"><Icon name="check" size={13}/></button></Tip>
                        <Tip tip="ลบถาวรทันที"><button onClick={() => setConfirmDelete(r)}
                          className="p-1.5 rounded-md text-rose-600 hover:bg-rose-50"><Icon name="trash" size={13}/></button></Tip>
                      </div>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        )}
      </div>

      {/* Audit log */}
      <div className="mt-6">
        <RetentionAuditList tenant={tenant} reloadSignal={rows.length}/>
      </div>

      {/* Confirm delete */}
      <Modal open={!!confirmDelete} onClose={() => setConfirmDelete(null)} width={460}
        title="ลบถาวรทันที"
        subtitle={confirmDelete ? `${confirmDelete.filename} (${formatBytes(confirmDelete.file_size)})` : ""}
        footer={<>
          <Button variant="secondary" onClick={() => setConfirmDelete(null)}>ยกเลิก</Button>
          <Button variant="danger" icon="trash" onClick={() => confirmDelete && doDeleteNow(confirmDelete)}>ลบถาวร</Button>
        </>}>
        <div className="text-[12.5px] text-ink-700 leading-snug">
          การลบนี้ <strong className="text-rose-600">ไม่สามารถกู้กลับได้</strong> · ไฟล์จะถูกลบออกจาก storage ทันที
        </div>
      </Modal>
    </div>
  );
};

// EXPORT
window.RetentionSettingsSection = RetentionSettingsSection;
window.RetentionArchivePage = RetentionArchivePage;
