(() => {
  const { useState, useEffect, useCallback } = React;
  const { Icon } = window.HiraIcons;
  const { EmptyState } = window.HiraUI;
  const HiraApi = window.HiraApi;
  const HiraRuntime = window.HiraRuntime;
  const HiraValidation = window.HiraValidation;
  const HiraFormat = window.HiraFormat;
  const API = HiraApi.API;
  const handleAuthFail = (message) => HiraRuntime.handleAuthFail(message);
  const { HOME_FILTERS } = window.HiraConstants;

// ── SettingsDrawer ────────────────────────────────────────────────────────────
function SettingsDrawer({
  open, onClose, T, dark, setDark, accounts, devUnlocked, deleteEnabled, toggleDeleteEnabled,
  onDevAuth, images, libraries, libraryItems, onNavToLib, homeFilter, setHomeFilter,
  onRenameLibrary, onDeleteLibrary, onCreateLibrary,
  batchMode, onToggleBatchMode, onOpenAdmin,
}) {
  const [mounted, setMounted] = useState(false);
  const [expandedSection, setExpandedSection] = useState("profile");

  useEffect(() => {
    if (open) { setTimeout(() => setMounted(true), 10); }
    else { setMounted(false); }
  }, [open]);

  if (!open && !mounted) return null;

  const toggle = (id) => setExpandedSection(prev => prev === id ? null : id);

  const Section = ({ id, icon, title, children, noPad }) => {
    const isOpen = expandedSection === id;
    return (
      <div className={`border-b ${dark ? "border-white/[0.06]" : "border-stone-100"}`}>
        <button onClick={() => toggle(id)}
          className={`w-full flex items-center gap-3 px-5 py-3.5 ${T.hoverSoft} transition-colors`}>
          <div className={`w-8 h-8 rounded-lg flex items-center justify-center shrink-0 ${dark ? "bg-white/[0.06]" : "bg-stone-100"}`}>
            {icon}
          </div>
          <span className="text-sm font-medium flex-1 text-left">{title}</span>
          <Icon.ChevronDown className={`transition-transform duration-200 ${isOpen ? "rotate-180" : ""} ${T.sub}`} />
        </button>
        {isOpen && (
          <div className={`${noPad ? "" : "px-5 pb-4"} panel-enter`}>
            {children}
          </div>
        )}
      </div>
    );
  };

  return (
    <div className="fixed inset-0 z-50 flex">
      <div className="absolute inset-0 bg-black/60 backdrop-blur-sm drawer-overlay" onClick={onClose} />
      <div className={`relative w-80 max-w-[88vw] h-full flex flex-col shadow-2xl drawer-enter ${mounted ? "drawer-open" : ""} ${dark ? "bg-[#10121e] text-stone-200" : "bg-white text-stone-800"}`}>

        {/* Header */}
        <div className={`flex items-center justify-between px-5 py-5 border-b ${dark ? "border-white/10" : "border-stone-200"}`}>
          <div className="flex items-center gap-3">
            <div className="w-9 h-9 rounded-full bg-gradient-to-br from-amber-300 to-orange-500 flex items-center justify-center text-[#0a0c16] text-sm font-bold">H</div>
            <div>
              <p className="font-display text-base leading-tight">Pengaturan</p>
              <p className={`text-[11px] ${T.sub}`}>Hira Library · {(images||[]).length} gambar</p>
            </div>
          </div>
          <button onClick={onClose} className={`p-1.5 rounded-full ${T.hoverSoft} ${T.sub}`}><Icon.X /></button>
        </div>

        {/* Body */}
        <div className="flex-1 overflow-y-auto py-1">

          {/* ── Profil & Statistik ── */}
          <Section id="profile" icon={<span className="text-base">👤</span>} title="Profil & Statistik">
            <div className="flex items-center gap-3 mb-3 pt-2">
              <div className="w-12 h-12 rounded-full bg-gradient-to-br from-amber-300 to-orange-500 flex items-center justify-center text-[#0a0c16] text-lg font-bold shrink-0">H</div>
              <div>
                <p className="font-display text-base leading-tight">Hira Studio</p>
                <p className={`text-xs ${T.sub} mt-0.5`}>{(images||[]).length} gambar · {(libraries||[]).length} koleksi · {accounts.length} akun Drive</p>
              </div>
            </div>
            {(libraries||[]).length > 0 && (
              <div className="grid grid-cols-2 gap-2 mt-2">
                {(libraries||[]).slice(0, 4).map((l) => {
                  const cover = libraryItems ? libraryItems(l.id)[0] : null;
                  return (
                    <button key={l.id} onClick={() => { if(onNavToLib) onNavToLib(l.id); onClose(); }} className="text-left group">
                      <div className={`rounded-lg overflow-hidden relative h-14 ring-1 ${T.ring}`}>
                        {cover ? <img src={HiraFormat.imageThumb(cover)} className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300" /> : <div className={`w-full h-full ${T.panel}`} />}
                      </div>
                      <p className={`text-[11px] mt-1 truncate ${T.text}`}>{l.name}</p>
                      <p className={`text-[10px] ${T.sub}`}>{libraryItems ? libraryItems(l.id).length : 0} gambar</p>
                    </button>
                  );
                })}
              </div>
            )}
            {(libraries||[]).length > 4 && (
              <p className="text-xs text-amber-400 mt-2">+{libraries.length - 4} koleksi lainnya</p>
            )}
          </Section>

          {/* ── Tampilan ── */}
          <Section id="display" icon={<span className="text-base">🎨</span>} title="Tampilan">
            <div className="flex items-center justify-between py-2 pt-2">
              <div className="flex items-center gap-2">
                {dark ? <Icon.Moon /> : <Icon.Sun />}
                <span className="text-sm">Mode gelap</span>
              </div>
              <button onClick={() => setDark(d => !d)} className={`w-11 h-6 rounded-full relative flex-shrink-0 transition-colors ${dark ? "bg-amber-400" : "bg-stone-300"}`}>
                <span className={`absolute top-1 w-4 h-4 rounded-full bg-white shadow transition-all ${dark ? "left-6" : "left-1"}`} />
              </button>
            </div>
          </Section>

          {/* ── Filter Konten ── */}
          <Section id="filter" icon={<span className="text-base">🔍</span>} title="Filter Konten" noPad>
            <p className={`text-[11px] ${T.sub} px-5 pt-1 pb-2`}>Filter konten di halaman Beranda</p>
            <div className="px-2 pb-2">
              {HOME_FILTERS.map(f => (
                <button key={f.id} onClick={() => setHomeFilter(f.id)}
                  className={`w-full flex items-center justify-between px-3 py-2.5 rounded-lg ${T.hoverSoft} transition-colors`}>
                  <span className={`text-sm ${homeFilter === f.id ? "text-amber-400 font-medium" : ""}`}>{f.label}</span>
                  <span className={`w-4 h-4 rounded-full border-2 flex items-center justify-center transition-all ${homeFilter === f.id ? "border-amber-400 bg-amber-400" : dark ? "border-white/20" : "border-stone-300"}`}>
                    {homeFilter === f.id && <span className="w-1.5 h-1.5 rounded-full bg-[#0a0c16]" />}
                  </span>
                </button>
              ))}
            </div>
          </Section>

          {/* ── Kelola Koleksi ── */}
          <Section id="collections" icon={<span className="text-base">📁</span>} title="Kelola Koleksi">
            <div className="space-y-2 pt-2">
              {(libraries||[]).map((l) => (
                <LibraryRow key={l.id} lib={l} T={T} dark={dark} imageCount={libraryItems ? libraryItems(l.id).length : 0}
                  onRename={onRenameLibrary} onDelete={onDeleteLibrary} onNav={onNavToLib} onCloseDrawer={onClose} />
              ))}
              {(libraries||[]).length === 0 && (
                <p className={`text-xs ${T.sub} py-2`}>Belum ada koleksi.</p>
              )}
              <button onClick={onCreateLibrary}
                className="flex items-center gap-2 text-xs text-amber-400 hover:text-amber-300 py-2 transition-colors">
                <span className="text-base font-bold leading-none">+</span> Koleksi baru
              </button>
            </div>
          </Section>

          {/* ── Google Drive ── */}
          <Section id="drive" icon={<Icon.Drive className={dark ? "text-blue-400" : "text-blue-500"} />} title="Google Drive">
            <div className="space-y-2 pt-2">
              {(accounts||[]).map((a) => (
                <div key={a.id} className={`flex items-center gap-2.5 px-3 py-2.5 rounded-lg ${dark ? "bg-white/[0.03]" : "bg-stone-50"}`}>
                  <div className={`w-7 h-7 rounded-full flex items-center justify-center text-[10px] font-bold ${dark ? "bg-blue-900/50 text-blue-300" : "bg-blue-100 text-blue-600"}`}>
                    {a.email?.[0]?.toUpperCase() || "?"}
                  </div>
                  <div className="flex-1 min-w-0">
                    <p className="text-xs truncate">{a.email}</p>
                    <p className={`text-[10px] ${T.sub}`}>Tersambung</p>
                  </div>
                  <div className="w-2 h-2 rounded-full bg-emerald-400 shrink-0" />
                </div>
              ))}
              {accounts.length === 0 && (
                <p className={`text-xs ${T.sub} py-2`}>Belum ada akun tersambung.</p>
              )}
              <a href={`${API}/api/auth/login`}
                className="flex items-center gap-2 text-xs text-amber-400 hover:text-amber-300 py-2 transition-colors">
                + Sambungkan akun Google Drive
              </a>
              <button
                type="button"
                onClick={() => { onOpenAdmin?.(); onClose(); }}
                className="flex items-center gap-2 text-xs text-blue-400 hover:text-blue-300 py-2 transition-colors"
              >
                📊 Dashboard Admin
              </button>
            </div>
          </Section>

          {/* ── Akses Edit ── */}
          <Section id="access" icon={<span className="text-base">🔒</span>} title="Akses Edit">
            <div className="pt-2 space-y-3">
              {!devUnlocked ? (
                <button onClick={() => { onClose(); setTimeout(() => onDevAuth(), 250); }}
                  className={`w-full flex items-center gap-3 px-3 py-3 rounded-xl border ${dark ? "border-white/10 hover:border-amber-400/30" : "border-stone-200 hover:border-amber-400/50"} transition-colors`}>
                  <div className={`w-8 h-8 rounded-lg flex items-center justify-center ${dark ? "bg-stone-800" : "bg-stone-100"}`}>
                    <Icon.Lock className={T.sub} />
                  </div>
                  <div className="text-left">
                    <span className="text-sm block">Buka mode edit</span>
                    <span className={`text-[10px] ${T.sub}`}>Diperlukan untuk unggah, edit, dan hapus</span>
                  </div>
                  <Icon.ChevronRight className={`ml-auto ${T.sub}`} />
                </button>
              ) : (
                <>
                  <div className={`flex items-center gap-3 px-3 py-2.5 rounded-lg ${dark ? "bg-emerald-500/10" : "bg-emerald-50"}`}>
                    <div className="w-2 h-2 rounded-full bg-emerald-400" />
                    <span className="text-sm text-emerald-400">Mode edit aktif</span>
                  </div>
                  <div className="flex items-center justify-between px-3 py-2">
                    <div className="flex items-center gap-2">
                      <span className={`w-2 h-2 rounded-full ${batchMode ? "bg-amber-400" : "bg-stone-400"}`} />
                      Mode Batch
                    </div>
                    <button
                      type="button"
                      onClick={() => onToggleBatchMode?.()}
                      className={`w-11 h-6 rounded-full relative flex-shrink-0 transition-colors ${batchMode ? "bg-amber-400" : "bg-stone-300"}`}
                      aria-label="Toggle mode batch"
                    >
                      <span className={`absolute top-1 w-4 h-4 rounded-full bg-white shadow transition-all ${batchMode ? "left-6" : "left-1"}`} />
                    </button>
                  </div>
                  <div className="flex items-center justify-between px-3 py-2">
                    <div className="flex items-center gap-2">
                      <Icon.Trash className={deleteEnabled ? "text-rose-400" : T.sub} />
                      <span className="text-sm">Tombol hapus</span>
                    </div>
                    <button onClick={toggleDeleteEnabled} className={`w-11 h-6 rounded-full relative flex-shrink-0 transition-colors ${deleteEnabled ? "bg-rose-400" : "bg-stone-300"}`}>
                      <span className={`absolute top-1 w-4 h-4 rounded-full bg-white shadow transition-all ${deleteEnabled ? "left-6" : "left-1"}`} />
                    </button>
                  </div>
                </>
              )}
            </div>
          </Section>
        </div>

        {/* Footer */}
        <div className={`px-5 py-4 border-t ${dark ? "border-white/10" : "border-stone-200"} ${T.faint} text-xs text-center`}>
          Hira Library · 灯
        </div>
      </div>
    </div>
  );
}

// ── LibraryRow (inline rename/delete for settings) ──────────────────────────
function LibraryRow({ lib, T, dark, imageCount, onRename, onDelete, onNav, onCloseDrawer }) {
  const [editing, setEditing] = useState(false);
  const [name, setName] = useState(lib.name);
  const [confirmDelete, setConfirmDelete] = useState(false);

  const saveRename = () => {
    const validation = HiraValidation.validateLibraryName(name);
    if (!validation.valid) return;
    if (validation.value && validation.value !== lib.name) onRename(lib.id, validation.value);
    setEditing(false);
  };

  const doDelete = () => {
    onDelete(lib.id);
    setConfirmDelete(false);
  };

  return (
    <div className={`flex items-center gap-2.5 px-3 py-2.5 rounded-lg ${dark ? "bg-white/[0.03]" : "bg-stone-50"}`}>
      {editing ? (
        <div className="flex-1 flex items-center gap-2">
          <input autoFocus value={name} onChange={e => setName(e.target.value)}
            onKeyDown={e => { if (e.key === "Enter") saveRename(); if (e.key === "Escape") setEditing(false); }}
            className={`flex-1 text-xs px-2 py-1.5 rounded-lg border ${T.inputBg}`} />
          <button onClick={saveRename} className="text-xs bg-amber-400 text-[#0a0c16] px-2.5 py-1.5 rounded-lg font-medium">✓</button>
          <button onClick={() => { setEditing(false); setName(lib.name); }} className={`text-xs px-2 py-1.5 rounded-lg border ${T.chipInactive}`}>✕</button>
        </div>
      ) : confirmDelete ? (
        <div className="flex-1 flex items-center gap-2">
          <span className="text-xs text-rose-400 flex-1">Hapus "{lib.name}"?</span>
          <button onClick={doDelete} className="text-xs bg-rose-500 text-white px-2.5 py-1.5 rounded-lg font-medium">Ya</button>
          <button onClick={() => setConfirmDelete(false)} className={`text-xs px-2 py-1.5 rounded-lg border ${T.chipInactive}`}>Batal</button>
        </div>
      ) : (
        <>
          <button onClick={() => { if(onNav) onNav(lib.id); onCloseDrawer(); }} className="flex-1 min-w-0 text-left">
            <p className="text-sm truncate">{lib.name}</p>
            <p className={`text-[10px] ${T.sub}`}>{imageCount} gambar</p>
          </button>
          <button onClick={() => setEditing(true)} className={`p-1.5 rounded-lg ${T.hoverSoft} ${T.sub}`} title="Rename">
            <Icon.Edit />
          </button>
          <button onClick={() => setConfirmDelete(true)} className={`p-1.5 rounded-lg ${T.hoverSoft} text-rose-400`} title="Hapus">
            <Icon.Trash />
          </button>
        </>
      )}
    </div>
  );
}

// ── ProductionReadinessPanel (P1) ───────────────────────────────────────────
function ProductionReadinessPanel({ T, stats }) {
  if (!stats) return null;
  const checks = [];
  checks.push({ ok: stats.adminRequired, label: "ADMIN_TOKEN aktif", warn: "OpenMode aktif — set ADMIN_TOKEN di production!", isOptional: false });
  checks.push({ ok: stats.tokenEncryptionConfigured, label: "TOKEN_ENCRYPTION_KEY aktif", warn: "TOKEN_ENCRYPTION_KEY belum diset. Token Drive lama mungkin tersimpan plaintext.", isOptional: false });
  checks.push({ ok: (stats.accounts||0)>0, label: `Google Drive tersambung (${stats.accounts||0} akun)`, warn: "Belum ada akun Drive tersambung", isOptional: false });
  checks.push({ ok: true, label: "PWA manifest tersedia", warn: null, isOptional: true, custom: typeof window!=="undefined" && ("serviceWorker" in navigator) });
  checks.push({ ok: stats.frontendUrlConfigured, label: "FRONTEND_URL terkonfigurasi", warn: "FRONTEND_URL belum diset (fallback ke origin request)", isOptional: true });
  checks.push({ ok: stats.corsConfigured, label: "CORS whitelist aktif", warn: "CORS whitelist belum dikonfigurasi (pakai wildcard *)", isOptional: true });
  checks.push({ ok: stats.turnstileConfigured, label: "Turnstile anti-bot aktif", warn: "Turnstile belum dikonfigurasi (opsional)", isOptional: true });
  checks.push({ ok: stats.kvRateLimitConfigured, label: "KV rate limit aktif", warn: "KV rate limit belum dikonfigurasi (pakai in-memory)", isOptional: true });
  // counts
  const shareActive = stats.shareLinksActive||0;
  const trashCount = stats.trash||0;
  return (
    <div className={`rounded-2xl border p-5 mb-6 ${T.panel}`}>
      <h2 className="font-display text-lg mb-1">Production Readiness</h2>
      <p className={`text-xs ${T.sub} mb-4`}>Status konfigurasi production. Tidak ada secret yang ditampilkan, hanya boolean.</p>
      <div className="space-y-2">
        {checks.map((c, i) => {
          const isOk = c.custom !== undefined ? Boolean(c.custom) : Boolean(c.ok);
          const icon = isOk ? "✓" : "⚠";
          const color = isOk ? "text-emerald-400" : (c.isOptional ? "text-amber-400" : "text-rose-400");
          return (
            <div key={i} className={`flex items-start gap-2 text-sm px-3 py-2 rounded-xl border ${isOk ? "border-emerald-400/20 bg-emerald-400/5" : c.isOptional ? "border-amber-400/20 bg-amber-400/5" : "border-rose-400/20 bg-rose-400/10"}`}>
              <span className={color}>{icon}</span>
              <div className="flex-1">
                <span className={isOk ? "" : color}>{c.label}</span>
                {!isOk && c.warn && <p className={`text-xs mt-0.5 ${T.sub}`}>{c.warn}</p>}
              </div>
            </div>
          );
        })}
        {shareActive>0 && <div className={`flex items-center gap-2 text-sm px-3 py-2 rounded-xl border border-amber-400/20 bg-amber-400/5`}><span className="text-amber-400">⚠</span><span className={T.sub}>{shareActive} share links aktif — review berkala dan revoke jika tidak perlu</span></div>}
        {trashCount>0 && <div className={`flex items-center gap-2 text-sm px-3 py-2 rounded-xl border border-white/10 ${T.panel}`}><span className={T.sub}>🗑</span><span className={T.sub}>{trashCount} item di Trash — kosongkan jika tidak diperlukan</span></div>}
        {stats.openMode && <div className="flex items-center gap-2 text-sm px-3 py-2 rounded-xl border border-rose-400/30 bg-rose-500/10"><span className="text-rose-400">⚠</span><span className="text-rose-300">OpenMode aktif — ADMIN_TOKEN kosong, endpoint sensitif terbuka!</span></div>}
      </div>
    </div>
  );
}

// ── TagManagerPanel (P1 ringan) ──────────────────────────────────────────────
function TagManagerPanel({ T, onToast, onChanged }) {
  const [tags, setTags] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [filter, setFilter] = React.useState("");
  const load = useCallback(async () => {
    setLoading(true);
    try {
      const data = await HiraApi.getAdminTags();
      setTags(data.tags || []);
    } catch (error) {
      if (error.status === 401) handleAuthFail();
      else onToast?.(error.message || "Gagal memuat tags", "error");
    } finally {
      setLoading(false);
    }
  }, [onToast]);
  React.useEffect(() => { load(); }, [load]);
  const filtered = filter.trim() ? tags.filter((tag) => tag.tag.toLowerCase().includes(filter.toLowerCase())) : tags;
  const renameTag = async (fromTag) => {
    const to = prompt(`Rename tag "${fromTag}" menjadi:`, fromTag);
    if (!to) return;
    const validation = HiraValidation.validateTagList([to]);
    const normTo = validation.value[0];
    if (!validation.valid || !normTo || normTo === fromTag) return;
    if (!confirm(`Yakin rename "${fromTag}" → "${normTo}" ? ${tags.find((tag) => tag.tag === fromTag)?.count || 0} gambar akan terpengaruh.`)) return;
    try {
      const data = await HiraApi.renameTag(fromTag, normTo);
      onToast?.(`Tag "${fromTag}" → "${normTo}" (${data.updated} gambar)`, "success");
      await load();
      onChanged?.();
    } catch (error) {
      if (error.status === 401) handleAuthFail();
      else onToast?.(error.message || "Gagal rename", "error");
    }
  };
  const deleteTag = async (tag) => {
    if (!confirm(`Hapus tag "${tag}" dari semua gambar? Tindakan ini tidak mengubah content rating.`)) return;
    try {
      const data = await HiraApi.deleteTag(tag);
      onToast?.(`Tag "${tag}" dihapus dari ${data.updated} gambar`, "success");
      await load();
      onChanged?.();
    } catch (error) {
      if (error.status === 401) handleAuthFail();
      else onToast?.(error.message || "Gagal hapus tag", "error");
    }
  };
  return (
    <div className={`rounded-2xl border p-5 mt-6 ${T.panel}`}>
      <div className="flex items-center justify-between mb-4">
        <div>
          <h2 className="font-display text-lg">Kelola Tag</h2>
          <p className={`text-xs ${T.sub}`}>Rename / hapus tag tanpa ubah schema. Termasuk Trash agar konsisten saat restore.</p>
        </div>
        <button onClick={load} className={`text-xs px-3 py-1.5 rounded-full border ${T.chipInactive}`}>Muat ulang</button>
      </div>
      <div className={`flex items-center gap-2 border rounded-xl px-3 py-2 mb-3 ${T.inputBg}`}>
        <span className={T.sub}>🔍</span>
        <input value={filter} onChange={e=>setFilter(e.target.value)} placeholder="Cari tag..." className="flex-1 bg-transparent outline-none text-sm" />
        {filter && <button onClick={()=>setFilter("")} className={T.sub}><Icon.X /></button>}
      </div>
      {loading ? <p className={`text-xs ${T.sub} py-4`}>Memuat tags…</p> : filtered.length===0 ? <p className={`text-xs ${T.sub} py-4`}>Tidak ada tag{filter?` untuk "${filter}"`:""}.</p> : (
        <div className="space-y-1.5 max-h-96 overflow-y-auto">
          {filtered.slice(0,100).map(t=>(
            <div key={t.tag} className={`flex items-center gap-2 px-3 py-2 rounded-xl border ${T.panel}`}>
              <span className="flex-1 text-sm truncate">#{t.tag} <span className={`text-xs ${T.sub}`}>({t.count})</span></span>
              <button onClick={()=>renameTag(t.tag)} className={`text-xs px-2.5 py-1 rounded-full border ${T.chipInactive}`}>Rename</button>
              <button onClick={()=>deleteTag(t.tag)} className="text-xs px-2.5 py-1 rounded-full border border-rose-400/30 text-rose-400">Hapus</button>
            </div>
          ))}
          {filtered.length>100 && <p className={`text-xs ${T.sub} text-center py-2`}>Menampilkan 100 dari {filtered.length} tag — gunakan pencarian untuk filter</p>}
        </div>
      )}
    </div>
  );
}



// ── AdminDashboard (P1 + readiness) ───────────────────────────────────────
function AdminDashboard({ T, onExport, onImport, onExportFull, onImportFull, onToast, onChanged }) {
  const [stats, setStats] = React.useState(null);
  const [loading, setLoading] = React.useState(true);
  React.useEffect(() => {
    let cancelled = false;
    HiraApi.getAdminStats()
      .then((data) => { if (!cancelled) setStats(data); })
      .catch((error) => {
        if (!cancelled) {
          if (error.status === 401) handleAuthFail();
          setStats({ error: error.message || "Gagal memuat statistik." });
        }
      })
      .finally(() => { if (!cancelled) setLoading(false); });
    return () => { cancelled = true; };
  }, []);
  if (loading) return <div className={`${T.sub} text-sm py-8 text-center`}>Memuat statistik...</div>;
  if (stats?.error) return <div className="text-rose-400 text-sm py-8 text-center">{stats.error}</div>;
  const cards = [
    ["Gambar", stats?.images || 0],
    ["Koleksi", stats?.libraries || 0],
    ["Akun Drive", stats?.accounts || 0],
    ["Tag Unik", stats?.tags?.length || 0],
    ["Trash", stats?.trash || 0],
    ["Share aktif", stats?.shareLinksActive || 0],
  ];
  return (
    <>
      <ProductionReadinessPanel T={T} stats={stats} />
      <div className={`rounded-2xl border p-6 ${T.panel}`}>
        <div className="flex flex-col sm:flex-row sm:items-start sm:justify-between gap-4 mb-5">
          <div>
            <h2 className="font-display text-xl">Ringkasan Produk</h2>
            <p className={`text-xs ${T.sub} mt-1`}>Status: {stats?.adminRequired ? "locked (ADMIN_TOKEN aktif)" : "open mode"} · Enc: {stats?.tokenEncryptionConfigured ? "✓" : "⚠"} · CORS: {stats?.corsConfigured ? "whitelist" : "*"} · Turnstile: {stats?.turnstileConfigured ? "✓" : "opsional"} · KV: {stats?.kvRateLimitConfigured ? "✓" : "memory"}</p>
          </div>
          <div className="flex flex-wrap gap-2">
            <button onClick={onExport} className="text-xs px-3 py-1.5 rounded-full border border-white/10 text-stone-300">Export Images</button>
            <button onClick={onImport} className={`text-xs px-3 py-1.5 rounded-full border ${T.chipInactive}`}>Import Images</button>
            <button onClick={() => {
              const includeTokens = confirm("Sertakan token share publik dalam backup? (Direkomendasikan agar link lama tetap aktif setelah di-restore)");
              onExportFull?.(includeTokens);
            }} className="text-xs px-3 py-1.5 rounded-full bg-amber-400 text-[#0a0c16] font-medium">Export Full Backup</button>
            <button onClick={onImportFull} className="text-xs px-3 py-1.5 rounded-full bg-amber-400/20 text-amber-300 border border-amber-400/30">Import Full Backup</button>
            <a href={`${API}/api/auth/login`} className={`text-xs px-3 py-1.5 rounded-full border ${T.chipInactive}`}>Sambung Drive</a>
          </div>
        </div>
        <div className="grid grid-cols-2 sm:grid-cols-3 lg:grid-cols-6 gap-3">
          {cards.map(([label, value]) => (
            <div key={label} className={`rounded-xl p-4 ${T.panel} border`}>
              <p className={`text-xs ${T.sub}`}>{label}</p>
              <p className="text-2xl font-bold text-amber-400">{value}</p>
            </div>
          ))}
        </div>
        {stats?.tags?.length > 0 && (
          <div className="mt-6">
            <h3 className="text-sm font-medium mb-3">Tag Terbanyak</h3>
            <div className="flex flex-wrap gap-2">
              {stats.tags.slice(0, 10).map(({ tag, count }) => (
                <span key={tag} className={`text-xs px-3 py-1 rounded-full border ${T.chipInactive}`}>#{tag} ({count})</span>
              ))}
            </div>
          </div>
        )}
      </div>

      <DriveHealthPanel T={T} onToast={onToast} />
      <MaintenancePanel T={T} onToast={onToast} onChanged={onChanged} />
      <AuditLogsPanel T={T} onToast={onToast} />
    </>
  );
}

function ShareLinksPanel({ T, onToast }) {
  const [links, setLinks] = React.useState([]);
  const [loading, setLoading] = React.useState(true);
  const [filterType, setFilterType] = React.useState("all");
  const [filterStatus, setFilterStatus] = React.useState("active");

  const loadLinks = React.useCallback(async () => {
    setLoading(true);
    try {
      const params = {};
      if (filterType !== "all") params.type = filterType;
      
      if (filterStatus === "active") {
        params.includeRevoked = "false";
        params.includeExpired = "false";
      } else if (filterStatus === "expired") {
        params.includeRevoked = "false";
        params.includeExpired = "true";
      } else if (filterStatus === "revoked") {
        params.includeRevoked = "true";
        params.includeExpired = "true";
      } else {
        params.includeRevoked = "true";
        params.includeExpired = "true";
      }

      const data = await HiraApi.listShareLinks(params);
      let list = data.links || [];
      
      if (filterStatus === "expired") {
        list = list.filter(l => l.expired && !l.revoked);
      } else if (filterStatus === "revoked") {
        list = list.filter(l => l.revoked);
      } else if (filterStatus === "active") {
        list = list.filter(l => !l.expired && !l.revoked);
      }
      
      setLinks(list);
    } catch (e) {
      if (e.status === 401) handleAuthFail();
      else onToast?.(e.message || "Gagal memuat share links", "error");
    } finally {
      setLoading(false);
    }
  }, [filterType, filterStatus]);

  React.useEffect(() => { loadLinks(); }, [loadLinks]);

  const revoke = async (link) => {
    if (!window.confirm(`Revoke link ${link.targetName || link.targetId}?`)) return;
    try {
      await HiraApi.revokeShareLink(link.id);
      onToast?.("Link publik dicabut", "success");
      loadLinks();
    } catch (e) {
      if (e.status === 401) handleAuthFail();
      else onToast?.(e.message || "Gagal revoke link", "error");
    }
  };

  const extend = async (link) => {
    const res = prompt(
      `Masukkan tanggal kedaluwarsa baru (Format: YYYY-MM-DD), atau kosongkan untuk tanpa batas:`,
      link.expiresAt ? link.expiresAt.substring(0, 10) : ""
    );
    if (res === null) return;

    let expiresAt = null;
    if (res.trim() !== "") {
      const parsed = new Date(res.trim());
      if (isNaN(parsed.getTime())) {
        onToast?.("Format tanggal tidak valid. Gunakan YYYY-MM-DD.", "error");
        return;
      }
      if (parsed.getTime() <= Date.now()) {
        onToast?.("Tanggal harus di masa depan.", "error");
        return;
      }
      expiresAt = parsed.toISOString();
    }

    try {
      await HiraApi.extendShareLinkExpiry(link.id, expiresAt, true);
      onToast?.("Tanggal kedaluwarsa berhasil diperbarui.", "success");
      loadLinks();
    } catch (e) {
      if (e.status === 401) handleAuthFail();
      else onToast?.(e.message || "Gagal memperbarui kedaluwarsa.", "error");
    }
  };

  const formatExpiry = (link) => {
    if (link.revoked) return "Revoked";
    if (link.expired) return "Expired";
    if (!link.expiresAt) return "Tanpa kedaluwarsa";
    try {
      const d = new Date(link.expiresAt);
      return `Exp: ${d.toLocaleDateString("id-ID", { day:"numeric", month:"short", year:"numeric" })}`;
    } catch { return `Exp: ${link.expiresAt}`; }
  };

  return (
    <div id="share-links" className={`rounded-2xl border p-5 mt-6 ${T.panel}`}>
      <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-3 mb-4">
        <div>
          <h2 className="font-display text-lg">Share Links Publik</h2>
          <p className={`text-xs ${T.sub}`}>Masa aktif share links publik. Anda dapat memperpanjang atau mencabut akses kapan saja.</p>
        </div>
        <button onClick={loadLinks} className={`text-xs px-3 py-1.5 rounded-full border ${T.chipInactive} self-end sm:self-auto`}>Muat ulang</button>
      </div>

      {/* Filters */}
      <div className="flex flex-wrap gap-3 mb-4 text-xs">
        <div className="flex items-center gap-2">
          <span className={T.sub}>Status:</span>
          <select value={filterStatus} onChange={e => setFilterStatus(e.target.value)} className={`border rounded-lg px-2 py-1 ${T.inputBg}`}>
            <option value="active">Aktif</option>
            <option value="expired">Kedaluwarsa</option>
            <option value="revoked">Dicabut</option>
            <option value="all">Semua</option>
          </select>
        </div>

        <div className="flex items-center gap-2">
          <span className={T.sub}>Tipe:</span>
          <select value={filterType} onChange={e => setFilterType(e.target.value)} className={`border rounded-lg px-2 py-1 ${T.inputBg}`}>
            <option value="all">Semua</option>
            <option value="image">Gambar</option>
            <option value="library">Koleksi</option>
          </select>
        </div>
      </div>

      {loading ? <p className={`text-xs ${T.sub} py-4`}>Memuat share links…</p> : links.length === 0 ? (
        <EmptyState T={T} title="Tidak ada share link" body="Tidak ada share link publik yang cocok dengan filter Anda." />
      ) : (
        <div className="space-y-2">
          {links.map((link) => (
            <div key={link.id} className={`flex flex-col sm:flex-row sm:items-center gap-3 px-3 py-3 rounded-xl border ${link.expired||link.revoked? "border-rose-400/20 bg-rose-500/5" : T.panel}`}>
              <div className="flex-1 min-w-0">
                <p className="text-sm truncate">{link.type === "image" ? "Gambar" : "Koleksi"}: {link.targetName || link.targetId} {link.expired ? "· Expired" : link.revoked ? "· Revoked" : ""}</p>
                <p className={`text-[11px] ${link.expired||link.revoked? "text-rose-400" : T.sub}`}>{link.createdAt ? new Date(link.createdAt).toLocaleString("id-ID") : ""} · {formatExpiry(link)}</p>
                <p className={`text-[10px] ${T.sub} truncate`}>{link.publicUrl}</p>
              </div>
              <div className="flex gap-2 shrink-0">
                <button onClick={() => HiraFormat.copyText(link.publicUrl).then(() => onToast?.("Link disalin", "success"))} className={`text-xs px-3 py-1.5 rounded-full border ${T.chipInactive}`}>Salin</button>
                <button onClick={() => extend(link)} className={`text-xs px-3 py-1.5 rounded-full border ${T.chipInactive}`}>Perpanjang</button>
                {!link.revoked && (
                  <button onClick={() => revoke(link)} className="text-xs px-3 py-1.5 rounded-full border border-rose-400/30 text-rose-400">Revoke</button>
                )}
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

// ── AuditLogsPanel (P4) ──────────────────────────────────────────────────────
function AuditLogsPanel({ T, onToast }) {
  const [logs, setLogs] = useState([]);
  const [loading, setLoading] = useState(true);
  const [hasMore, setHasMore] = useState(false);
  const [offset, setOffset] = useState(0);

  const loadLogs = useCallback(async (currentOffset = 0, append = false) => {
    setLoading(true);
    try {
      const data = await HiraApi.getAuditLogs({ limit: 20, offset: currentOffset });
      if (append) {
        setLogs(prev => [...prev, ...(data.logs || [])]);
      } else {
        setLogs(data.logs || []);
      }
      setHasMore(data.hasMore);
      setOffset(currentOffset);
    } catch (e) {
      if (e.status === 401) handleAuthFail();
      else onToast?.(e.message || "Gagal memuat log aktivitas", "error");
    } finally {
      setLoading(false);
    }
  }, [onToast]);

  useEffect(() => {
    loadLogs(0, false);
  }, [loadLogs]);

  return (
    <div className={`rounded-2xl border p-5 mt-6 ${T.panel}`}>
      <div className="flex items-center justify-between mb-4">
        <div>
          <h2 className="font-display text-lg">Aktivitas Terbaru</h2>
          <p className={`text-xs ${T.sub}`}>Log audit administratif untuk memantau aktivitas penting admin.</p>
        </div>
        <button onClick={() => loadLogs(0, false)} className={`text-xs px-3 py-1.5 rounded-full border ${T.chipInactive}`}>Segarkan</button>
      </div>
      
      {logs.length === 0 && !loading ? (
        <p className={`text-xs ${T.sub} py-4`}>Belum ada aktivitas tercatat.</p>
      ) : (
        <div className="space-y-3 max-h-96 overflow-y-auto pr-1">
          {logs.map((log) => (
            <div key={log.id} className={`p-3.5 rounded-xl border ${T.panel} flex flex-col gap-1.5`}>
              <div className="flex items-start justify-between gap-2">
                <span className="text-sm font-medium text-amber-400 capitalize">{log.action}</span>
                <span className={`text-[10px] ${T.sub}`}>{new Date(log.createdAt).toLocaleString("id-ID")}</span>
              </div>
              {log.targetType && (
                <p className={`text-xs ${T.sub}`}>Target: <span className="font-mono">{log.targetType} ({log.targetId})</span></p>
              )}
              {Object.keys(log.metadata || {}).length > 0 && (
                <div className={`text-[11px] p-2 rounded bg-black/20 font-mono text-stone-300 break-all`}>
                  {JSON.stringify(log.metadata)}
                </div>
              )}
              <div className="flex items-center justify-between text-[10px] text-stone-500 pt-1 border-t border-white/[0.04]">
                <span>IP: {log.ip || "unknown"}</span>
                <span className="truncate max-w-[200px]" title={log.userAgent}>UA: {log.userAgent || "unknown"}</span>
              </div>
            </div>
          ))}
          {hasMore && (
            <button
              onClick={() => loadLogs(offset + 20, true)}
              disabled={loading}
              className={`w-full py-2 text-xs rounded-xl border ${T.chipInactive} hover:text-amber-400 transition-colors`}
            >
              {loading ? "Memuat..." : "Tampilkan Lebih Banyak"}
            </button>
          )}
        </div>
      )}
    </div>
  );
}

// ── MaintenancePanel (P4) ────────────────────────────────────────────────────
function MaintenancePanel({ T, onToast, onChanged }) {
  const [summary, setSummary] = useState(null);
  const [scanning, setScanning] = useState(false);
  const [cleaning, setCleaning] = useState(false);

  const scan = async () => {
    setScanning(true);
    try {
      const data = await HiraApi.getMaintenanceSummary();
      setSummary(data);
    } catch (e) {
      if (e.status === 401) handleAuthFail();
      else onToast?.(e.message || "Gagal melakukan scan maintenance", "error");
    } finally {
      setScanning(false);
    }
  };

  const cleanup = async (options) => {
    if (!window.confirm("Apakah Anda yakin ingin menjalankan aksi perbaikan manual ini?")) return;
    setCleaning(true);
    try {
      await HiraApi.runMaintenanceCleanup(options);
      onToast?.("Perbaikan berhasil dijalankan!", "success");
      await scan();
      onChanged?.();
    } catch (e) {
      if (e.status === 401) handleAuthFail();
      else onToast?.(e.message || "Gagal menjalankan cleanup", "error");
    } finally {
      setCleaning(false);
    }
  };

  useEffect(() => {
    scan();
  }, []);

  return (
    <div className={`rounded-2xl border p-5 mt-6 ${T.panel}`}>
      <div className="flex items-center justify-between mb-4">
        <div>
          <h2 className="font-display text-lg">Pembersihan & Maintenance</h2>
          <p className={`text-xs ${T.sub}`}>Identifikasi dan perbaiki referensi database yang tidak konsisten secara manual.</p>
        </div>
        <button onClick={scan} disabled={scanning} className={`text-xs px-3 py-1.5 rounded-full border ${T.chipInactive}`}>
          {scanning ? "Memindai..." : "Pindai Ulang"}
        </button>
      </div>

      {summary && (
        <div className="space-y-3.5">
          <div className="grid grid-cols-2 gap-3">
            <div className={`p-3 rounded-xl border ${T.panel}`}>
              <p className={`text-[11px] ${T.sub}`}>Referensi Library Orphan</p>
              <p className="text-xl font-bold text-amber-400">{summary.orphanedLibraryRefs}</p>
              {summary.orphanedLibraryRefs > 0 && (
                <button
                  onClick={() => cleanup({ fixOrphanedLibraryRefs: true })}
                  disabled={cleaning}
                  className="mt-1.5 text-[10px] text-amber-300 hover:text-amber-400 font-medium"
                >
                  Perbaiki Sekarang
                </button>
              )}
            </div>
            <div className={`p-3 rounded-xl border ${T.panel}`}>
              <p className={`text-[11px] ${T.sub}`}>Share Link Kedaluwarsa</p>
              <p className="text-xl font-bold text-amber-400">{summary.expiredShareLinks}</p>
              {summary.expiredShareLinks > 0 && (
                <button
                  onClick={() => cleanup({ revokeExpiredShareLinks: true })}
                  disabled={cleaning}
                  className="mt-1.5 text-[10px] text-amber-300 hover:text-amber-400 font-medium"
                >
                  Revoke Semuanya
                </button>
              )}
            </div>
            <div className={`p-3 rounded-xl border ${T.panel}`}>
              <p className={`text-[11px] ${T.sub}`}>Tanpa Tanggal Dibuat</p>
              <p className="text-xl font-bold text-amber-400">{summary.imagesWithoutCreatedAt}</p>
              {summary.imagesWithoutCreatedAt > 0 && (
                <button
                  onClick={() => cleanup({ fillMissingCreatedAt: true })}
                  disabled={cleaning}
                  className="mt-1.5 text-[10px] text-amber-300 hover:text-amber-400 font-medium"
                >
                  Isi Tanggal Default
                </button>
              )}
            </div>
            <div className={`p-3 rounded-xl border ${T.panel}`}>
              <p className={`text-[11px] ${T.sub}`}>Duplikat Konten Aktif</p>
              <p className="text-xl font-bold text-amber-400">{summary.duplicateContentHashes}</p>
            </div>
          </div>
          
          <div className="grid grid-cols-1 sm:grid-cols-2 gap-2 text-xs">
            <div className="flex items-center justify-between p-2 rounded bg-black/15">
              <span className={T.sub}>Gambar Terhapus (Trash):</span>
              <span className="font-bold text-amber-400">{summary.deletedImages}</span>
            </div>
            <div className="flex items-center justify-between p-2 rounded bg-black/15">
              <span className={T.sub}>Share Link Direvoke:</span>
              <span className="font-bold text-amber-400">{summary.revokedShareLinks}</span>
            </div>
          </div>
        </div>
      )}
    </div>
  );
}

// ── DriveHealthPanel (P4) ────────────────────────────────────────────────────
function DriveHealthPanel({ T, onToast }) {
  const [accounts, setAccounts] = useState([]);
  const [loading, setLoading] = useState(true);

  const checkHealth = async () => {
    setLoading(true);
    try {
      const data = await HiraApi.getDriveHealth();
      setAccounts(data.accounts || []);
    } catch (e) {
      if (e.status === 401) handleAuthFail();
      else onToast?.(e.message || "Gagal memuat status kesehatan Drive", "error");
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    checkHealth();
  }, []);

  return (
    <div className={`rounded-2xl border p-5 mt-6 ${T.panel}`}>
      <div className="flex items-center justify-between mb-4">
        <div>
          <h2 className="font-display text-lg">Kesehatan Penyimpanan Drive</h2>
          <p className={`text-xs ${T.sub}`}>Periksa status koneksi, kedaluwarsa token, dan folder penyimpanan untuk setiap akun Google Drive.</p>
        </div>
      </div>

      {accounts.length === 0 && !loading ? (
        <p className={`text-xs ${T.sub} py-4`}>Belum ada akun Google Drive yang terhubung.</p>
      ) : (
        <div className="space-y-3">
          {accounts.map((acc) => {
            const statusColor = acc.status === "ok" ? "bg-emerald-400 text-emerald-400 border-emerald-400/20" : acc.status === "needs_reauth" ? "bg-rose-400 text-rose-400 border-rose-400/20" : "bg-amber-400 text-amber-400 border-amber-400/20";
            return (
              <div key={acc.id} className={`p-4 rounded-xl border ${T.panel} flex flex-col sm:flex-row sm:items-center justify-between gap-3`}>
                <div className="flex items-start gap-3 min-w-0">
                  <div className="w-10 h-10 rounded-full bg-blue-500/10 text-blue-400 flex items-center justify-center font-bold text-sm shrink-0">
                    {acc.email ? acc.email[0].toUpperCase() : "G"}
                  </div>
                  <div className="min-w-0">
                    <p className="text-sm font-medium truncate">{acc.email || "Google Drive Account"}</p>
                    <p className={`text-xs ${T.sub} mt-0.5`}>Folder Configured: {acc.hasFolderId ? "✓ Yes" : "✕ No"}</p>
                    {acc.tokenExpiry && (
                      <p className={`text-[11px] ${T.sub} mt-0.5`}>
                        Token Expiry: {new Date(acc.tokenExpiry).toLocaleString("id-ID")}
                        {acc.tokenExpiredSoon && <span className="text-rose-400 ml-1">(Soon / Expired)</span>}
                      </p>
                    )}
                  </div>
                </div>
                <div className="flex items-center gap-2">
                  <span className={`text-xs px-2.5 py-1 rounded-full border bg-opacity-10 capitalize ${statusColor}`}>
                    {acc.status === "ok" ? "Connected" : acc.status === "needs_reauth" ? "Needs Reauth" : "Error"}
                  </span>
                  {acc.status === "needs_reauth" && (
                    <a href={`${API}/api/auth/login`} className="text-xs bg-amber-400 text-[#0a0c16] font-medium px-2.5 py-1.5 rounded-lg transition-colors">
                      Sambungkan Lagi
                    </a>
                  )}
                </div>
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
}


  window.HiraAdmin = {
    SettingsDrawer,
    LibraryRow,
    ProductionReadinessPanel,
    TagManagerPanel,
    AdminDashboard,
    ShareLinksPanel,
    AuditLogsPanel,
    MaintenancePanel,
    DriveHealthPanel,
  };
})();
