// AURIX Gateway frontend
let currentGuild = null;
let currentUser = null;

const $ = id => document.getElementById(id);
const fmt = n => Number(n).toLocaleString('id-ID');
const fmtIDR = n => `Rp${fmt(n)}`;
const escapeHtml = s => String(s || '').replace(/[&<>"']/g, c => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' }[c]));

const showToast = (msg, type = '') => {
  const t = $('toast');
  t.textContent = msg;
  t.className = 'toast ' + type;
  setTimeout(() => t.classList.add('hidden'), 3000);
};

// ===== Image Upload Helper =====
async function uploadImage(file) {
  return new Promise((resolve, reject) => {
    if (!file) return reject(new Error('No file selected'));
    if (!file.type.match(/^image\/(png|jpeg|jpg|gif|webp)$/)) {
      return reject(new Error('Format tidak didukung. Gunakan: PNG, JPG, GIF, WEBP'));
    }
    if (file.size > 10 * 1024 * 1024) {
      return reject(new Error('File terlalu besar (max 10MB)'));
    }
    const reader = new FileReader();
    reader.onload = async (e) => {
      try {
        showToast('Uploading image...', '');
        const result = await api('/upload-image', {
          method: 'POST',
          body: JSON.stringify({
            guild_id: currentGuild,
            image_data: e.target.result,
            filename: file.name,
          }),
        });
        showToast('Image uploaded', 'success');
        resolve(result.url);
      } catch (err) { reject(err); }
    };
    reader.onerror = () => reject(new Error('Failed to read file'));
    reader.readAsDataURL(file);
  });
}

function createImageUpload(inputId, previewId) {
  const input = $(inputId);
  const preview = $(previewId);
  const fileInput = document.createElement('input');
  fileInput.type = 'file';
  fileInput.accept = 'image/png,image/jpeg,image/jpg,image/gif,image/webp';
  fileInput.style.display = 'none';
  input.parentElement.appendChild(fileInput);
  const uploadBtn = document.createElement('button');
  uploadBtn.type = 'button';
  uploadBtn.className = 'btn';
  uploadBtn.textContent = 'Upload Image';
  uploadBtn.style.marginTop = '8px';
  input.parentElement.appendChild(uploadBtn);
  uploadBtn.addEventListener('click', () => fileInput.click());
  fileInput.addEventListener('change', async () => {
    const file = fileInput.files[0];
    if (!file) return;
    try {
      const url = await uploadImage(file);
      input.value = url;
      if (preview) { preview.src = url; preview.style.display = 'block'; }
    } catch (e) { showToast(e.message, 'error'); }
  });
  if (preview) {
    input.addEventListener('input', () => {
      if (input.value) { preview.src = input.value; preview.style.display = 'block'; }
      else { preview.style.display = 'none'; }
    });
  }
}

async function api(path, opts = {}) {
  const r = await fetch('/api' + path, {
    ...opts,
    credentials: 'include',
    headers: { 'Content-Type': 'application/json', ...(opts.headers || {}) },
  });
  if (r.status === 401) { location.href = '/login'; throw new Error('Sesi habis'); }
  if (!r.ok) {
    const err = await r.json().catch(() => ({ error: r.statusText }));
    throw new Error(err.error || 'API error');
  }
  return r.json();
}

async function authApi(path, opts = {}) {
  const r = await fetch(path, {
    ...opts,
    credentials: 'include',
    headers: { 'Content-Type': 'application/json', ...(opts.headers || {}) },
  });
  if (r.status === 401 && path !== '/auth/me') { location.href = '/login'; throw new Error('Sesi habis'); }
  if (!r.ok) {
    const err = await r.json().catch(() => ({ error: r.statusText }));
    throw new Error(err.error || 'Request gagal');
  }
  return r.json();
}

// ===== Modal =====
function showModal(title, html) {
  $('modal-title').textContent = title;
  $('modal-body').innerHTML = html;
  $('modal').classList.remove('hidden');
}
window.closeModal = () => $('modal').classList.add('hidden');

// ===== Tabs =====
const VALID_TABS = ['dashboard','mybot','payment','announcement','send','panels','server','categories','products','stock','emojis','ticket','orders','settings','users'];

function activateTab(tab) {
  console.log('[activateTab]', tab, 'valid:', VALID_TABS.includes(tab), 'section:', !!$('tab-' + tab));
  if (!VALID_TABS.includes(tab)) tab = 'dashboard';
  if (tab === 'users' && (!currentUser || currentUser.role !== 'admin')) tab = 'dashboard';
  const navBtn = document.querySelector(`.sidebar .nav-item[data-tab="${tab}"]`);
  const section = $('tab-' + tab);
  if (!section) return;

  document.querySelectorAll('.nav-item').forEach(x => x.classList.remove('active'));
  document.querySelectorAll('.bottom-nav button').forEach(x => x.classList.remove('active'));
  document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
  if (navBtn) navBtn.classList.add('active');
  section.classList.add('active');

  const bottomBtn = document.querySelector(`.bottom-nav button[data-tab="${tab}"]`);
  if (bottomBtn) bottomBtn.classList.add('active');

  if (tab === 'dashboard') loadDashboard();
  if (tab === 'mybot') loadMyBot();
  if (tab === 'payment') loadPaymentConfig();
  if (tab === 'panels') loadPanels();
  if (tab === 'server') loadServerTab();
  if (tab === 'categories') loadCategories();
  if (tab === 'products') loadProducts();
  if (tab === 'stock') loadStockTab();
  if (tab === 'orders') loadOrders();
  if (tab === 'emojis') loadEmojis();
  if (tab === 'settings') loadSettings();
  if (tab === 'users') loadUsers();
}

document.querySelectorAll('.nav-item').forEach(b => {
  b.addEventListener('click', () => { location.hash = b.dataset.tab; });
});
document.querySelectorAll('.bottom-nav button').forEach(b => {
  b.addEventListener('click', () => { location.hash = b.dataset.tab; });
});
window.addEventListener('hashchange', () => {
  activateTab(location.hash.replace(/^#/, '') || 'dashboard');
});

window.switchTab = (tab) => { location.hash = tab; };

// ===== Mode Switcher =====
$('mode-discord')?.addEventListener('click', () => {
  $('mode-discord').className = 'mode-btn active-discord';
  $('mode-whatsapp').className = 'mode-btn';
  localStorage.setItem('haikz_mode', 'discord');
});
$('mode-whatsapp')?.addEventListener('click', () => {
  showToast('WhatsApp mode coming soon! Stay tuned.', '');
});

// ===== Guild loader =====
async function loadGuilds() {
  try {
    const guilds = await api('/guilds');
    $('bot-status').textContent = 'Connected';
    if (!guilds.length) {
      $('guild-select').innerHTML = '<option>(belum ada guild)</option>';
      return;
    }
    $('guild-select').innerHTML = guilds
      .map(g => `<option value="${g.guild_id}">${escapeHtml(g.name || g.guild_id)}</option>`)
      .join('');
    const saved = localStorage.getItem('haikz_guild');
    if (saved && guilds.some(g => g.guild_id === saved)) {
      currentGuild = saved;
      $('guild-select').value = saved;
    } else {
      currentGuild = guilds[0].guild_id;
    }
    activateTab(location.hash.replace(/^#/, '') || 'dashboard');
  } catch (e) {
    $('bot-status').textContent = 'Error: ' + e.message;
    showToast(e.message, 'error');
  }
}
$('guild-select').addEventListener('change', e => {
  localStorage.setItem('haikz_guild', e.target.value);
  location.reload();
});

// ===== SVG Chart Renderers =====

function renderLineChart(container, series, opts = {}) {
  if (!series.length) {
    container.innerHTML = '<div style="color:var(--text-mute);text-align:center;padding:40px">Belum ada data di periode ini</div>';
    return;
  }

  const W = 700, H = 260, PAD = { top: 20, right: 20, bottom: 36, left: 56 };
  const chartW = W - PAD.left - PAD.right;
  const chartH = H - PAD.top - PAD.bottom;

  const maxVal = Math.max(...series.map(s => s.revenue), 1);
  const maxOrders = Math.max(...series.map(s => s.orders), 1);

  const xStep = series.length > 1 ? chartW / (series.length - 1) : chartW;
  const x = i => PAD.left + i * xStep;
  const yRev = v => PAD.top + chartH - (v / maxVal) * chartH;
  const yOrd = v => PAD.top + chartH - (v / maxOrders) * chartH;

  const revPoints = series.map((s, i) => `${x(i)},${yRev(s.revenue)}`).join(' ');
  const ordPoints = series.map((s, i) => `${x(i)},${yOrd(s.orders)}`).join(' ');

  const areaPath = `M${x(0)},${yRev(0)} ` +
    series.map((s, i) => `L${x(i)},${yRev(s.revenue)}`).join(' ') +
    ` L${x(series.length - 1)},${PAD.top + chartH} L${x(0)},${PAD.top + chartH} Z`;

  const gridLines = [0, 0.25, 0.5, 0.75, 1].map(pct => {
    const y = PAD.top + chartH * (1 - pct);
    const val = Math.round(maxVal * pct);
    const label = val >= 1000000 ? `${(val / 1000000).toFixed(1)}M` : val >= 1000 ? `${(val / 1000).toFixed(0)}k` : val;
    return `<line x1="${PAD.left}" y1="${y}" x2="${W - PAD.right}" y2="${y}" stroke="var(--border)" stroke-dasharray="4,4" opacity="0.5"/>
      <text x="${PAD.left - 8}" y="${y + 4}" fill="var(--text-mute)" font-size="10" text-anchor="end">${label}</text>`;
  }).join('');

  const xLabels = series.length <= 10 ? series : series.filter((_, i) => i % Math.ceil(series.length / 8) === 0 || i === series.length - 1);
  const xLabelSvg = xLabels.map((s, _, arr) => {
    const i = series.indexOf(s);
    return `<text x="${x(i)}" y="${H - 8}" fill="var(--text-mute)" font-size="10" text-anchor="middle">${s.date.slice(5)}</text>`;
  }).join('');

  const dots = series.map((s, i) =>
    `<circle cx="${x(i)}" cy="${yRev(s.revenue)}" r="3" fill="var(--accent)" stroke="var(--card)" stroke-width="2">
      <title>${s.date}: Rp${fmt(s.revenue)} (${s.orders} order)</title>
    </circle>`
  ).join('');

  container.innerHTML = `
    <div class="chart-summary">
      <span style="color:var(--text-dim)">Total Revenue: <b style="color:var(--green)">Rp${fmt(series.reduce((a, s) => a + s.revenue, 0))}</b></span>
      <span style="color:var(--text-dim)">Total Orders: <b>${series.reduce((a, s) => a + s.orders, 0)}</b></span>
    </div>
    <svg viewBox="0 0 ${W} ${H}" style="width:100%;height:auto">
      <defs>
        <linearGradient id="areaGrad" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stop-color="var(--accent)" stop-opacity="0.2"/>
          <stop offset="100%" stop-color="var(--accent)" stop-opacity="0"/>
        </linearGradient>
      </defs>
      ${gridLines}
      ${xLabelSvg}
      <path d="${areaPath}" fill="url(#areaGrad)"/>
      <polyline points="${revPoints}" fill="none" stroke="var(--accent)" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/>
      <polyline points="${ordPoints}" fill="none" stroke="var(--green)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" stroke-dasharray="6,3" opacity="0.6"/>
      ${dots}
    </svg>`;
}

function renderPieChart(container, data, opts = {}) {
  if (!data.length) {
    container.innerHTML = '<div style="color:var(--text-mute);text-align:center;padding:30px">Belum ada data</div>';
    return;
  }

  const colors = ['#6B5CE7', '#2ECC71', '#F39C12', '#3B82F6', '#EF4444', '#E91E8C', '#00BCD4', '#FF9800'];
  const total = data.reduce((a, d) => a + d.value, 0);
  const size = 140, cx = size / 2, cy = size / 2, r = 55, innerR = 35;

  let startAngle = -Math.PI / 2;
  const slices = data.slice(0, 8).map((d, i) => {
    const angle = (d.value / total) * Math.PI * 2;
    const endAngle = startAngle + angle;
    const largeArc = angle > Math.PI ? 1 : 0;

    const x1 = cx + r * Math.cos(startAngle);
    const y1 = cy + r * Math.sin(startAngle);
    const x2 = cx + r * Math.cos(endAngle);
    const y2 = cy + r * Math.sin(endAngle);
    const ix1 = cx + innerR * Math.cos(startAngle);
    const iy1 = cy + innerR * Math.sin(startAngle);
    const ix2 = cx + innerR * Math.cos(endAngle);
    const iy2 = cy + innerR * Math.sin(endAngle);

    const path = `M${ix1},${iy1} L${x1},${y1} A${r},${r} 0 ${largeArc} 1 ${x2},${y2} L${ix2},${iy2} A${innerR},${innerR} 0 ${largeArc} 0 ${ix1},${iy1}`;
    startAngle = endAngle;

    return `<path d="${path}" fill="${colors[i % colors.length]}" opacity="0.85"><title>${escapeHtml(d.label)}: ${d.value} (${((d.value / total) * 100).toFixed(1)}%)</title></path>`;
  }).join('');

  const legend = data.slice(0, 8).map((d, i) =>
    `<li><span class="dot" style="background:${colors[i % colors.length]}"></span>${escapeHtml(d.label)}<span class="val">${((d.value / total) * 100).toFixed(0)}%</span></li>`
  ).join('');

  container.innerHTML = `
    <div class="pie-chart-wrap">
      <svg viewBox="0 0 ${size} ${size}" width="${size}" height="${size}">
        ${slices}
        <text x="${cx}" y="${cy - 4}" text-anchor="middle" fill="var(--text)" font-size="14" font-weight="800">${total}</text>
        <text x="${cx}" y="${cy + 10}" text-anchor="middle" fill="var(--text-mute)" font-size="8">TOTAL</text>
      </svg>
      <ul class="pie-legend">${legend}</ul>
    </div>`;
}

// ===== Dashboard =====
async function loadDashboard() {
  if (!currentGuild) return;
  try {
    const stats = await api('/stats?guild_id=' + currentGuild);
    $('stat-revenue').textContent = fmtIDR(stats.revenue);
    $('stat-delivered').textContent = stats.orders_delivered;
    $('stat-pending').textContent = stats.orders_pending;
    $('stat-tickets').textContent = stats.tickets_open;
    $('stat-products').textContent = stats.products_active;

    loadRevenueChart();

    const orders = await api('/orders?guild_id=' + currentGuild);

    // Recent Activity
    const actEl = $('recent-activity');
    if (!orders.length) {
      actEl.innerHTML = '<li style="color:var(--text-mute);text-align:center;padding:30px">Belum ada activity</li>';
    } else {
      actEl.innerHTML = orders.slice(0, 6).map(o => {
        const statusClass = o.status === 'delivered' ? 'success' : o.status === 'pending' ? 'pending' : 'error';
        const icon = o.status === 'delivered'
          ? '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg>'
          : o.status === 'pending'
          ? '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>'
          : '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><line x1="15" y1="9" x2="9" y2="15"/><line x1="9" y1="9" x2="15" y2="15"/></svg>';
        return `
          <li class="activity-item">
            <div class="activity-dot ${statusClass}">${icon}</div>
            <div class="activity-info">
              <div class="activity-title">${escapeHtml(o.product_name || 'Order')} — ${fmtIDR(o.total)}</div>
              <div class="activity-sub">${o.invoice_id} · ${new Date(o.created_at * 1000).toLocaleString('id-ID')}</div>
            </div>
            <span class="activity-badge ${statusClass}">${o.status}</span>
          </li>`;
      }).join('');
    }

    // Top Products (pie chart)
    const productCounts = {};
    orders.filter(o => o.status === 'delivered').forEach(o => {
      const name = o.product_name || 'Unknown';
      productCounts[name] = (productCounts[name] || 0) + 1;
    });
    const pieData = Object.entries(productCounts)
      .map(([label, value]) => ({ label, value }))
      .sort((a, b) => b.value - a.value)
      .slice(0, 6);
    renderPieChart($('top-products'), pieData);

    // Recent Orders table
    if (!orders.length) {
      $('recent-orders').innerHTML = '<table><tbody><tr><td class="empty">Belum ada order</td></tr></tbody></table>';
      return;
    }
    $('recent-orders').innerHTML = `
      <table>
        <thead><tr><th>Invoice</th><th>Produk</th><th>Total</th><th>Status</th><th>Time</th></tr></thead>
        <tbody>${orders.slice(0, 10).map(o => `
          <tr>
            <td><code>${o.invoice_id}</code></td>
            <td>${escapeHtml(o.product_name || '-')}</td>
            <td>${fmtIDR(o.total)}</td>
            <td><span class="badge ${o.status === 'delivered' ? 'green' : o.status === 'pending' ? 'warn' : 'red'}">${o.status}</span></td>
            <td>${new Date(o.created_at * 1000).toLocaleString('id-ID')}</td>
          </tr>
        `).join('')}</tbody>
      </table>`;
  } catch (e) { showToast(e.message, 'error'); }
}

// ===== Revenue Chart =====
async function loadRevenueChart() {
  if (!currentGuild) return;
  const box = $('revenue-chart');
  const activeBtn = document.querySelector('#rev-range .period-pills button.active, #rev-range button.active');
  const days = parseInt(activeBtn?.dataset.days, 10) || 30;
  try {
    const data = await api(`/revenue-series?guild_id=${currentGuild}&days=${days}`);
    const series = data.series || [];
    renderLineChart(box, series);
  } catch (e) {
    box.innerHTML = `<div style="color:var(--red);padding:20px">${escapeHtml(e.message)}</div>`;
  }
}
document.querySelectorAll('#rev-range button').forEach(btn => {
  btn.addEventListener('click', () => {
    document.querySelectorAll('#rev-range button').forEach(b => b.classList.remove('active'));
    btn.classList.add('active');
    loadRevenueChart();
  });
});

// ===== Server Tab =====
function toBold(t) {
  return t.replace(/[A-Z]/g, c => String.fromCodePoint(0x1D5D4 + c.charCodeAt(0) - 65))
          .replace(/[a-z]/g, c => String.fromCodePoint(0x1D5EE + c.charCodeAt(0) - 97))
          .replace(/[0-9]/g, c => String.fromCodePoint(0x1D7EC + c.charCodeAt(0) - 48));
}
function dotName(name) { return name.replace(/[-\s]+/g, '\u30FB'); }
function buildChName(emoji, name, prefix = '\u256D') {
  return `${prefix}\u30FB${emoji}\u200B\u2503\u200B${toBold(dotName(name))}`;
}
function chName(emoji, name, prefix) { return buildChName(emoji, name, prefix); }
function processTemplate(template) {
  return template.map(section => ({
    ...section,
    channels: (section.channels || []).map((ch, i, arr) => {
      const len = arr.length;
      const prefix = len === 1 ? '\u256D' : i === 0 ? '\u256D' : i === len - 1 ? '\u2570' : '\u251C';
      return { ...ch, name: buildChName(ch.emoji, ch.rawName, prefix) };
    })
  }));
}

const STORE_TEMPLATE = [
  { cat: '━━━ 📢 𝗜𝗡𝗙𝗢𝗥𝗠𝗔𝗧𝗜𝗢𝗡 ━━━', private: false, channels: [
    { emoji: '📜', rawName: 'rules', type: 0, overwrites: { readOnly: true } },
    { emoji: '📢', rawName: 'announcements', type: 0, overwrites: { readOnly: true } },
    { emoji: '👋', rawName: 'welcome bye', type: 0, overwrites: { readOnly: true } },
    { emoji: '🎉', rawName: 'giveaway', type: 0 },
    { emoji: '🚀', rawName: 'booster', type: 0, overwrites: { readOnly: true } },
    { emoji: '📊', rawName: 'server stats', type: 0, overwrites: { readOnly: true } },
  ]},
  { cat: '━━━ 🛒 𝗦𝗧𝗢𝗥𝗘 ━━━', private: false, channels: [
    { emoji: '🛒', rawName: 'order', type: 0, topic: 'Place your orders here' },
    { emoji: '🔔', rawName: 'promo', type: 0, overwrites: { readOnly: true } },
    { emoji: '🔥', rawName: 'flashsale', type: 0, overwrites: { readOnly: true } },
    { emoji: '💳', rawName: 'payment info', type: 0, overwrites: { readOnly: true } },
    { emoji: '✅', rawName: 'testimonials', type: 0 },
    { emoji: '🎁', rawName: 'claim garansi', type: 0 },
    { emoji: '📋', rawName: 'product list', type: 0, overwrites: { readOnly: true } },
    { emoji: '⭐', rawName: 'rating', type: 0 },
    { emoji: '📦', rawName: 'stock update', type: 0, overwrites: { readOnly: true } },
    { emoji: '💬', rawName: 'tanya jawab', type: 0 },
  ]},
  { cat: '━━━ 📦 𝗣𝗥𝗢𝗗𝗨𝗖𝗧 ━━━', private: false, channels: [
    { emoji: '📦', rawName: 'alight motion', type: 0 },
    { emoji: '📦', rawName: 'canva pro', type: 0 },
    { emoji: '📦', rawName: 'spotify', type: 0 },
    { emoji: '📦', rawName: 'netflix', type: 0 },
    { emoji: '📦', rawName: 'youtube premium', type: 0 },
    { emoji: '📦', rawName: 'discord nitro', type: 0 },
    { emoji: '📦', rawName: 'chatgpt plus', type: 0 },
    { emoji: '📦', rawName: 'capcut pro', type: 0 },
    { emoji: '📦', rawName: 'grammarly', type: 0 },
    { emoji: '📦', rawName: 'vidio premium', type: 0 },
    { emoji: '📦', rawName: 'wink premium', type: 0 },
    { emoji: '📦', rawName: 'bruno', type: 0 },
    { emoji: '🔐', rawName: 'vpn', type: 0 },
    { emoji: '✨', rawName: 'gemini', type: 0 },
    { emoji: '☁️', rawName: 'kiro aws', type: 0 },
    { emoji: '🌊', rawName: 'digital ocean', type: 0 },
    { emoji: '☁️', rawName: 'azure cloud', type: 0 },
  ]},
  { cat: '━━━ 💬 𝗟𝗢𝗕𝗕𝗬 ━━━', private: false, channels: [
    { emoji: '💬', rawName: 'general chat', type: 0 },
    { emoji: '🤖', rawName: 'bot commands', type: 0 },
    { emoji: '🖼️', rawName: 'media share', type: 0 },
    { emoji: '🎵', rawName: 'music', type: 2 },
  ]},
  { cat: '━━━ ❓ 𝗦𝗨𝗣𝗣𝗢𝗥𝗧 ━━━', private: false, channels: [
    { emoji: '❓', rawName: 'help', type: 0 },
    { emoji: '✍️', rawName: 'feedback', type: 0 },
    { emoji: '🐛', rawName: 'bug report', type: 0 },
  ]},
  { cat: '━━━ 🎫 𝗧𝗜𝗖𝗞𝗘𝗧 𝗢𝗥𝗗𝗘𝗥 ━━━', private: true, channels: [
    { emoji: '🎫', rawName: 'open ticket', type: 0, topic: 'Klik tombol untuk buka tiket order' },
  ]},
  { cat: '━━━ 🛡️ 𝗧𝗜𝗖𝗞𝗘𝗧 𝗚𝗔𝗥𝗔𝗡𝗦𝗜 ━━━', private: true, channels: [
    { emoji: '🛡️', rawName: 'claim garansi', type: 0, topic: 'Klaim garansi produk di sini' },
  ]},
  { cat: '━━━ ⚔️ 𝗦𝗧𝗔𝗙 ━━━', staffOnly: true, channels: [
    { emoji: '📋', rawName: 'moderator chat', type: 0 },
    { emoji: '🤖', rawName: 'command bot', type: 0 },
    { emoji: '📝', rawName: 'log tiket', type: 0 },
    { emoji: '📊', rawName: 'log penjualan', type: 0 },
    { emoji: '🎙️', rawName: 'meeting', type: 2 },
  ]},
];

async function loadServerTab() {
  if (!currentGuild) return;
  try {
    const channels = await api(`/channels?guild_id=${currentGuild}`);
    const cats = channels.filter(c => c.type === 4);
    const sel = $('srv-ch-category');
    sel.innerHTML = '<option value="">— Tanpa kategori —</option>' +
      cats.map(c => `<option value="${c.id}">${escapeHtml(c.name)}</option>`).join('');
  } catch (e) {}
}

function updateChPreview() {
  const emoji = ($('srv-ch-emoji')?.value || '').trim();
  const name = ($('srv-ch-name')?.value || '').trim();
  const preview = $('srv-ch-preview');
  if (preview) preview.textContent = emoji ? buildChName(emoji, name) : name || '';
}
$('srv-ch-emoji')?.addEventListener('input', updateChPreview);
$('srv-ch-name')?.addEventListener('input', updateChPreview);

$('btn-srv-create-cat')?.addEventListener('click', async () => {
  const name = $('srv-cat-name').value.trim();
  if (!name) return showToast('Nama kategori wajib diisi', 'error');
  const isPrivate = $('srv-cat-private').checked;
  const res = $('srv-cat-result');
  res.textContent = 'Membuat...';
  try {
    const r = await api('/server/create-category', {
      method: 'POST',
      body: JSON.stringify({ guild_id: currentGuild, name, private: isPrivate }),
    });
    res.textContent = `Kategori "${r.name}" dibuat (ID: ${r.id})`;
    $('srv-cat-name').value = '';
    loadServerTab();
  } catch (e) { res.textContent = e.message; res.style.color = 'var(--red)'; }
});

$('btn-srv-create-ch')?.addEventListener('click', async () => {
  const emoji = ($('srv-ch-emoji').value || '').trim();
  const name = ($('srv-ch-name').value || '').trim();
  if (!name) return showToast('Nama channel wajib diisi', 'error');
  const fullName = emoji ? buildChName(emoji, name) : name;
  const type = parseInt($('srv-ch-type').value, 10);
  const categoryId = $('srv-ch-category').value || null;
  const topic = $('srv-ch-topic').value.trim() || null;
  const res = $('srv-ch-result');
  res.textContent = 'Membuat...';
  try {
    const r = await api('/server/create-channel', {
      method: 'POST',
      body: JSON.stringify({ guild_id: currentGuild, name: fullName, type, category_id: categoryId, topic }),
    });
    res.textContent = `Channel "${r.name}" dibuat`;
    $('srv-ch-name').value = '';
    $('srv-ch-emoji').value = '';
    updateChPreview();
  } catch (e) { res.textContent = e.message; res.style.color = 'var(--red)'; }
});

$('btn-srv-deploy-template')?.addEventListener('click', async () => {
  if (!confirm('Deploy template store? Ini akan membuat roles + kategori + channel baru (tidak menghapus yang sudah ada).')) return;
  const res = $('srv-template-result');
  res.style.color = 'var(--text-dim)';
  res.textContent = 'Deploying roles + channels...';
  try {
    const r = await api('/server/deploy-template', {
      method: 'POST',
      body: JSON.stringify({ guild_id: currentGuild, template: processTemplate(STORE_TEMPLATE) }),
    });
    res.style.color = 'var(--green)';
    const roleMsg = r.roles_created?.length ? `, ${r.roles_created.length} roles dibuat` : '';
    res.textContent = `Selesai: ${r.categories} kategori, ${r.channels} channel${roleMsg}${r.errors?.length ? ` (${r.errors.length} error)` : ''}`;
  } catch (e) { res.style.color = 'var(--red)'; res.textContent = e.message; }
});

$('btn-srv-wipe-deploy')?.addEventListener('click', async () => {
  if (!confirm('PERINGATAN: Ini akan MENGHAPUS SEMUA channel dan kategori, lalu deploy ulang. Lanjutkan?')) return;
  if (!confirm('Yakin? Semua channel akan hilang dan tidak bisa dikembalikan!')) return;
  const res = $('srv-template-result');
  res.style.color = 'var(--orange)';
  res.textContent = 'Menghapus semua channel...';
  try {
    const del = await api('/server/delete-all-channels', {
      method: 'POST',
      body: JSON.stringify({ guild_id: currentGuild }),
    });
    res.textContent = `${del.deleted} channel dihapus. Deploying template...`;
    const r = await api('/server/deploy-template', {
      method: 'POST',
      body: JSON.stringify({ guild_id: currentGuild, template: processTemplate(STORE_TEMPLATE) }),
    });
    res.style.color = 'var(--green)';
    const roleMsg = r.roles_created?.length ? `, ${r.roles_created.length} roles baru` : '';
    res.textContent = `Wipe + Deploy selesai: ${del.deleted} dihapus, ${r.categories} kategori + ${r.channels} channel${roleMsg}`;
  } catch (e) { res.style.color = 'var(--red)'; res.textContent = e.message; }
});

$('btn-srv-create-roles')?.addEventListener('click', async () => {
  if (!confirm('Buat roles: Owner, Admin, Staff, Seller, VIP, Buyer?')) return;
  const res = $('srv-roles-result');
  res.style.color = 'var(--text-dim)';
  res.textContent = 'Membuat roles...';
  try {
    const r = await api('/server/create-roles', {
      method: 'POST',
      body: JSON.stringify({ guild_id: currentGuild }),
    });
    res.style.color = 'var(--green)';
    res.textContent = `${r.created.length} roles dibuat${r.skipped.length ? `, ${r.skipped.length} sudah ada` : ''}`;
  } catch (e) { res.style.color = 'var(--red)'; res.textContent = e.message; }
});

// ===== Panels =====
async function loadPanels() {
  if (!currentGuild) return;
  const panels = await api('/panels?guild_id=' + currentGuild);
  if (!panels.length) {
    $('panels-list').innerHTML = '<div class="card"><div class="card-body" style="color:var(--text-mute);text-align:center;">Belum ada panel. Klik "+ New Panel".</div></div>';
    return;
  }
  $('panels-list').innerHTML = panels.map(p => `
    <div class="item-card" data-id="${p.id}">
      ${p.image_url ? `<div class="preview-img" style="background-image:url('${escapeHtml(p.image_url)}')"></div>` : ''}
      <div class="title">${escapeHtml(p.title)}</div>
      <div class="meta">
        <span class="badge">${p.category_count} kategori</span>
        <span class="badge ${p.enabled ? 'green' : 'red'}">${p.enabled ? 'Active' : 'Disabled'}</span>
      </div>
      <div class="meta" style="margin-top:6px;">${escapeHtml(p.footer_note || '').slice(0, 80)}</div>
      <div class="actions">
        <button class="btn small" onclick="editPanel(${p.id})">Edit</button>
        <button class="btn small primary" onclick="sendPanel(${p.id})">Send to Discord</button>
        <button class="btn small danger" onclick="deletePanel(${p.id})">Delete</button>
      </div>
    </div>
  `).join('');
}

function panelForm(panel = {}) {
  return `
    <form onsubmit="event.preventDefault(); savePanel(${panel.id || 'null'})">
      <div class="form-row">
        <label>Title</label>
        <input id="f-title" value="${escapeHtml(panel.title || '')}" required />
      </div>
      <div class="form-row">
        <label>Image URL</label>
        <input id="f-panel-image" value="${escapeHtml(panel.image_url || '')}" placeholder="https://..." />
        <img id="f-panel-image-preview" src="${panel.image_url || ''}" style="${panel.image_url ? '' : 'display:none;'}max-width:100%;margin-top:12px;border-radius:var(--radius-sm);border:1px solid var(--border)" />
      </div>
      <div class="form-row">
        <label>Footer Note</label>
        <textarea id="f-footer">${escapeHtml(panel.footer_note || '')}</textarea>
      </div>
      <div class="form-grid-2">
        <div class="form-row">
          <label>Dropdown Placeholder</label>
          <input id="f-placeholder" value="${escapeHtml(panel.placeholder || 'Pilih Di Sini')}" />
        </div>
        <div class="form-row">
          <label>Copyright</label>
          <input id="f-copyright" value="${escapeHtml(panel.copyright || '')}" />
        </div>
      </div>
      <div class="form-actions">
        <button type="button" class="btn" onclick="closeModal()">Cancel</button>
        <button type="submit" class="btn primary">Save</button>
      </div>
    </form>`;
}

window.editPanel = async (id) => {
  const panels = await api('/panels?guild_id=' + currentGuild);
  const p = panels.find(x => x.id === id);
  showModal('Edit Panel #' + id, panelForm(p));
  setTimeout(() => createImageUpload('f-panel-image', 'f-panel-image-preview'), 100);
};
window.savePanel = async (id) => {
  const body = {
    guild_id: currentGuild,
    title: $('f-title').value,
    image_url: $('f-panel-image').value,
    footer_note: $('f-footer').value,
    placeholder: $('f-placeholder').value,
    copyright: $('f-copyright').value,
  };
  try {
    if (id) await api('/panels/' + id, { method: 'PUT', body: JSON.stringify(body) });
    else await api('/panels', { method: 'POST', body: JSON.stringify(body) });
    closeModal(); showToast('Panel saved', 'success'); loadPanels();
  } catch (e) { showToast(e.message, 'error'); }
};
window.deletePanel = async (id) => {
  if (!confirm('Hapus panel ini?')) return;
  await api('/panels/' + id, { method: 'DELETE' });
  showToast('Deleted', 'success'); loadPanels();
};
window.sendPanel = async (id) => {
  pickChannel('Pilih Channel untuk Panel', async (channelId) => {
    try {
      await api(`/panels/${id}/send`, { method: 'POST', body: JSON.stringify({ channel_id: channelId }) });
      showToast('Panel terkirim!', 'success'); closeModal();
    } catch (e) { showToast(e.message, 'error'); }
  });
};
$('btn-new-panel').addEventListener('click', () => {
  showModal('New Panel', panelForm());
  setTimeout(() => createImageUpload('f-panel-image', 'f-panel-image-preview'), 100);
});

// ===== Categories =====
async function loadCategories() {
  if (!currentGuild) return;
  const [cats, panels] = await Promise.all([
    api('/categories?guild_id=' + currentGuild),
    api('/panels?guild_id=' + currentGuild),
  ]);
  if (!cats.length) {
    $('categories-list').innerHTML = '<div class="card"><div class="card-body" style="color:var(--text-mute);text-align:center;">Belum ada kategori.</div></div>';
    return;
  }
  $('categories-list').innerHTML = cats.map(c => {
    const panel = panels.find(p => p.id === c.panel_id);
    return `
      <div class="item-card">
        <div class="title">${c.emoji ? c.emoji + ' ' : ''}${escapeHtml(c.name)}</div>
        <div class="meta" style="margin-top:6px;">${escapeHtml(c.description || '')}</div>
        <div class="meta" style="margin-top:6px;">
          <span class="badge">${c.product_count} produk</span>
          <span class="badge ${c.enabled ? 'green' : 'red'}">${c.enabled ? 'Active' : 'Disabled'}</span>
          ${panel ? `<span class="badge">${escapeHtml(panel.title.slice(0, 18))}</span>` : '<span class="badge warn">No panel</span>'}
        </div>
        ${c.note ? `<div class="meta" style="margin-top:8px;padding:8px;background:var(--bg);border-radius:var(--radius-sm);border-left:2px solid var(--accent);">${escapeHtml(c.note.slice(0, 100))}</div>` : ''}
        <div class="actions">
          <button class="btn small" onclick="editCategory(${c.id})">Edit</button>
          <button class="btn small danger" onclick="deleteCategory(${c.id})">Delete</button>
        </div>
      </div>`;
  }).join('');
}

async function categoryForm(cat = {}) {
  const panels = await api('/panels?guild_id=' + currentGuild);
  return `
    <form onsubmit="event.preventDefault(); saveCategory(${cat.id || 'null'})">
      <div class="form-grid-2">
        <div class="form-row"><label>Name</label><input id="f-name" value="${escapeHtml(cat.name || '')}" required /></div>
        <div class="form-row"><label>Emoji</label><input id="f-emoji" value="${escapeHtml(cat.emoji || '')}" /></div>
      </div>
      <div class="form-row">
        <label>Panel</label>
        <select id="f-panel">
          <option value="">— No panel —</option>
          ${panels.map(p => `<option value="${p.id}" ${cat.panel_id === p.id ? 'selected' : ''}>${escapeHtml(p.title)}</option>`).join('')}
        </select>
      </div>
      <div class="form-row"><label>Description</label><input id="f-description" value="${escapeHtml(cat.description || '')}" /></div>
      <div class="form-row"><label>Note</label><textarea id="f-note">${escapeHtml(cat.note || '')}</textarea></div>
      <div class="form-row"><label>Sort Order</label><input id="f-sort" type="number" value="${cat.sort_order || 0}" /></div>
      <div class="form-actions">
        <button type="button" class="btn" onclick="closeModal()">Cancel</button>
        <button type="submit" class="btn primary">Save</button>
      </div>
    </form>`;
}

window.editCategory = async (id) => {
  const cats = await api('/categories?guild_id=' + currentGuild);
  const c = cats.find(x => x.id === id);
  showModal('Edit Category', await categoryForm(c));
};
window.saveCategory = async (id) => {
  const body = {
    guild_id: currentGuild, panel_id: $('f-panel').value || null,
    name: $('f-name').value, emoji: $('f-emoji').value,
    description: $('f-description').value, note: $('f-note').value,
    sort_order: parseInt($('f-sort').value) || 0,
  };
  try {
    if (id) await api('/categories/' + id, { method: 'PUT', body: JSON.stringify(body) });
    else await api('/categories', { method: 'POST', body: JSON.stringify(body) });
    closeModal(); showToast('Category saved', 'success'); loadCategories();
  } catch (e) { showToast(e.message, 'error'); }
};
window.deleteCategory = async (id) => {
  if (!confirm('Hapus kategori ini?')) return;
  await api('/categories/' + id, { method: 'DELETE' });
  showToast('Deleted', 'success'); loadCategories();
};
$('btn-new-category').addEventListener('click', async () => showModal('New Category', await categoryForm()));

// ===== Products =====
async function loadProducts() {
  if (!currentGuild) return;
  const products = await api('/products?guild_id=' + currentGuild);
  if (!products.length) {
    $('products-list').innerHTML = '<div class="card"><div class="card-body" style="color:var(--text-mute);text-align:center;">Belum ada produk.</div></div>';
    return;
  }
  $('products-list').innerHTML = products.map(p => {
    const priceText = p.price_max ? `${fmtIDR(p.price)} - ${fmtIDR(p.price_max)}` : fmtIDR(p.price);
    const skuBadge = p.sku ? `<span class="badge" style="background:var(--blue-dim);color:var(--blue)">${escapeHtml(p.sku)}</span>` : '';
    return `
      <div class="item-card">
        ${p.image_url ? `<div class="preview-img" style="background-image:url('${escapeHtml(p.image_url)}')"></div>` : ''}
        <div class="title">${escapeHtml(p.name)}</div>
        <div class="meta" style="font-weight:700;color:var(--accent);margin-top:4px;">${priceText}</div>
        <div class="meta" style="margin-top:6px;">
          ${skuBadge}
          ${p.category_name ? `<span class="badge">${p.category_emoji || ''} ${escapeHtml(p.category_name)}</span>` : '<span class="badge warn">No category</span>'}
          <span class="badge ${p.stock_available > 0 ? 'green' : 'red'}">${p.stock_available} avail</span>
          <span class="badge">Sold ${p.stock_sold}</span>
        </div>
        <div class="actions">
          <button class="btn small" onclick="editProduct(${p.id})">Edit</button>
          <button class="btn small danger" onclick="deleteProduct(${p.id})">Delete</button>
        </div>
      </div>`;
  }).join('');
}

async function productForm(product = {}) {
  const cats = await api('/categories?guild_id=' + currentGuild);
  const randomSuffix = Math.random().toString(36).substring(2, 6).toLowerCase();
  return `
    <form onsubmit="event.preventDefault(); saveProduct(${product.id || 'null'})">
      <div class="form-row">
        <label>SKU/Code</label>
        <div style="display:flex;gap:8px">
          <input id="f-sku" value="${escapeHtml(product.sku || '')}" placeholder="d3_${randomSuffix}" />
          <button type="button" class="btn" onclick="document.getElementById('f-sku').value = (document.getElementById('f-sku').value.split('_')[0]||'product')+'_'+Math.random().toString(36).substring(2,6)">Random</button>
        </div>
      </div>
      <div class="form-row"><label>Name</label><input id="f-name" value="${escapeHtml(product.name || '')}" required /></div>
      <div class="form-row"><label>Description</label><textarea id="f-description">${escapeHtml(product.description || '')}</textarea></div>
      <div class="form-grid-2">
        <div class="form-row"><label>Price (IDR)</label><input id="f-price" type="number" value="${product.price || 25000}" min="1000" required /></div>
        <div class="form-row"><label>Price Max (optional)</label><input id="f-price-max" type="number" value="${product.price_max || ''}" /></div>
      </div>
      <div class="form-row">
        <label>Category</label>
        <select id="f-category">
          <option value="">— No category —</option>
          ${cats.map(c => `<option value="${c.id}" ${product.category_id === c.id ? 'selected' : ''}>${c.emoji || ''} ${escapeHtml(c.name)}</option>`).join('')}
        </select>
      </div>
      <div class="form-row">
        <label>Image URL</label>
        <input id="f-image" value="${escapeHtml(product.image_url || '')}" placeholder="https://..." />
        <img id="f-image-preview" src="${product.image_url || ''}" style="${product.image_url ? '' : 'display:none;'}max-width:100%;margin-top:12px;border-radius:var(--radius-sm);border:1px solid var(--border)" />
      </div>
      <div class="form-grid-2">
        <div class="form-row">
          <label>Auto-delivery?</label>
          <select id="f-auto">
            <option value="1" ${product.auto_delivery !== 0 ? 'selected' : ''}>Yes</option>
            <option value="0" ${product.auto_delivery === 0 ? 'selected' : ''}>No (manual)</option>
          </select>
        </div>
        <div class="form-row"><label>Sort Order</label><input id="f-sort" type="number" value="${product.sort_order || 0}" /></div>
      </div>
      <div class="form-actions">
        <button type="button" class="btn" onclick="closeModal()">Cancel</button>
        <button type="submit" class="btn primary">Save</button>
      </div>
    </form>`;
}

window.editProduct = async (id) => {
  const products = await api('/products?guild_id=' + currentGuild);
  const p = products.find(x => x.id === id);
  showModal('Edit Product', await productForm(p));
  setTimeout(() => createImageUpload('f-image', 'f-image-preview'), 100);
};
window.saveProduct = async (id) => {
  const body = {
    guild_id: currentGuild, sku: $('f-sku').value.trim() || null,
    category_id: $('f-category').value || null, name: $('f-name').value,
    description: $('f-description').value, price: parseInt($('f-price').value),
    price_max: parseInt($('f-price-max').value) || null, image_url: $('f-image').value,
    auto_delivery: parseInt($('f-auto').value), sort_order: parseInt($('f-sort').value) || 0,
  };
  try {
    if (id) await api('/products/' + id, { method: 'PUT', body: JSON.stringify(body) });
    else await api('/products', { method: 'POST', body: JSON.stringify(body) });
    closeModal(); showToast('Product saved', 'success'); loadProducts();
  } catch (e) { showToast(e.message, 'error'); }
};
window.deleteProduct = async (id) => {
  if (!confirm('Hapus produk ini?')) return;
  await api('/products/' + id, { method: 'DELETE' });
  showToast('Deleted', 'success'); loadProducts();
};
$('btn-new-product').addEventListener('click', async () => {
  showModal('New Product', await productForm());
  setTimeout(() => createImageUpload('f-image', 'f-image-preview'), 100);
});

// ===== Stock =====
async function loadStockTab() {
  if (!currentGuild) return;
  const products = await api('/products?guild_id=' + currentGuild);
  $('stock-product-select').innerHTML = '<option value="">— Pilih produk —</option>' +
    products.map(p => `<option value="${p.id}">${escapeHtml(p.name)} (${p.stock_available} avail)</option>`).join('');
}

$('stock-product-select').addEventListener('change', e => {
  const productId = e.target.value;
  if (!productId) { $('stock-content').innerHTML = ''; return; }
  loadStockItems(productId);
});

async function loadStockItems(productId) {
  const items = await api('/stock?product_id=' + productId);
  const availableCount = items.filter(i => !i.sold).length;
  const soldCount = items.filter(i => i.sold).length;

  $('stock-content').innerHTML = `
    <div class="form-row">
      <label>Tambah Stok (1 baris = 1 item)</label>
      <textarea id="stock-input" class="stock-textarea" placeholder="user1:pass1&#10;LICENSE-KEY-XXXX"></textarea>
    </div>
    <button class="btn primary" onclick="addStock(${productId})">+ Tambah Stok</button>
    <div style="margin-top:24px;display:flex;gap:12px;align-items:center">
      <h4 style="margin:0;color:var(--text-dim);font-size:14px;">Stock Items (${items.length})</h4>
      <span class="badge green">${availableCount} available</span>
      <span class="badge red">${soldCount} sold</span>
    </div>
    <div class="stock-list" style="margin-top:12px;">
      ${items.length === 0 ? '<div style="color:var(--text-mute);text-align:center;padding:40px;background:var(--bg);border-radius:var(--radius-sm);">Belum ada stok</div>' :
        `<table style="width:100%">
          <thead><tr><th style="width:60px">ID</th><th>Content</th><th style="width:100px">Status</th><th style="width:150px">Sold To</th><th style="width:120px">Actions</th></tr></thead>
          <tbody>
            ${items.map(s => {
              const preview = s.content.length > 40 ? s.content.slice(0, 40) + '...' : s.content;
              return `<tr style="${s.sold ? 'opacity:0.5' : ''}">
                <td><code>#${s.id}</code></td>
                <td><code style="font-size:12px">${escapeHtml(preview)}</code></td>
                <td>${s.sold ? '<span class="badge red">SOLD</span>' : '<span class="badge green">Available</span>'}</td>
                <td>${s.sold_to ? `<code style="font-size:11px">${s.sold_to}</code>` : '-'}</td>
                <td>
                  <button class="btn small" onclick="viewStockDetail(${s.id}, ${productId})">View</button>
                  ${!s.sold ? `<button class="btn small danger" onclick="deleteStock(${s.id}, ${productId})">Delete</button>` : ''}
                </td>
              </tr>`;
            }).join('')}
          </tbody>
        </table>`
      }
    </div>`;
}

window.viewStockDetail = async (stockId, productId) => {
  try {
    const items = await api('/stock?product_id=' + productId);
    const stock = items.find(s => s.id === stockId);
    if (!stock) return showToast('Stock not found', 'error');
    const soldInfo = stock.sold ? `
      <div style="margin-top:12px;padding:12px;background:var(--bg);border-radius:var(--radius-sm);border-left:3px solid var(--red)">
        <strong style="color:var(--red)">SOLD</strong><br>
        <small style="color:var(--text-dim)">To: <code>${stock.sold_to}</code> · ${stock.sold_at ? new Date(stock.sold_at * 1000).toLocaleString('id-ID') : '-'}</small>
      </div>` : '<div style="margin-top:12px;padding:12px;background:var(--bg);border-radius:var(--radius-sm);border-left:3px solid var(--green)"><strong style="color:var(--green)">AVAILABLE</strong></div>';

    showModal(`Stock #${stockId}`, `
      <div style="font-family:monospace">
        <div style="margin-bottom:12px">
          <label style="display:block;color:var(--text-dim);font-size:12px;margin-bottom:4px">FULL CONTENT:</label>
          <textarea readonly style="width:100%;min-height:150px;background:var(--bg);border:1px solid var(--border);border-radius:var(--radius-sm);padding:12px;color:var(--text);font-family:monospace;font-size:13px">${escapeHtml(stock.content)}</textarea>
        </div>
        ${soldInfo}
        <div style="margin-top:16px;display:flex;gap:8px">
          <button class="btn" onclick="copyStockContent('${escapeHtml(stock.content).replace(/'/g, "\\'").replace(/"/g, '&quot;')}')">Copy</button>
          <button class="btn" onclick="closeModal()">Close</button>
        </div>
      </div>`);
  } catch (e) { showToast('Error: ' + e.message, 'error'); }
};

window.copyStockContent = (content) => {
  const textarea = document.createElement('textarea');
  textarea.innerHTML = content;
  navigator.clipboard.writeText(textarea.value).then(() => showToast('Copied', 'success')).catch(() => showToast('Copy failed', 'error'));
};

window.addStock = async (productId) => {
  const content = $('stock-input').value.trim();
  if (!content) return showToast('Isi stok dulu', 'error');
  try {
    const r = await api('/stock', { method: 'POST', body: JSON.stringify({ product_id: productId, content }) });
    showToast(`+${r.added} item ditambah`, 'success');
    loadStockItems(productId); loadStockTab();
  } catch (e) { showToast(e.message, 'error'); }
};
window.deleteStock = async (id, productId) => {
  await api('/stock/' + id, { method: 'DELETE' });
  loadStockItems(productId); loadStockTab();
};

// ===== Orders =====
async function loadOrders() {
  if (!currentGuild) return;
  const orders = await api('/orders?guild_id=' + currentGuild);
  if (!orders.length) {
    $('orders-list').innerHTML = '<div class="card"><div class="card-body" style="color:var(--text-mute);text-align:center;">Belum ada order</div></div>';
    return;
  }
  $('orders-list').innerHTML = `
    <div class="card"><div class="card-body" style="padding:0;">
      <table>
        <thead><tr><th>Invoice</th><th>Produk</th><th>User</th><th>Total</th><th>Status</th><th>Created</th><th>Paid</th></tr></thead>
        <tbody>${orders.map(o => `
          <tr>
            <td><code>${o.invoice_id}</code></td>
            <td>${escapeHtml(o.product_name || '-')}</td>
            <td><code>${o.user_id}</code></td>
            <td>${fmtIDR(o.total)}</td>
            <td><span class="badge ${o.status === 'delivered' ? 'green' : o.status === 'pending' ? 'warn' : 'red'}">${o.status}</span></td>
            <td>${new Date(o.created_at * 1000).toLocaleString('id-ID')}</td>
            <td>${o.paid_at ? new Date(o.paid_at * 1000).toLocaleString('id-ID') : '-'}</td>
          </tr>
        `).join('')}</tbody>
      </table>
    </div></div>`;
}

// ===== My Bot =====
async function loadMyBot() {
  try {
    const s = await authApi('/bot/status');
    const badge = $('mybot-badge');
    const map = { running: ['Running', 'green'], stopped: ['Stopped', ''], error: ['Error', 'red'] };
    const [label, cls] = map[s.status] || map.stopped;
    badge.textContent = label;
    badge.className = 'badge ' + cls;
    $('mybot-name').textContent = s.bot_name ? `· ${s.bot_name}` : '';
    $('mybot-guilds').textContent = s.guild_count != null ? `· ${s.guild_count} server` : '';
    $('bot-token-preview').textContent = s.token_preview || '(belum di-set)';

    const errBox = $('mybot-error');
    if (s.last_error) { errBox.textContent = s.last_error; errBox.style.display = 'block'; }
    else errBox.style.display = 'none';

    $('btn-bot-start').disabled = !s.configured || s.running;
    $('btn-bot-stop').disabled = !s.running;
  } catch (e) { showToast(e.message, 'error'); }
}

$('btn-bot-save-token').addEventListener('click', async () => {
  const token = $('bot-token').value.trim();
  if (!token) return showToast('Masukin token dulu', 'error');
  try {
    await authApi('/bot/token', { method: 'POST', body: JSON.stringify({ token }) });
    $('bot-token').value = '';
    showToast('Token tersimpan (terenkripsi)', 'success');
    loadMyBot();
  } catch (e) { showToast(e.message, 'error'); }
});

$('btn-bot-delete-token').addEventListener('click', async () => {
  if (!confirm('Hapus token bot?')) return;
  try {
    await authApi('/bot/token', { method: 'DELETE' });
    showToast('Token dihapus', 'success');
    loadMyBot();
  } catch (e) { showToast(e.message, 'error'); }
});

$('btn-bot-start').addEventListener('click', async () => {
  $('btn-bot-start').disabled = true;
  showToast('Menyalakan bot...', '');
  try {
    await authApi('/bot/start', { method: 'POST' });
    showToast('Bot online', 'success');
  } catch (e) { showToast(e.message, 'error'); }
  loadMyBot();
});

$('btn-bot-stop').addEventListener('click', async () => {
  try {
    await authApi('/bot/stop', { method: 'POST' });
    showToast('Bot dihentikan', 'success');
  } catch (e) { showToast(e.message, 'error'); }
  loadMyBot();
});

// ===== Payment Config =====
let _payQrisUploadInit = false;
async function loadPaymentConfig() {
  if (!currentGuild) return;
  try {
    const c = await api('/payment-config?guild_id=' + currentGuild);
    $('pay-tripay-enabled').checked = !!c.tripay_enabled;
    $('pay-midtrans-enabled').checked = !!c.midtrans_enabled;
    $('pay-pakasir-enabled').checked = !!c.pakasir_enabled;
    $('pay-auto-delivery').checked = !!c.auto_delivery;
    $('pay-tripay-merchant').value = c.tripay_merchant_code || '';
    $('pay-midtrans-client').value = c.midtrans_client_key || '';
    $('pay-midtrans-prod').checked = !!c.midtrans_is_production;
    $('pay-pakasir-slug').value = c.pakasir_slug || '';
    $('pay-manual-methods').value = c.manual_methods || '';
    $('pay-qris-url').value = c.qris_image_url || '';
    $('pay-tripay-api-mask').textContent = c.tripay_configured ? (c.tripay_api_key_mask || '****') : '(belum ada)';
    $('pay-midtrans-server-mask').textContent = c.midtrans_configured ? (c.midtrans_server_key_mask || '****') : '(belum ada)';
    $('pay-pakasir-api-mask').textContent = c.pakasir_configured ? (c.pakasir_api_key_mask || '****') : '(belum ada)';
    $('pay-tripay-api').value = '';
    $('pay-tripay-priv').value = '';
    $('pay-midtrans-server').value = '';
    $('pay-pakasir-api').value = '';
    const qp = $('pay-qris-preview');
    if (c.qris_image_url) { qp.src = c.qris_image_url; qp.style.display = 'block'; }
    else qp.style.display = 'none';
    if (!_payQrisUploadInit) { createImageUpload('pay-qris-url', 'pay-qris-preview'); _payQrisUploadInit = true; }
  } catch (e) { showToast(e.message, 'error'); }
}

$('btn-save-payment').addEventListener('click', async () => {
  const body = {
    guild_id: currentGuild,
    tripay_enabled: $('pay-tripay-enabled').checked,
    midtrans_enabled: $('pay-midtrans-enabled').checked,
    pakasir_enabled: $('pay-pakasir-enabled').checked,
    auto_delivery: $('pay-auto-delivery').checked,
    tripay_merchant_code: $('pay-tripay-merchant').value.trim(),
    midtrans_client_key: $('pay-midtrans-client').value.trim(),
    midtrans_is_production: $('pay-midtrans-prod').checked,
    pakasir_slug: $('pay-pakasir-slug').value.trim(),
    manual_methods: $('pay-manual-methods').value.trim(),
    qris_image_url: $('pay-qris-url').value.trim(),
  };
  const ta = $('pay-tripay-api').value.trim(); if (ta) body.tripay_api_key = ta;
  const tp = $('pay-tripay-priv').value.trim(); if (tp) body.tripay_private_key = tp;
  const ms = $('pay-midtrans-server').value.trim(); if (ms) body.midtrans_server_key = ms;
  const pk = $('pay-pakasir-api').value.trim(); if (pk) body.pakasir_api_key = pk;
  try {
    await api('/payment-config', { method: 'POST', body: JSON.stringify(body) });
    showToast('Setting pembayaran tersimpan', 'success');
    loadPaymentConfig();
  } catch (e) { showToast(e.message, 'error'); }
});

// ===== Users (admin only) =====
async function loadUsers() {
  try {
    const users = await authApi('/auth/users');
    $('users-list').innerHTML = `
      <table>
        <thead><tr><th>ID</th><th>Username</th><th>Role</th><th>Status</th><th>Aksi</th></tr></thead>
        <tbody>${users.map(u => `
          <tr>
            <td>${u.id}</td>
            <td>${escapeHtml(u.username)}</td>
            <td><span class="badge ${u.role === 'admin' ? 'green' : ''}">${u.role}</span></td>
            <td>${u.enabled ? 'Aktif' : 'Nonaktif'}</td>
            <td>
              <button class="btn small" onclick="toggleUser(${u.id}, ${u.enabled ? 0 : 1})">${u.enabled ? 'Nonaktifkan' : 'Aktifkan'}</button>
              <button class="btn small" onclick="resetUserPw(${u.id})">Reset PW</button>
              ${u.id !== currentUser.id ? `<button class="btn small danger" onclick="removeUser(${u.id})">Hapus</button>` : ''}
            </td>
          </tr>
        `).join('')}</tbody>
      </table>`;
  } catch (e) {
    $('users-list').innerHTML = `<p style="color:var(--red);padding:16px">${escapeHtml(e.message)}</p>`;
  }
}

window.toggleUser = async (id, enabled) => {
  try { await authApi(`/auth/users/${id}/enabled`, { method: 'POST', body: JSON.stringify({ enabled: !!enabled }) }); loadUsers(); }
  catch (e) { showToast(e.message, 'error'); }
};
window.resetUserPw = async (id) => {
  const pw = prompt('Password baru (min 6 char):');
  if (!pw) return;
  try { await authApi(`/auth/users/${id}/password`, { method: 'POST', body: JSON.stringify({ new_password: pw }) }); showToast('Password di-reset', 'success'); }
  catch (e) { showToast(e.message, 'error'); }
};
window.removeUser = async (id) => {
  if (!confirm('Hapus user ini?')) return;
  try { await authApi(`/auth/users/${id}`, { method: 'DELETE' }); loadUsers(); }
  catch (e) { showToast(e.message, 'error'); }
};

$('btn-new-user').addEventListener('click', () => {
  showModal('User Baru', `
    <form onsubmit="event.preventDefault(); createNewUser()">
      <div class="form-row"><label>Username</label><input id="nu-username" required /></div>
      <div class="form-row"><label>Password (min 6)</label><input id="nu-password" type="text" required /></div>
      <div class="form-row"><label>Role</label>
        <select id="nu-role"><option value="user">user</option><option value="admin">admin</option></select>
      </div>
      <div class="form-actions">
        <button type="button" class="btn" onclick="closeModal()">Cancel</button>
        <button type="submit" class="btn primary">Buat</button>
      </div>
    </form>`);
});

window.createNewUser = async () => {
  try {
    await authApi('/auth/users', { method: 'POST', body: JSON.stringify({
      username: $('nu-username').value.trim(), password: $('nu-password').value, role: $('nu-role').value,
    }) });
    closeModal(); showToast('User dibuat', 'success'); loadUsers();
  } catch (e) { showToast(e.message, 'error'); }
};

// ===== Boot =====
async function boot() {
  let me;
  try { me = await authApi('/auth/me'); } catch { location.href = '/login'; return; }
  currentUser = me.user;
  $('current-user').textContent = `${currentUser.username} (${currentUser.role})`;
  if (currentUser.role === 'admin') $('nav-users').style.display = '';
  loadGuilds();
  setInterval(() => {
    if (document.querySelector('.nav-item.active')?.dataset.tab === 'dashboard') loadDashboard();
  }, 30000);
}

$('btn-logout').addEventListener('click', async () => {
  try { await authApi('/auth/logout', { method: 'POST' }); } catch {}
  location.href = '/login';
});

boot();

// ===== Channel Picker =====
async function pickChannel(title, onPick) {
  if (!currentGuild) return showToast('Pilih guild dulu', 'error');
  showModal(title, '<div style="text-align:center;color:var(--text-mute);padding:30px;">Memuat channel...</div>');
  try {
    const channels = await api('/channels?guild_id=' + currentGuild);
    const cats = channels.filter(c => c.type === 4);
    const others = channels.filter(c => c.type !== 4);
    const grouped = {};
    cats.forEach(c => { grouped[c.id] = { name: c.name, items: [] }; });
    grouped['_none'] = { name: 'Tanpa Kategori', items: [] };
    others.forEach(c => {
      const key = c.parent_id || '_none';
      if (!grouped[key]) grouped[key] = { name: c.parent_name || 'Tanpa Kategori', items: [] };
      grouped[key].items.push(c);
    });

    const html = `
      <input type="text" id="ch-search" placeholder="Cari channel..." style="margin-bottom:14px;" />
      <div id="ch-list" style="max-height:50vh;overflow-y:auto;">
        ${Object.values(grouped).filter(g => g.items.length).map(g => `
          <div style="margin-bottom:14px;">
            <div style="font-size:11px;text-transform:uppercase;color:var(--text-mute);letter-spacing:0.8px;margin-bottom:6px;font-weight:700;">${escapeHtml(g.name)}</div>
            ${g.items.map(c => `
              <div class="ch-row" data-name="${escapeHtml(c.name.toLowerCase())}" style="display:flex;align-items:center;justify-content:space-between;padding:10px 14px;background:var(--bg);border-radius:var(--radius-sm);margin-bottom:4px;">
                <span style="color:var(--text-dim)"># ${escapeHtml(c.name)}</span>
                <button class="btn small primary" onclick="window.__pickChannelChosen('${c.id}')">Pilih</button>
              </div>
            `).join('')}
          </div>
        `).join('')}
      </div>`;
    $('modal-body').innerHTML = html;
    window.__pickChannelChosen = (id) => onPick(id);
    $('ch-search').addEventListener('input', e => {
      const q = e.target.value.toLowerCase();
      document.querySelectorAll('.ch-row').forEach(r => {
        r.style.display = r.dataset.name.includes(q) ? 'flex' : 'none';
      });
    });
  } catch (e) { showToast(e.message, 'error'); closeModal(); }
}

// ===== Emojis =====
async function loadEmojis() {
  if (!currentGuild) return;
  try {
    const emojis = await api('/emojis?guild_id=' + currentGuild);
    if (!emojis.length) {
      $('emojis-list').innerHTML = '<div class="card"><div class="card-body" style="color:var(--text-mute);text-align:center;">Belum ada custom emoji.</div></div>';
      return;
    }
    $('emojis-list').innerHTML = emojis.map(e => `
      <div class="item-card">
        <div style="text-align:center;padding:14px;background:var(--bg);border-radius:var(--radius-sm);margin-bottom:10px;">
          <img src="${escapeHtml(e.url)}" alt="${escapeHtml(e.name)}" style="width:64px;height:64px;object-fit:contain;" />
        </div>
        <div class="title">:${escapeHtml(e.name)}:</div>
        <div class="meta" style="margin-top:6px;">${e.animated ? '<span class="badge warn">animated</span>' : '<span class="badge">static</span>'}</div>
        <div style="margin-top:8px;font-family:monospace;font-size:11px;color:var(--text-dim);background:var(--bg);padding:6px 8px;border-radius:4px;word-break:break-all;cursor:pointer;" onclick="navigator.clipboard.writeText('${e.tag}'); showToast('Copied','success')">${escapeHtml(e.tag)}</div>
        <div class="actions">
          <button class="btn small danger" onclick="deleteEmoji('${e.id}')">Delete</button>
        </div>
      </div>
    `).join('');
  } catch (e) { showToast(e.message, 'error'); }
}

window.deleteEmoji = async (id) => {
  if (!confirm('Hapus emoji ini?')) return;
  try {
    await fetch(`/api/emojis/${id}?guild_id=${currentGuild}`, { method: 'DELETE', credentials: 'include', headers: { 'Content-Type': 'application/json' } });
    showToast('Deleted', 'success'); loadEmojis();
  } catch (e) { showToast(e.message, 'error'); }
};

$('btn-new-emoji').addEventListener('click', () => {
  showModal('Upload Emoji', `
    <form onsubmit="event.preventDefault(); uploadEmoji()">
      <div class="form-row">
        <label>Nama</label>
        <input id="emoji-name" placeholder="my_emoji" required />
      </div>
      <div class="form-row">
        <label>Upload File</label>
        <input id="emoji-file" type="file" accept="image/png,image/jpeg,image/jpg,image/gif,image/webp" />
        <img id="emoji-preview" style="display:none;max-height:96px;margin-top:10px;border-radius:var(--radius-sm)" />
      </div>
      <div class="form-row">
        <label>Atau Image URL</label>
        <input id="emoji-url" placeholder="https://..." />
      </div>
      <div class="form-actions">
        <button type="button" class="btn" onclick="closeModal()">Cancel</button>
        <button type="submit" class="btn primary">Upload</button>
      </div>
    </form>`);
  const fileInput = $('emoji-file');
  fileInput.addEventListener('change', () => {
    const f = fileInput.files[0];
    if (!f) return;
    const reader = new FileReader();
    reader.onload = ev => { const img = $('emoji-preview'); img.src = ev.target.result; img.style.display = 'block'; };
    reader.readAsDataURL(f);
  });
});

function readFileAsDataURL(file) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result);
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
}

window.uploadEmoji = async () => {
  const name = $('emoji-name').value;
  const file = $('emoji-file').files[0];
  const url = $('emoji-url').value.trim();
  if (!name) return showToast('Nama emoji wajib diisi', 'error');
  if (!file && !url) return showToast('Pilih file atau isi URL', 'error');
  try {
    const body = { guild_id: currentGuild, name };
    if (file) body.image_data = await readFileAsDataURL(file);
    else body.url = url;
    await api('/emojis', { method: 'POST', body: JSON.stringify(body) });
    closeModal(); showToast('Emoji uploaded', 'success'); loadEmojis();
  } catch (e) { showToast(e.message, 'error'); }
};

// ===== Ticket Panel =====
$('btn-place-ticket').addEventListener('click', () => {
  const title = $('tp-title').value;
  const rules = $('tp-rules').value;
  const placeholder = $('tp-placeholder').value;
  const color = $('tp-color').value;
  pickChannel('Pilih Channel untuk Order Panel', async (channelId) => {
    try {
      await api('/ticket-panel/send', {
        method: 'POST',
        body: JSON.stringify({ guild_id: currentGuild, channel_id: channelId, title, rules, placeholder, color, mention_everyone: $('tp-mention').checked }),
      });
      closeModal(); showToast('Order panel terkirim!', 'success');
    } catch (e) { showToast(e.message, 'error'); }
  });
});

// ===== Announcement =====
let announcementChannels = [];

async function loadAnnouncementChannels() {
  if (!currentGuild) return;
  try {
    const channels = await api(`/channels?guild_id=${currentGuild}`);
    announcementChannels = channels.filter(c => c.type === 0 || c.type === 5);
    const select = $('ann-channel');
    select.innerHTML = '<option value="">-- Pilih Channel --</option>' +
      announcementChannels.map(c => {
        const prefix = c.parent_name ? `${c.parent_name} / ` : '';
        return `<option value="${c.id}">${prefix}#${escapeHtml(c.name)}</option>`;
      }).join('');
  } catch (e) {}
}

$('btn-preview-announcement').addEventListener('click', () => {
  const title = $('ann-title').value;
  const message = $('ann-message').value;
  const color = $('ann-color').value;
  const imageUrl = $('ann-image').value;
  const mentionEveryone = $('ann-mention').checked;
  if (!message.trim()) return showToast('Message tidak boleh kosong', 'error');

  const colors = { red: '#ef4444', green: '#2ecc71', blue: '#6b5ce7', yellow: '#fbbf24', purple: '#a855f7' };
  const embedColor = colors[color] || colors.blue;
  $('ann-preview-content').innerHTML = `
    <div style="border-left:4px solid ${embedColor};background:var(--bg);padding:18px;border-radius:var(--radius-sm);max-width:520px">
      ${mentionEveryone ? '<div style="color:var(--accent);margin-bottom:8px">@everyone</div>' : ''}
      ${title ? `<div style="font-weight:700;font-size:16px;margin-bottom:8px;color:var(--text)">${escapeHtml(title)}</div>` : ''}
      <div style="color:var(--text-dim);white-space:pre-wrap">${escapeHtml(message)}</div>
      ${imageUrl ? `<img src="${escapeHtml(imageUrl)}" style="max-width:100%;margin-top:12px;border-radius:var(--radius-sm)" onerror="this.style.display='none'" />` : ''}
      <div style="color:var(--text-mute);font-size:12px;margin-top:12px">${new Date().toLocaleString('id-ID')}</div>
    </div>`;
  $('ann-preview-card').style.display = 'block';
});

$('btn-send-announcement').addEventListener('click', async () => {
  const channelId = $('ann-channel').value;
  const title = $('ann-title').value;
  const message = $('ann-message').value;
  const color = $('ann-color').value;
  const imageUrl = $('ann-image').value;
  const mentionEveryone = $('ann-mention').checked;
  if (!channelId) return showToast('Pilih channel dulu', 'error');
  if (!message.trim()) return showToast('Message tidak boleh kosong', 'error');
  if (message.length > 4000) return showToast('Message terlalu panjang (max 4000)', 'error');

  const channelName = announcementChannels.find(c => c.id === channelId)?.name || channelId;
  if (!confirm(`Kirim announcement ke #${channelName}?`)) return;
  try {
    const result = await api('/announcement/send', {
      method: 'POST',
      body: JSON.stringify({ channel_id: channelId, message, title: title || undefined, color, image_url: imageUrl || undefined, mention_everyone: mentionEveryone }),
    });
    showToast(`Announcement terkirim ke #${channelName}`, 'success');
    $('ann-title').value = ''; $('ann-message').value = ''; $('ann-image').value = '';
    $('ann-color').value = 'blue'; $('ann-mention').checked = true;
    $('ann-preview-card').style.display = 'none';
    if (result.url) setTimeout(() => { if (confirm('Buka message di Discord?')) window.open(result.url, '_blank'); }, 500);
  } catch (e) { showToast(e.message, 'error'); }
});

document.querySelector('[data-tab="announcement"]').addEventListener('click', () => loadAnnouncementChannels());
createImageUpload('ann-image', 'ann-image-preview');

// ===== Manual Delivery =====
let manualDeliveryProducts = [];

async function loadManualDeliveryProducts() {
  if (!currentGuild) return;
  try {
    const products = await api(`/products?guild_id=${currentGuild}`);
    manualDeliveryProducts = products.filter(p => p.enabled);
    const select = $('send-product');
    select.innerHTML = '<option value="">-- Pilih Produk --</option>' +
      manualDeliveryProducts.map(p => {
        const stock = p.stock_available || 0;
        const skuLabel = p.sku ? `[${p.sku}] ` : `#${p.id} `;
        return `<option value="${p.id}">${skuLabel}${escapeHtml(p.name)} (stock: ${stock})</option>`;
      }).join('');
  } catch (e) {}
}

async function loadManualDeliveryLog() {
  if (!currentGuild) return;
  try {
    const logs = await api(`/manual-delivery-log?guild_id=${currentGuild}`);
    if (!logs.length) {
      $('manual-delivery-log').innerHTML = '<p style="color:var(--text-mute);padding:16px">Belum ada manual delivery</p>';
      return;
    }
    $('manual-delivery-log').innerHTML = `
      <table>
        <thead><tr><th>Date</th><th>Target</th><th>Product</th><th>Qty</th><th>Note</th></tr></thead>
        <tbody>${logs.map(l => `
          <tr>
            <td>${l.created_at_formatted}</td>
            <td><code>${l.data.target_user}</code></td>
            <td>${escapeHtml(l.data.product_name)}</td>
            <td>${l.data.quantity}</td>
            <td>${escapeHtml(l.data.note || '-')}</td>
          </tr>
        `).join('')}</tbody>
      </table>`;
  } catch (e) {
    $('manual-delivery-log').innerHTML = '<p style="color:var(--red);padding:16px">Error loading log</p>';
  }
}

$('btn-manual-send').addEventListener('click', async () => {
  const userId = $('send-user-id').value.trim();
  const productId = $('send-product').value;
  const quantity = parseInt($('send-quantity').value);
  const note = $('send-note').value.trim();
  if (!userId) return showToast('User ID wajib diisi', 'error');
  if (!productId) return showToast('Pilih produk dulu', 'error');
  if (!userId.match(/^\d{17,19}$/)) return showToast('User ID tidak valid', 'error');
  const product = manualDeliveryProducts.find(p => p.id == productId);
  if (!product) return showToast('Produk tidak ditemukan', 'error');
  if (!confirm(`Kirim ${quantity}x "${product.name}" ke user ${userId}?`)) return;
  try {
    showToast('Sending...', '');
    const result = await api('/manual-delivery', {
      method: 'POST',
      body: JSON.stringify({ guild_id: currentGuild, user_id: userId, product_id: productId, quantity, note: note || undefined }),
    });
    showToast(`Berhasil kirim ke ${result.user_tag}`, 'success');
    $('send-user-id').value = ''; $('send-quantity').value = '1'; $('send-note').value = '';
    loadManualDeliveryProducts(); loadManualDeliveryLog();
  } catch (e) { showToast(e.message, 'error'); }
});

document.querySelector('[data-tab="send"]').addEventListener('click', () => {
  loadManualDeliveryProducts(); loadManualDeliveryLog();
});

// ===== Settings =====
async function loadSettings() {
  if (!currentGuild) return;
  try {
    const cfg = await api('/guild-config?guild_id=' + currentGuild);
    $('cfg-emoji-price').value = cfg.emoji_price || '';
    $('cfg-emoji-stock').value = cfg.emoji_stock || '';
    $('cfg-emoji-sku').value = cfg.emoji_sku || '';
    $('cfg-emoji-category').value = cfg.emoji_category || '';
    $('cfg-emoji-description').value = cfg.emoji_description || '';
    $('cfg-emoji-order').value = cfg.emoji_order || '';
    const tc = cfg.ticket_color || '#5865F2';
    $('cfg-ticket-color').value = tc;
    $('cfg-ticket-color-hex').value = tc;
    $('cfg-ticket-cat').value = cfg.ticket_category_id || '';
    $('cfg-log-channel').value = cfg.log_channel_id || '';
    $('cfg-staff-role').value = cfg.staff_role_id || '';
    $('tp-color').value = tc;
    $('tp-color-hex').value = tc;
  } catch (e) { console.error('loadSettings', e); }
}

$('btn-save-settings')?.addEventListener('click', async () => {
  try {
    await api('/guild-config', {
      method: 'PUT',
      body: JSON.stringify({
        guild_id: currentGuild,
        emoji_price: $('cfg-emoji-price').value.trim(),
        emoji_stock: $('cfg-emoji-stock').value.trim(),
        emoji_sku: $('cfg-emoji-sku').value.trim(),
        emoji_category: $('cfg-emoji-category').value.trim(),
        emoji_description: $('cfg-emoji-description').value.trim(),
        emoji_order: $('cfg-emoji-order').value.trim(),
        ticket_color: $('cfg-ticket-color').value,
        ticket_category_id: $('cfg-ticket-cat').value.trim(),
        log_channel_id: $('cfg-log-channel').value.trim(),
        staff_role_id: $('cfg-staff-role').value.trim(),
      }),
    });
    showToast('Settings saved!', 'success');
  } catch (e) { showToast(e.message, 'error'); }
});

// Color picker sync
$('cfg-ticket-color')?.addEventListener('input', e => { $('cfg-ticket-color-hex').value = e.target.value; });
$('cfg-ticket-color-hex')?.addEventListener('input', e => {
  if (/^#[0-9a-fA-F]{6}$/.test(e.target.value)) $('cfg-ticket-color').value = e.target.value;
});
$('tp-color')?.addEventListener('input', e => { $('tp-color-hex').value = e.target.value; });
$('tp-color-hex')?.addEventListener('input', e => {
  if (/^#[0-9a-fA-F]{6}$/.test(e.target.value)) $('tp-color').value = e.target.value;
});

// ===== Theme Toggle =====
function setTheme(mode) {
  document.documentElement.setAttribute('data-theme', mode);
  localStorage.setItem('theme', mode);
  const btn = $('btn-theme-toggle');
  if (btn) {
    btn.innerHTML = mode === 'light'
      ? '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></svg>'
      : '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="5"/><line x1="12" y1="1" x2="12" y2="3"/><line x1="12" y1="21" x2="12" y2="23"/><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"/><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"/><line x1="1" y1="12" x2="3" y2="12"/><line x1="21" y1="12" x2="23" y2="12"/><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"/><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"/></svg>';
  }
  document.querySelectorAll('input[name="theme"]').forEach(r => { r.checked = r.value === mode; });
}

$('btn-theme-toggle')?.addEventListener('click', () => {
  const current = document.documentElement.getAttribute('data-theme') || 'dark';
  setTheme(current === 'dark' ? 'light' : 'dark');
});

document.querySelectorAll('input[name="theme"]').forEach(r => {
  r.addEventListener('change', e => { if (e.target.checked) setTheme(e.target.value); });
});

// Restore theme on load
const savedTheme = localStorage.getItem('theme') || 'dark';
setTheme(savedTheme);

// ===== Status Bar Polling =====
async function updateStatusBar() {
  try {
    const health = await api('/health');
    const botDot = $('sb-bot-dot');
    const botStatus = $('sb-bot-status');
    const lastUpdate = $('sb-last-update');
    if (health?.ok) {
      if (botDot) botDot.className = 'status-dot';
      if (botStatus) botStatus.textContent = 'Bot Online';
    } else {
      if (botDot) botDot.className = 'status-dot offline';
      if (botStatus) botStatus.textContent = 'Bot Offline';
    }
    if (lastUpdate) lastUpdate.textContent = 'Last updated: just now';
  } catch {
    const botDot = $('sb-bot-dot');
    const botStatus = $('sb-bot-status');
    if (botDot) botDot.className = 'status-dot offline';
    if (botStatus) botStatus.textContent = 'Connection Error';
  }
}
updateStatusBar();
setInterval(updateStatusBar, 30000);
