const ADMIN_KEY = "weavy_admin_password";
let adminPass = "";
let sseSource = null;
let countdownInterval = null;
let nextRunTime = null;

const $ = (id) => document.getElementById(id);
const els = {
  loginScreen: $("login-screen"),
  adminScreen: $("admin-screen"),
  password: $("admin-password"),
  loginBtn: $("login-btn"),
  loginStatus: $("login-status"),

  cleanBtn: $("clean-btn"),
  syncBtn: $("sync-btn"),
  refreshBtn: $("refresh-btn"),
  logoutBtn: $("logout-btn"),
  stats: $("stats"),
  accountList: $("account-list"),
  poolSize: $("pool-size"),

  addToken: $("add-token"),
  addRecipe: $("add-recipe"),
  addLabel: $("add-label"),
  addBtn: $("add-btn"),

  bulkText: $("bulk-text"),
  bulkBtn: $("bulk-btn"),

  editForm: $("edit-form"),
  editId: $("edit-id"),
  editToken: $("edit-token"),
  editRecipe: $("edit-recipe"),
  editLabel: $("edit-label"),
  saveEditBtn: $("save-edit-btn"),
  cancelEditBtn: $("cancel-edit-btn"),

  // Bot elements
  botRunBtn: $("bot-run-btn"),
  botStatusBadge: $("bot-status-badge"),
  botCountdown: $("bot-countdown"),
  countdownTimer: $("countdown-timer"),
  schedulerToggle: $("scheduler-toggle"),
  schedulerInterval: $("scheduler-interval"),
  logBody: $("log-body"),
  logClearBtn: $("log-clear-btn"),
  botLastRun: $("bot-last-run"),
  botLastRunText: $("bot-last-run-text"),
  botStopBtn: $("bot-stop-btn"),
  headlessToggle: $("headless-toggle"),

  // Voucher elements
  vchCode: $("vch-code"),
  vchTier: $("vch-tier"),
  createVchBtn: $("create-vch-btn"),
  voucherList: $("voucher-list"),
  vchWhatsapp: $("vch-whatsapp"),
  vchDuration: $("vch-duration"),
  vchDurationDays: $("vch-duration-days"),
  vchDurationDaysWrapper: $("vch-duration-days-wrapper"),
  vchDailyLimit: $("vch-daily-limit"),
};

// ─── Utilities ──────────────────────────────────────────────────────────────

function setLoginStatus(text, type = "") {
  if (!text) { els.loginStatus.hidden = true; return; }
  els.loginStatus.hidden = false;
  els.loginStatus.textContent = text;
  els.loginStatus.className = `status ${type}`;
}

async function api(path, opts = {}) {
  const headers = { "Content-Type": "application/json", "x-admin-password": adminPass, ...(opts.headers || {}) };
  const res = await fetch(path, { ...opts, headers });
  const data = await res.json().catch(() => ({}));
  if (!res.ok) throw new Error(data.error || `HTTP ${res.status}`);
  return data;
}

function escapeHtml(s) {
  return String(s ?? "").replace(/[&<>"']/g, (c) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" }[c]));
}

function formatTimeLeft(exp) {
  if (!exp) return "no exp";
  const sec = exp - Date.now() / 1000;
  if (sec <= 0) return "expired";
  if (sec < 60) return `${Math.floor(sec)}s left`;
  if (sec < 3600) return `${Math.floor(sec / 60)}m left`;
  return `${Math.floor(sec / 3600)}h ${Math.floor((sec % 3600) / 60)}m left`;
}

// ─── Login ──────────────────────────────────────────────────────────────────

async function tryLogin(password) {
  try {
    const res = await fetch("/api/admin/login", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ password }),
    });
    const data = await res.json().catch(() => ({}));
    if (!res.ok) throw new Error(data.error || "Login failed");
    adminPass = password;
    sessionStorage.setItem(ADMIN_KEY, password);
    showAdmin();
    return true;
  } catch (err) {
    setLoginStatus(err.message, "error");
    return false;
  }
}

els.loginBtn.addEventListener("click", () => {
  const pass = els.password.value.trim();
  if (!pass) return;
  setLoginStatus("Logging in...");
  tryLogin(pass);
});

els.password.addEventListener("keydown", (e) => {
  if (e.key === "Enter") els.loginBtn.click();
});

const togglePassword = $("toggle-password");
if (togglePassword) {
  togglePassword.addEventListener("click", () => {
    const isPass = els.password.type === "password";
    els.password.type = isPass ? "text" : "password";
    togglePassword.textContent = isPass ? "🙈" : "👁️";
  });
}

els.logoutBtn.addEventListener("click", () => {
  adminPass = "";
  sessionStorage.removeItem(ADMIN_KEY);
  els.adminScreen.hidden = true;
  els.loginScreen.hidden = false;
  els.password.value = "";
  setLoginStatus("");
  closeSse();
});

function showAdmin() {
  els.loginScreen.hidden = true;
  els.adminScreen.hidden = false;
  setLoginStatus("");
  refresh();
  loadBotStatus();
  connectSse();
}

// ─── Account list ────────────────────────────────────────────────────────────

async function refresh() {
  try {
    const { accounts } = await api("/api/admin/accounts");
    renderStats(accounts);
    renderList(accounts);
    els.poolSize.textContent = `${accounts.length} (${accounts.filter((a) => !a.expired).length} aktif)`;
    refreshVouchers().catch(() => {});
  } catch (err) {
    if (err.message === "Unauthorized") {
      els.logoutBtn.click();
      setLoginStatus("Session expired, login lagi", "warn");
    } else {
      console.error(err);
    }
  }
}

function renderStats(accounts) {
  const total = accounts.length;
  const active = accounts.filter((a) => !a.expired).length;
  const expired = total - active;
  const totalRuns = accounts.reduce((s, a) => s + (a.runs || 0), 0);
  els.stats.innerHTML = `
    <div class="stat"><div class="stat-num">${total}</div><div class="stat-label">Total Akun</div></div>
    <div class="stat"><div class="stat-num good">${active}</div><div class="stat-label">Aktif</div></div>
    <div class="stat"><div class="stat-num bad">${expired}</div><div class="stat-label">Expired</div></div>
    <div class="stat"><div class="stat-num">${totalRuns}</div><div class="stat-label">Total Runs</div></div>
  `;
}

function renderList(accounts) {
  if (!accounts.length) {
    els.accountList.innerHTML = `<div class="empty-accounts">Belum ada akun. Tambahkan di bawah atau gunakan Auto Token Bot.</div>`;
    return;
  }
  els.accountList.innerHTML = "";
  for (const a of accounts) {
    const row = document.createElement("div");
    row.className = `account-row ${a.expired ? "expired" : ""}`;
    row.innerHTML = `
      <div class="acc-info">
        <div class="acc-label">${escapeHtml(a.label)}</div>
        <div class="acc-meta">
          <span>${escapeHtml(a.email || "?")}</span>
          <span class="dot">·</span>
          <span class="${a.expired ? "exp-bad" : "exp-ok"}">${formatTimeLeft(a.exp)}</span>
          <span class="dot">·</span>
          <span>runs: ${a.runs || 0}</span>
          <span class="dot">·</span>
          <span>recipe: <code>${escapeHtml(a.recipeId || "default")}</code></span>
        </div>
        <div class="acc-meta">
          <span class="muted-inline">${escapeHtml(a.tokenPreview)}</span>
        </div>
      </div>
      <div class="acc-actions">
        <button type="button" class="ghost small" data-act="edit" data-id="${a.id}">✏️</button>
        <button type="button" class="ghost small danger" data-act="del" data-id="${a.id}">🗑️</button>
      </div>
    `;
    els.accountList.appendChild(row);
  }

  els.accountList.querySelectorAll("button[data-act=del]").forEach((b) => {
    b.addEventListener("click", async () => {
      if (!confirm("Hapus akun ini?")) return;
      try {
        await api(`/api/admin/accounts/${b.dataset.id}`, { method: "DELETE" });
        refresh();
      } catch (err) { alert(err.message); }
    });
  });
  els.accountList.querySelectorAll("button[data-act=edit]").forEach((b) => {
    b.addEventListener("click", async () => {
      const a = accounts.find((x) => x.id === b.dataset.id);
      if (!a) return;
      els.editId.value = a.id;
      els.editToken.value = "";
      els.editToken.placeholder = `(token tersembunyi: ${a.tokenPreview}) — kosongkan jika tidak diubah`;
      els.editRecipe.value = a.recipeId || "";
      els.editLabel.value = a.label || "";
      els.editForm.hidden = false;
      els.editForm.scrollIntoView({ behavior: "smooth" });
    });
  });
}

// ─── Add / edit / bulk ──────────────────────────────────────────────────────

els.refreshBtn.addEventListener("click", refresh);

els.syncBtn.addEventListener("click", async () => {
  els.syncBtn.disabled = true;
  els.syncBtn.textContent = "☁️ Syncing...";
  try {
    const res = await api("/api/admin/accounts/sync", { method: "POST" });
    alert("Sinkronisasi Sukses: " + res.msg);
    refresh();
  } catch (err) {
    alert("Gagal Sinkronisasi: " + err.message);
  } finally {
    els.syncBtn.disabled = false;
    els.syncBtn.textContent = "☁️ Sync Server";
  }
});

els.cleanBtn.addEventListener("click", async () => {
  if (!confirm("Bersihkan semua akun yang expired/habis jatah generate?")) return;
  try {
    const res = await api("/api/admin/accounts/clean", { method: "POST" });
    alert(`Berhasil menghapus ${res.cleaned} akun expired.`);
    refresh();
  } catch (err) {
    alert("Gagal membersihkan: " + err.message);
  }
});

els.addBtn.addEventListener("click", async () => {
  const token = els.addToken.value.trim();
  if (!token) return alert("Token wajib diisi");
  try {
    await api("/api/admin/accounts", {
      method: "POST",
      body: JSON.stringify({ token, recipeId: els.addRecipe.value.trim(), label: els.addLabel.value.trim() }),
    });
    els.addToken.value = ""; els.addRecipe.value = ""; els.addLabel.value = "";
    refresh();
  } catch (err) { alert(err.message); }
});

els.bulkBtn.addEventListener("click", async () => {
  const lines = els.bulkText.value.split("\n").map((s) => s.trim()).filter(Boolean);
  if (!lines.length) return alert("Tidak ada baris");
  try {
    const result = await api("/api/admin/accounts/bulk", { method: "POST", body: JSON.stringify({ lines }) });
    let msg = `${result.added} akun berhasil ditambahkan`;
    if (result.errors?.length) {
      msg += `\n\n${result.errors.length} error:\n` + result.errors.map((e) => `- ${e.line}: ${e.error}`).join("\n");
    }
    alert(msg);
    els.bulkText.value = "";
    refresh();
  } catch (err) { alert(err.message); }
});

els.cancelEditBtn.addEventListener("click", () => { els.editForm.hidden = true; });

els.saveEditBtn.addEventListener("click", async () => {
  const id = els.editId.value;
  const patch = { recipeId: els.editRecipe.value.trim(), label: els.editLabel.value.trim() };
  const newToken = els.editToken.value.trim();
  if (newToken) patch.token = newToken;
  try {
    await api(`/api/admin/accounts/${id}`, { method: "PUT", body: JSON.stringify(patch) });
    els.editForm.hidden = true;
    refresh();
  } catch (err) { alert(err.message); }
});

// ─── Auto Token Bot ──────────────────────────────────────────────────────────

// Step keyword map: detects which step is active from log message
const STEP_KEYWORDS = [
  ["Step 1", "iCloud", "email", "Generate"],         // step 1
  ["Step 2", "Figma", "Daftar", "signup"],            // step 2
  ["Step 3", "verif", "inbox", "Refresh inbox"],      // step 3
  ["Step 4", "verif", "link"],                        // step 4
  ["Step 5", "weave", "Bearer", "Capture", "token"],  // step 5
];

function updateStepFromMsg(msg) {
  const lower = msg.toLowerCase();
  for (let i = 0; i < STEP_KEYWORDS.length; i++) {
    const keywords = STEP_KEYWORDS[i];
    if (keywords.some((k) => lower.includes(k.toLowerCase()))) {
      // Mark steps up to i as done, i as active, rest as idle
      for (let j = 1; j <= 5; j++) {
        const el = $(`bstep-${j}`);
        if (!el) continue;
        el.classList.remove("step-active", "step-done", "step-idle");
        if (j < i + 1) el.classList.add("step-done");
        else if (j === i + 1) el.classList.add("step-active");
        else el.classList.add("step-idle");
      }
      break;
    }
  }
}

function resetSteps(state = "idle") {
  for (let i = 1; i <= 5; i++) {
    const el = $(`bstep-${i}`);
    if (!el) continue;
    el.classList.remove("step-active", "step-done", "step-idle");
    if (state === "done") el.classList.add("step-done");
  }
}

function appendLog(msg, type = "info") {
  const body = els.logBody;
  // Remove placeholder
  const placeholder = body.querySelector(".log-info");
  if (placeholder && placeholder.textContent.includes("Menunggu")) placeholder.remove();

  const line = document.createElement("div");
  line.className = `log-line log-${type}`;
  line.textContent = msg;
  body.appendChild(line);
  // Keep max 200 lines
  while (body.children.length > 200) body.removeChild(body.firstChild);
  body.scrollTop = body.scrollHeight;
}

function setBotStatus(status) {
  const badge = els.botStatusBadge;
  badge.className = `badge badge-${status}`;
  const labels = { idle: "IDLE", running: "RUNNING", success: "SUCCESS", error: "ERROR" };
  badge.textContent = labels[status] || status.toUpperCase();
  
  if (status === "running") {
    els.botRunBtn.style.display = "none";
    if (els.botStopBtn) els.botStopBtn.style.display = "inline-block";
  } else {
    els.botRunBtn.style.display = "inline-block";
    els.botRunBtn.disabled = false;
    els.botRunBtn.textContent = "▶ Jalankan Sekarang";
    if (els.botStopBtn) els.botStopBtn.style.display = "none";
  }
}

function connectSse() {
  closeSse();
  const url = `/api/admin/auto-token/stream`;
  const headers = { "x-admin-password": adminPass };

  // EventSource doesn't support custom headers, use fetch with ReadableStream
  const ctrl = new AbortController();
  sseSource = ctrl;

  fetch(url, { headers, signal: ctrl.signal })
    .then(async (res) => {
      const reader = res.body.getReader();
      const decoder = new TextDecoder();
      let buffer = "";
      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        buffer += decoder.decode(value, { stream: true });
        const lines = buffer.split("\n");
        buffer = lines.pop();
        for (const line of lines) {
          if (line.startsWith("data: ")) {
            try {
              const event = JSON.parse(line.slice(6));
              handleSseEvent(event);
            } catch {}
          }
        }
      }
    })
    .catch((err) => {
      if (err.name !== "AbortError") {
        appendLog("❌ SSE disconnect: " + err.message, "error");
        // Reconnect after 5s
        setTimeout(() => { if (adminPass) connectSse(); }, 5000);
      }
    });
}

function closeSse() {
  if (sseSource) {
    sseSource.abort?.();
    sseSource = null;
  }
}

function handleSseEvent(event) {
  const { type, msg } = event;

  if (type === "connected") {
    appendLog(msg, "info");
    return;
  }
  if (type === "start") {
    setBotStatus("running");
    resetSteps("idle");
    appendLog(msg, "info");
    return;
  }
  if (type === "success") {
    setBotStatus("success");
    resetSteps("done");
    appendLog(msg, "success");
    refresh(); // Reload account list
    updateLastRun("success");
    return;
  }
  if (type === "error") {
    setBotStatus("error");
    appendLog(msg, "error");
    updateLastRun("error");
    return;
  }
  if (type === "warn") {
    appendLog(msg, "warn");
    return;
  }

  // Regular info log — also check for step keywords
  appendLog(msg, "info");
  updateStepFromMsg(msg);
}

function updateLastRun(status) {
  const now = new Date().toLocaleString("id-ID");
  els.botLastRun.hidden = false;
  els.botLastRunText.textContent = `${now} · ${status === "success" ? "✅ Berhasil" : "❌ Gagal"}`;
}

// ─── Bot controls ─────────────────────────────────────────────────────────────

els.botRunBtn.addEventListener("click", async () => {
  try {
    setBotStatus("running");
    appendLog("▶ Memulai bot secara manual...", "info");
    await api("/api/admin/auto-token/run", { method: "POST", body: JSON.stringify({ force: true }) });
  } catch (err) {
    appendLog(`❌ Gagal memulai bot: ${err.message}`, "error");
    setBotStatus("error");
  }
});

els.botStopBtn.addEventListener("click", async () => {
  try {
    els.botStopBtn.disabled = true;
    els.botStopBtn.textContent = "⏳ Menghentikan...";
    appendLog("🛑 Mengirim permintaan stop bot...", "warn");
    const res = await api("/api/admin/auto-token/stop", { method: "POST" });
    appendLog(`⏹️ Bot dihentikan: ${res.msg || "Selesai"}`, "warn");
    setBotStatus("idle");
  } catch (err) {
    appendLog(`❌ Gagal menghentikan bot: ${err.message}`, "error");
  } finally {
    els.botStopBtn.disabled = false;
    els.botStopBtn.textContent = "⏹️ Hentikan Bot";
  }
});

els.logClearBtn.addEventListener("click", () => {
  els.logBody.innerHTML = `<div class="log-line log-info">● Log dibersihkan.</div>`;
});

// Scheduler toggle
els.schedulerToggle.addEventListener("change", async () => {
  const enabled = els.schedulerToggle.checked;
  const mins = parseInt(els.schedulerInterval.value);
  try {
    const res = await api("/api/admin/auto-token/config", {
      method: "POST",
      body: JSON.stringify({ enabled, intervalMinutes: mins }),
    });
    appendLog(`⏰ Scheduler: ${res.msg}`, "info");
    if (enabled) {
      nextRunTime = Date.now() + mins * 60 * 1000;
      startCountdown();
      els.botCountdown.hidden = false;
    } else {
      stopCountdown();
      els.botCountdown.hidden = true;
    }
  } catch (err) {
    appendLog(`❌ Scheduler error: ${err.message}`, "error");
    els.schedulerToggle.checked = !enabled; // revert
  }
});

// Headless toggle
els.headlessToggle.addEventListener("change", async () => {
  const headless = els.headlessToggle.checked;
  try {
    const res = await api("/api/admin/auto-token/config", {
      method: "POST",
      body: JSON.stringify({ headless }),
    });
    appendLog(`⚙️ Mode Browser: ${headless ? "Sembunyikan" : "Tampilkan"} (Headless: ${headless})`, "info");
  } catch (err) {
    appendLog(`❌ Gagal mengubah mode browser: ${err.message}`, "error");
    els.headlessToggle.checked = !headless; // revert
  }
});

function startCountdown() {
  stopCountdown();
  countdownInterval = setInterval(() => {
    if (!nextRunTime) return;
    const diff = Math.max(0, nextRunTime - Date.now());
    const m = Math.floor(diff / 60000);
    const s = Math.floor((diff % 60000) / 1000);
    els.countdownTimer.textContent = `${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
    if (diff === 0) nextRunTime = null;
  }, 1000);
}

function stopCountdown() {
  if (countdownInterval) { clearInterval(countdownInterval); countdownInterval = null; }
}

async function loadBotStatus() {
  try {
    const st = await api("/api/admin/auto-token/status");
    els.schedulerToggle.checked = st.schedulerActive;
    els.headlessToggle.checked = st.headless;
    if (st.schedulerActive && st.nextRunAt) {
      nextRunTime = new Date(st.nextRunAt).getTime();
      startCountdown();
      els.botCountdown.hidden = false;
    }
    if (st.running) setBotStatus("running");
    if (st.lastRunAt) {
      const status = st.lastRunResult?.ok ? "success" : "error";
      updateLastRun(status);
    }
  } catch {}
}

// ─── Voucher management ──────────────────────────────────────────────────────

async function refreshVouchers() {
  const { vouchers } = await api("/api/admin/vouchers");
  renderVouchers(vouchers);
}

// Toggle custom duration days display
els.vchDuration.addEventListener("change", () => {
  const isCustom = els.vchDuration.value === "custom";
  els.vchDurationDaysWrapper.style.display = isCustom ? "flex" : "none";
});

function renderVouchers(vouchers) {
  if (!vouchers.length) {
    els.voucherList.innerHTML = `<div class="empty-accounts">Belum ada kode voucher VIP. Buat di atas.</div>`;
    return;
  }
  els.voucherList.innerHTML = "";
  const todayStr = new Date().toISOString().split("T")[0];

  for (const v of vouchers) {
    const row = document.createElement("div");
    row.className = "account-row";
    row.style.gridTemplateColumns = "1fr auto";

    const usageToday = v.usage?.[todayStr] || 0;
    const expTime = new Date(v.expiresAt).getTime() / 1000;
    const timeLeftStr = formatTimeLeft(expTime);
    const isExpired = expTime < Date.now() / 1000;

    row.innerHTML = `
      <div class="acc-info">
        <div class="acc-label" style="display: flex; align-items: center; gap: 8px;">
          <span>${escapeHtml(v.code)}</span>
          <span class="badge ${v.tier === 'pro' ? 'badge-running' : 'badge-idle'}" style="animation: none;">${v.tier.toUpperCase()}</span>
        </div>
        <div class="acc-meta" style="margin-top: 4px;">
          <span>WA: <strong>${escapeHtml(v.whatsapp || '-')}</strong></span>
          <span class="dot">·</span>
          <span>Generate Hari Ini: <strong>${usageToday}/${v.dailyLimit}</strong></span>
          <span class="dot">·</span>
          <span class="${isExpired ? 'exp-bad' : 'exp-ok'}">Aktif S/D: ${new Date(v.expiresAt).toLocaleDateString('id-ID')} (${timeLeftStr})</span>
        </div>
      </div>
      <div class="acc-actions">
        <button type="button" class="ghost small danger" onclick="deleteVoucher('${escapeHtml(v.code)}')">✕ Hapus</button>
      </div>
    `;
    els.voucherList.appendChild(row);
  }
}

els.createVchBtn.addEventListener("click", async () => {
  const code = els.vchCode.value.trim().toUpperCase();
  const tier = els.vchTier.value;
  const whatsapp = els.vchWhatsapp.value.trim();
  const duration = els.vchDuration.value;
  const durationDays = parseInt(els.vchDurationDays.value, 10);
  const dailyLimit = parseInt(els.vchDailyLimit.value, 10);

  if (!code && !whatsapp) {
    return alert("Silakan masukkan Kode Voucher ATAU Nomor Whatsapp Member!");
  }

  try {
    await api("/api/admin/vouchers", {
      method: "POST",
      body: JSON.stringify({ code, tier, whatsapp, duration, durationDays, dailyLimit }),
    });
    // Reset form
    els.vchCode.value = "";
    els.vchWhatsapp.value = "";
    els.vchDuration.value = "1bulan";
    els.vchDurationDays.value = "30";
    els.vchDurationDaysWrapper.style.display = "none";
    els.vchDailyLimit.value = "3";
    refreshVouchers().catch(() => {});
  } catch (err) {
    alert(err.message);
  }
});

window.deleteVoucher = async function(code) {
  if (!confirm(`Hapus voucher ${code}?`)) return;
  try {
    await api(`/api/admin/vouchers/${encodeURIComponent(code)}`, { method: "DELETE" });
    refreshVouchers().catch(() => {});
  } catch (err) {
    alert(err.message);
  }
};

// ─── Bootstrap ──────────────────────────────────────────────────────────────

(async function init() {
  const saved = sessionStorage.getItem(ADMIN_KEY);
  if (saved) {
    const ok = await tryLogin(saved);
    if (!ok) sessionStorage.removeItem(ADMIN_KEY);
  }
  setInterval(() => { if (!els.adminScreen.hidden) refresh(); }, 30_000);
})();
