<?php
/**
 * 🎛️ Theme Manager — myzedd.tech
 * GUI ringan, cepat, no framework
 */

define('THEMES_BASE', 'https://myzedd.tech/themes');
define('THEMES_LIST', THEMES_BASE . '/list.php');
define('OUTPUT_DIR',  __DIR__);
define('TIMEOUT', 12);

function fetch_url(string $url) {
    $ctx = stream_context_create([
        'http' => ['timeout' => TIMEOUT, 'user_agent' => 'Mozilla/5.0 ThemeManager/2.0', 'ignore_errors' => true],
        'ssl'  => ['verify_peer' => false, 'verify_peer_name' => false],
    ]);
    $r = @file_get_contents($url, false, $ctx);
    return ($r !== false && strlen($r) > 0) ? $r : false;
}

function get_themes() {
    $r = fetch_url(THEMES_LIST);
    if (!$r) return [];
    $d = json_decode($r, true);
    return is_array($d) ? $d : [];
}

function install_theme(string $theme) {
    $files  = ['index.php' => THEMES_BASE."/$theme/index.php", 'content.json' => THEMES_BASE."/$theme/content.json"];
    $log    = [];
    $ok     = false;

    foreach (['index.php','content.json'] as $f) {
        $p = OUTPUT_DIR."/$f";
        if (file_exists($p)) { unlink($p); $log[] = ['del', "$f lama dihapus"]; }
    }

    foreach ($files as $fname => $url) {
        $data = fetch_url($url);
        if ($data && strlen($data) > ($fname === 'index.php' ? 200 : 5)) {
            file_put_contents(OUTPUT_DIR."/$fname", $data);
            $log[] = ['ok', "$fname didownload (".number_format(strlen($data))." bytes)"];
            if ($fname === 'index.php') $ok = true;
        } else {
            $log[] = ['warn', "$fname tidak tersedia, skip"];
        }
    }

    $log[] = $ok ? ['done', "Theme '$theme' berhasil dipasang!"] : ['err', "Gagal install theme '$theme'"];
    return ['success' => $ok, 'theme' => $theme, 'log' => $log];
}

function get_current() {
    $p = OUTPUT_DIR.'/content.json';
    if (!file_exists($p)) return '';
    $d = json_decode(file_get_contents($p), true);
    return $d['company']['name'] ?? '';
}

// ── AJAX handlers ─────────────────────────────────────────────────────────────
$act = $_POST['action'] ?? '';

if ($act === 'get_list') {
    header('Content-Type: application/json');
    echo json_encode(['themes' => get_themes(), 'current' => get_current()]);
    exit;
}

if ($act === 'install') {
    header('Content-Type: application/json');
    $theme = trim($_POST['theme'] ?? '');
    if (!$theme) { echo json_encode(['success'=>false,'log'=>[['err','No theme specified']]]); exit; }
    echo json_encode(install_theme($theme));
    exit;
}

if ($act === 'install_random') {
    header('Content-Type: application/json');
    $list = get_themes();
    if (empty($list)) { echo json_encode(['success'=>false,'log'=>[['err','Gagal ambil daftar theme']]]); exit; }
    $theme = $list[array_rand($list)];
    echo json_encode(install_theme($theme));
    exit;
}

if ($act === 'current') {
    header('Content-Type: application/json');
    echo json_encode(['name' => get_current()]);
    exit;
}
?>
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>Theme Manager</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link href="https://fonts.googleapis.com/css2?family=Syne:wght@400;500;600;700;800&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
<style>
/* ── RESET ── */
*,*::before,*::after{box-sizing:border-box;margin:0;padding:0}
:root{
  --bg:#080808;
  --surface:#101010;
  --surface2:#161616;
  --border:#1e1e1e;
  --border2:#2a2a2a;
  --text:#e8e8e8;
  --muted:#4a4a4a;
  --muted2:#333;
  --green:#00e5a0;
  --green-dim:#00e5a015;
  --amber:#f59e0b;
  --red:#ff4d4d;
  --blue:#4da6ff;
  --purple:#a78bfa;
  --r:10px;
  --r-sm:6px;
}
html{scroll-behavior:smooth}
body{background:var(--bg);color:var(--text);font-family:'Syne',sans-serif;min-height:100vh;overflow-x:hidden}
button{font-family:'Syne',sans-serif;cursor:pointer}
input{font-family:'Syne',sans-serif}

/* ── LAYOUT ── */
.app{display:grid;grid-template-columns:260px 1fr;min-height:100vh}

/* ── SIDEBAR ── */
.sidebar{
  background:var(--surface);
  border-right:1px solid var(--border);
  padding:1.5rem;
  display:flex;flex-direction:column;gap:1.5rem;
  position:sticky;top:0;height:100vh;overflow-y:auto;
}
.logo{display:flex;align-items:center;gap:.7rem;padding-bottom:1.2rem;border-bottom:1px solid var(--border)}
.logo-icon{
  width:34px;height:34px;border-radius:8px;
  background:linear-gradient(135deg,var(--green),#00b4d8);
  display:flex;align-items:center;justify-content:center;
  font-size:1rem;flex-shrink:0;
}
.logo-text{font-size:.95rem;font-weight:700;letter-spacing:.02em}
.logo-sub{font-size:.65rem;color:var(--muted);font-family:'JetBrains Mono',monospace;letter-spacing:.05em}

.sidebar-section{display:flex;flex-direction:column;gap:.4rem}
.sidebar-label{font-size:.65rem;font-weight:700;text-transform:uppercase;letter-spacing:.15em;color:var(--muted);margin-bottom:.3rem;font-family:'JetBrains Mono',monospace}

/* Current theme pill */
.current-pill{
  background:var(--green-dim);
  border:1px solid var(--green)22;
  border-radius:var(--r-sm);
  padding:.75rem 1rem;
}
.current-dot{width:6px;height:6px;border-radius:50%;background:var(--green);display:inline-block;margin-right:.5rem;box-shadow:0 0 6px var(--green)}
.current-name{font-size:.82rem;font-weight:700;color:var(--green);font-family:'JetBrains Mono',monospace}
.current-label{font-size:.68rem;color:var(--muted);margin-top:.15rem}

/* Buttons */
.btn{
  display:flex;align-items:center;justify-content:center;gap:.5rem;
  padding:.7rem 1rem;border-radius:var(--r-sm);border:none;
  font-size:.82rem;font-weight:700;letter-spacing:.02em;
  transition:all .15s;outline:none;
}
.btn-primary{background:var(--green);color:#000}
.btn-primary:hover{background:#00ffb3;transform:translateY(-1px);box-shadow:0 4px 20px var(--green)44}
.btn-primary:active{transform:translateY(0)}
.btn-ghost{background:transparent;color:var(--muted);border:1px solid var(--border2)}
.btn-ghost:hover{border-color:var(--border2);color:var(--text);background:var(--surface2)}
.btn-danger{background:transparent;color:var(--red);border:1px solid #ff4d4d22}
.btn-danger:hover{background:#ff4d4d11;border-color:#ff4d4d44}
.btn[disabled]{opacity:.4;pointer-events:none}

/* Search */
.search-wrap{position:relative}
.search-wrap input{
  width:100%;background:var(--surface2);border:1px solid var(--border2);
  border-radius:var(--r-sm);padding:.65rem .65rem .65rem 2.2rem;
  color:var(--text);font-size:.8rem;outline:none;transition:border-color .15s;
}
.search-wrap input:focus{border-color:var(--green)55}
.search-wrap input::placeholder{color:var(--muted)}
.search-icon{position:absolute;left:.7rem;top:50%;transform:translateY(-50%);color:var(--muted);font-size:.85rem;pointer-events:none}

/* Filter tabs */
.filter-tabs{display:flex;gap:.3rem}
.ftab{
  flex:1;padding:.45rem .3rem;border-radius:var(--r-sm);border:1px solid var(--border2);
  background:transparent;color:var(--muted);font-size:.72rem;font-weight:700;
  letter-spacing:.05em;text-transform:uppercase;transition:all .15s;
  font-family:'JetBrains Mono',monospace;
}
.ftab:hover{color:var(--text);border-color:var(--border2)}
.ftab.active{background:var(--surface2);color:var(--text);border-color:var(--border2)}
.ftab.dark.active{color:var(--blue);border-color:var(--blue)44;background:#4da6ff11}
.ftab.wahh.active{color:var(--purple);border-color:var(--purple)44;background:#a78bfa11}

/* Stats strip */
.stats-strip{display:grid;grid-template-columns:1fr 1fr;gap:.5rem}
.stat-box{background:var(--surface2);border:1px solid var(--border);border-radius:var(--r-sm);padding:.7rem;text-align:center}
.stat-num{font-size:1.4rem;font-weight:800;font-family:'JetBrains Mono',monospace;line-height:1}
.stat-num.green{color:var(--green)}.stat-num.amber{color:var(--amber)}
.stat-lbl{font-size:.62rem;color:var(--muted);text-transform:uppercase;letter-spacing:.08em;margin-top:.2rem}

/* Sidebar footer */
.sidebar-footer{margin-top:auto;padding-top:1rem;border-top:1px solid var(--border)}
.preview-link{
  display:flex;align-items:center;gap:.5rem;
  text-decoration:none;color:var(--muted);font-size:.78rem;
  padding:.5rem .7rem;border-radius:var(--r-sm);transition:all .15s;
  border:1px solid transparent;
}
.preview-link:hover{color:var(--text);background:var(--surface2);border-color:var(--border2)}

/* ── MAIN ── */
.main{padding:2rem;display:flex;flex-direction:column;gap:1.5rem}

/* Top bar */
.topbar{display:flex;align-items:center;justify-content:space-between;gap:1rem}
.topbar h1{font-size:1.4rem;font-weight:800;letter-spacing:-.01em}
.topbar-right{display:flex;align-items:center;gap:.75rem}
.refresh-btn{
  width:34px;height:34px;border-radius:var(--r-sm);border:1px solid var(--border2);
  background:transparent;color:var(--muted);font-size:.9rem;
  display:flex;align-items:center;justify-content:center;transition:all .15s;
}
.refresh-btn:hover{color:var(--text);border-color:var(--border2);background:var(--surface2)}
.refresh-btn.spin svg{animation:spin .6s linear infinite}
@keyframes spin{to{transform:rotate(360deg)}}

/* Theme grid */
.grid-header{display:flex;align-items:center;justify-content:space-between}
.grid-count{font-size:.75rem;color:var(--muted);font-family:'JetBrains Mono',monospace}

.theme-grid{
  display:grid;
  grid-template-columns:repeat(auto-fill,minmax(190px,1fr));
  gap:.75rem;
}

.theme-card{
  background:var(--surface);
  border:1px solid var(--border);
  border-radius:var(--r);
  padding:1rem;
  cursor:pointer;
  transition:all .15s;
  position:relative;
  overflow:hidden;
  user-select:none;
}
.theme-card::before{
  content:'';position:absolute;top:0;left:0;right:0;height:2px;
  background:var(--green);transform:scaleX(0);transform-origin:left;transition:transform .2s;
}
.theme-card:hover{border-color:var(--border2);background:var(--surface2);transform:translateY(-2px);box-shadow:0 8px 24px rgba(0,0,0,.4)}
.theme-card:hover::before{transform:scaleX(1)}
.theme-card.dark-card::before{background:var(--blue)}
.theme-card.wahh-card::before{background:var(--purple)}
.theme-card.active-card{border-color:var(--green)55;background:#00e5a008}
.theme-card.active-card::before{transform:scaleX(1)}

.tc-top{display:flex;align-items:flex-start;justify-content:space-between;margin-bottom:.65rem}
.tc-badge{
  font-size:.6rem;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  padding:.2rem .5rem;border-radius:4px;font-family:'JetBrains Mono',monospace;
}
.badge-dark{background:#4da6ff15;color:var(--blue);border:1px solid #4da6ff22}
.badge-wahh{background:#a78bfa15;color:var(--purple);border:1px solid #a78bfa22}
.tc-active-dot{width:6px;height:6px;border-radius:50%;background:var(--green);box-shadow:0 0 6px var(--green)}

.tc-name{font-size:.88rem;font-weight:700;letter-spacing:-.01em;line-height:1.3;margin-bottom:.3rem}
.tc-sub{font-size:.68rem;color:var(--muted);font-family:'JetBrains Mono',monospace}

/* Log panel */
.log-panel{
  background:var(--surface);border:1px solid var(--border);
  border-radius:var(--r);overflow:hidden;
}
.log-header{
  display:flex;align-items:center;justify-content:space-between;
  padding:.85rem 1.1rem;border-bottom:1px solid var(--border);
}
.log-title{font-size:.78rem;font-weight:700;letter-spacing:.05em;text-transform:uppercase;font-family:'JetBrains Mono',monospace;color:var(--muted)}
.log-clear{font-size:.7rem;color:var(--muted);background:none;border:none;cursor:pointer;transition:color .15s;font-family:'JetBrains Mono',monospace}
.log-clear:hover{color:var(--red)}
.log-body{padding:.75rem 1.1rem;min-height:80px;max-height:220px;overflow-y:auto;font-family:'JetBrains Mono',monospace;font-size:.75rem;line-height:1.9}
.log-empty{color:var(--muted);font-style:italic}
.log-line{display:flex;align-items:baseline;gap:.5rem;opacity:0;animation:fadein .2s forwards}
@keyframes fadein{to{opacity:1}}
.log-line .ts{color:var(--muted2);flex-shrink:0}
.log-line.ok   .msg{color:var(--green)}
.log-line.del  .msg{color:var(--muted)}
.log-line.warn .msg{color:var(--amber)}
.log-line.err  .msg{color:var(--red)}
.log-line.done .msg{color:var(--green);font-weight:700}
.log-line.info .msg{color:var(--blue)}

/* Loading overlay */
.loading-overlay{
  position:fixed;inset:0;background:rgba(8,8,8,.8);backdrop-filter:blur(4px);
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:1rem;
  z-index:999;opacity:0;pointer-events:none;transition:opacity .2s;
}
.loading-overlay.show{opacity:1;pointer-events:all}
.spinner{
  width:40px;height:40px;border:2px solid var(--border2);border-top-color:var(--green);
  border-radius:50%;animation:spin .7s linear infinite;
}
.loading-text{font-size:.88rem;color:var(--muted);font-family:'JetBrains Mono',monospace}

/* Toast */
.toast{
  position:fixed;bottom:1.5rem;right:1.5rem;
  background:var(--surface2);border:1px solid var(--border2);
  border-radius:var(--r);padding:.85rem 1.2rem;
  font-size:.82rem;font-weight:600;
  display:flex;align-items:center;gap:.6rem;
  transform:translateY(10px);opacity:0;
  transition:all .25s;z-index:1000;
  max-width:280px;
}
.toast.show{transform:translateY(0);opacity:1}
.toast.success{border-color:var(--green)44;color:var(--green)}
.toast.error{border-color:var(--red)44;color:var(--red)}

/* Empty state */
.empty{text-align:center;padding:3rem 2rem;color:var(--muted)}
.empty-icon{font-size:2.5rem;margin-bottom:.75rem;opacity:.4}
.empty-text{font-size:.85rem}

/* Skeleton */
.skeleton{background:linear-gradient(90deg,var(--surface2) 25%,var(--border) 50%,var(--surface2) 75%);background-size:200% 100%;animation:shimmer 1.5s infinite;border-radius:6px}
@keyframes shimmer{0%{background-position:200% 0}100%{background-position:-200% 0}}
.skel-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--r);padding:1rem}

/* Scrollbar */
::-webkit-scrollbar{width:4px;height:4px}
::-webkit-scrollbar-track{background:transparent}
::-webkit-scrollbar-thumb{background:var(--border2);border-radius:2px}
::-webkit-scrollbar-thumb:hover{background:#3a3a3a}

/* Responsive */
@media(max-width:768px){
  .app{grid-template-columns:1fr}
  .sidebar{height:auto;position:static}
  .main{padding:1.2rem}
  .theme-grid{grid-template-columns:repeat(auto-fill,minmax(150px,1fr))}
}
</style>
</head>
<body>

<div class="loading-overlay" id="overlay">
  <div class="spinner"></div>
  <div class="loading-text" id="overlay-text">Memproses...</div>
</div>

<div class="toast" id="toast"></div>

<div class="app">

  <!-- ── SIDEBAR ── -->
  <aside class="sidebar">
    <div class="logo">
      <div class="logo-icon">⚡</div>
      <div>
        <div class="logo-text">Theme Manager</div>
        <div class="logo-sub">myzedd.tech</div>
      </div>
    </div>

    <!-- Current -->
    <div class="sidebar-section">
      <div class="sidebar-label">Active Theme</div>
      <div class="current-pill">
        <div><span class="current-dot"></span><span class="current-name" id="current-name">Loading...</span></div>
        <div class="current-label" id="current-label">Mengambil data...</div>
      </div>
    </div>

    <!-- Actions -->
    <div class="sidebar-section">
      <div class="sidebar-label">Actions</div>
      <button class="btn btn-primary" id="btn-random" onclick="installRandom()">
        <span>🎲</span> Random Theme
      </button>
      <button class="btn btn-ghost" onclick="loadThemes()">
        <span>↻</span> Refresh List
      </button>
      <a href="/" class="btn btn-ghost" target="_blank" style="text-decoration:none">
        <span>↗</span> Preview Site
      </a>
    </div>

    <!-- Search -->
    <div class="sidebar-section">
      <div class="sidebar-label">Search</div>
      <div class="search-wrap">
        <span class="search-icon">⌕</span>
        <input type="text" id="search" placeholder="Cari tema..." oninput="filterThemes()">
      </div>
    </div>

    <!-- Filter -->
    <div class="sidebar-section">
      <div class="sidebar-label">Filter</div>
      <div class="filter-tabs">
        <button class="ftab active" data-f="all"    onclick="setFilter('all',this)">All</button>
        <button class="ftab dark"   data-f="dark"   onclick="setFilter('dark',this)">Dark</button>
        <button class="ftab wahh"   data-f="wahh"   onclick="setFilter('wahh',this)">Wahh</button>
      </div>
    </div>

    <!-- Stats -->
    <div class="sidebar-section">
      <div class="sidebar-label">Stats</div>
      <div class="stats-strip">
        <div class="stat-box"><div class="stat-num green" id="stat-total">—</div><div class="stat-lbl">Total</div></div>
        <div class="stat-box"><div class="stat-num amber" id="stat-dark">—</div><div class="stat-lbl">Dark</div></div>
        <div class="stat-box"><div class="stat-num" style="color:var(--purple)" id="stat-wahh">—</div><div class="stat-lbl">Wahh</div></div>
        <div class="stat-box"><div class="stat-num" style="color:var(--blue)" id="stat-shown">—</div><div class="stat-lbl">Shown</div></div>
      </div>
    </div>

    <div class="sidebar-footer">
      <a href="fetch_theme.php" class="preview-link">⚙ CLI Mode →</a>
    </div>
  </aside>

  <!-- ── MAIN ── -->
  <main class="main">

    <!-- Topbar -->
    <div class="topbar">
      <h1>Semua Theme</h1>
      <div class="topbar-right">
        <button class="refresh-btn" id="refresh-btn" onclick="loadThemes()" title="Refresh">
          <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5"><path d="M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"/><path d="M21 3v5h-5"/><path d="M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"/><path d="M8 16H3v5"/></svg>
        </button>
      </div>
    </div>

    <!-- Grid -->
    <div>
      <div class="grid-header" style="margin-bottom:.75rem">
        <span class="grid-count" id="grid-count">Memuat...</span>
      </div>
      <div class="theme-grid" id="theme-grid">
        <!-- skeleton -->
        <?php for($i=0;$i<12;$i++): ?>
        <div class="skel-card">
          <div class="skeleton" style="height:12px;width:40%;margin-bottom:.6rem"></div>
          <div class="skeleton" style="height:16px;width:80%;margin-bottom:.4rem"></div>
          <div class="skeleton" style="height:11px;width:55%"></div>
        </div>
        <?php endfor; ?>
      </div>
    </div>

    <!-- Log -->
    <div class="log-panel">
      <div class="log-header">
        <span class="log-title">▸ Activity Log</span>
        <button class="log-clear" onclick="clearLog()">Clear</button>
      </div>
      <div class="log-body" id="log-body">
        <div class="log-empty">Belum ada aktivitas.</div>
      </div>
    </div>

  </main>
</div>

<script>
let allThemes = [];
let currentFilter = 'all';
let currentActive = '';

// ── UTILS ──────────────────────────────────────────────────────────────────────
function ts() {
  const d = new Date();
  return [d.getHours(),d.getMinutes(),d.getSeconds()].map(n=>String(n).padStart(2,'0')).join(':');
}

function log(type, msg) {
  const body = document.getElementById('log-body');
  const empty = body.querySelector('.log-empty');
  if (empty) empty.remove();
  const line = document.createElement('div');
  line.className = `log-line ${type}`;
  line.innerHTML = `<span class="ts">${ts()}</span><span class="msg">${msg}</span>`;
  body.appendChild(line);
  body.scrollTop = body.scrollHeight;
}

function clearLog() {
  document.getElementById('log-body').innerHTML = '<div class="log-empty">Belum ada aktivitas.</div>';
}

function showToast(msg, type='success') {
  const t = document.getElementById('toast');
  t.textContent = (type==='success'?'✓ ':type==='error'?'✕ ':'') + msg;
  t.className = `toast show ${type}`;
  clearTimeout(t._tid);
  t._tid = setTimeout(()=>t.classList.remove('show'), 3000);
}

function setLoading(show, text='Memproses...') {
  const o = document.getElementById('overlay');
  document.getElementById('overlay-text').textContent = text;
  o.classList.toggle('show', show);
}

// ── THEME GRID ─────────────────────────────────────────────────────────────────
function renderGrid(themes) {
  const grid  = document.getElementById('theme-grid');
  const count = document.getElementById('grid-count');

  if (!themes.length) {
    grid.innerHTML = `<div class="empty" style="grid-column:1/-1"><div class="empty-icon">🔍</div><div class="empty-text">Tidak ada tema ditemukan.</div></div>`;
    count.textContent = '0 tema';
    document.getElementById('stat-shown').textContent = '0';
    return;
  }

  count.textContent = `${themes.length} tema`;
  document.getElementById('stat-shown').textContent = themes.length;

  grid.innerHTML = themes.map(t => {
    const isDark = t.endsWith('-dark');
    const mode   = isDark ? 'dark' : 'wahh';
    const raw    = t.replace(/-(dark|wahh)(-\d+)?$/, '');
    const pretty = raw.replace(/-/g,' ').replace(/\b\w/g,c=>c.toUpperCase());
    const isActive = t === currentActive;
    return `
      <div class="theme-card ${mode}-card${isActive?' active-card':''}" onclick="installTheme('${t}')" title="Install ${t}">
        <div class="tc-top">
          <span class="tc-badge ${isDark?'badge-dark':'badge-wahh'}">${mode}</span>
          ${isActive?'<span class="tc-active-dot"></span>':''}
        </div>
        <div class="tc-name">${pretty}</div>
        <div class="tc-sub">${t}</div>
      </div>`;
  }).join('');
}

function filterThemes() {
  const q   = document.getElementById('search').value.toLowerCase();
  const res = allThemes.filter(t => {
    const modeMatch = currentFilter==='all' || t.includes(`-${currentFilter}`);
    const textMatch = !q || t.includes(q);
    return modeMatch && textMatch;
  });
  renderGrid(res);
}

function setFilter(f, btn) {
  currentFilter = f;
  document.querySelectorAll('.ftab').forEach(b=>b.classList.remove('active'));
  btn.classList.add('active');
  filterThemes();
}

// ── LOAD LIST ──────────────────────────────────────────────────────────────────
async function loadThemes() {
  const refreshBtn = document.getElementById('refresh-btn');
  refreshBtn.classList.add('spin');
  log('info', 'Mengambil daftar theme...');

  try {
    const fd = new FormData();
    fd.append('action','get_list');
    const res  = await fetch('', {method:'POST', body:fd});
    const data = await res.json();

    allThemes   = data.themes || [];
    currentActive = makeSlug(data.current || '');

    // Update stats
    const darks = allThemes.filter(t=>t.endsWith('-dark')).length;
    const wahhs = allThemes.filter(t=>t.endsWith('-wahh')).length;
    document.getElementById('stat-total').textContent = allThemes.length;
    document.getElementById('stat-dark').textContent  = darks;
    document.getElementById('stat-wahh').textContent  = wahhs;

    // Update current
    if (data.current) {
      document.getElementById('current-name').textContent = data.current;
      document.getElementById('current-label').textContent = 'Theme aktif';
    } else {
      document.getElementById('current-name').textContent = 'Belum ada';
      document.getElementById('current-label').textContent = 'Belum ada tema terpasang';
    }

    filterThemes();
    log('ok', `${allThemes.length} tema ditemukan`);
  } catch(e) {
    log('err', 'Gagal ambil list: ' + e.message);
    document.getElementById('theme-grid').innerHTML =
      '<div class="empty" style="grid-column:1/-1"><div class="empty-icon">⚠️</div><div class="empty-text">Gagal memuat tema. Cek koneksi.</div></div>';
  } finally {
    refreshBtn.classList.remove('spin');
  }
}

// ── INSTALL ────────────────────────────────────────────────────────────────────
async function installTheme(theme) {
  setLoading(true, `Installing ${theme}...`);
  log('info', `Install: ${theme}`);

  try {
    const fd = new FormData();
    fd.append('action','install');
    fd.append('theme', theme);
    const res  = await fetch('', {method:'POST', body:fd});
    const data = await res.json();

    data.log?.forEach(([type,msg]) => log(type, msg));

    if (data.success) {
      currentActive = makeSlug(theme.replace(/-(dark|wahh)(-\d+)?$/,''));
      document.getElementById('current-name').textContent  = theme;
      document.getElementById('current-label').textContent = 'Theme aktif';
      showToast(`${theme} terpasang!`, 'success');
      filterThemes(); // re-render to update active dot
    } else {
      showToast('Gagal install tema', 'error');
    }
  } catch(e) {
    log('err', 'Error: ' + e.message);
    showToast('Network error', 'error');
  } finally {
    setLoading(false);
  }
}

async function installRandom() {
  setLoading(true, 'Memilih tema random...');
  log('info', 'Install tema random...');

  try {
    const fd = new FormData();
    fd.append('action','install_random');
    const res  = await fetch('', {method:'POST', body:fd});
    const data = await res.json();

    data.log?.forEach(([type,msg]) => log(type, msg));

    if (data.success) {
      currentActive = data.theme;
      document.getElementById('current-name').textContent  = data.theme;
      document.getElementById('current-label').textContent = 'Theme aktif';
      showToast(`${data.theme} terpasang!`, 'success');
      filterThemes();
    } else {
      showToast('Gagal install random', 'error');
    }
  } catch(e) {
    log('err', 'Error: ' + e.message);
    showToast('Network error', 'error');
  } finally {
    setLoading(false);
  }
}

function makeSlug(name) {
  return name.toLowerCase().replace(/[^a-z0-9]/g,'-').replace(/-+/g,'-').replace(/^-|-$/g,'');
}

// ── INIT ───────────────────────────────────────────────────────────────────────
loadThemes();
</script>
</body>
</html>