// panelbot/assets/app.js

// =========================
// Base URLs
// =========================
// Admin-panel: same-origin (Cloudflare Pages) -> gunakan path relatif /api/*
export const ADMIN_API_BASE = ""; // jangan diubah kecuali panel admin beda origin

// Panel-api (untuk bot realtime/report dsb). SESUAIKAN domainmu di sini.
export const PANEL_API_BASE = "https://panel-api.ttm-paneldepo.online";

// =========================
// Brand & URL utils
// =========================
export function brandDisplayName(brand) {
  const b = (brand || "").toLowerCase();
  if (b === "tiara") return "TIARATOTO";
  if (b === "ttm")   return "TOTOMANTAP";
  return "TOTOSAKTI"; // default (untuk tts dan fallback lama)
}

export function buildBrandUrl(br, pageKind, channel) {
  switch (pageKind) {
    case "global":
      return `global.html?brand=${br}`;
    case "brand":
      return `brand.html?brand=${br}`;
    case "profile-list":
      return `profile-list.html?brand=${br}`;
    case "profile-edit":
      return `profile-edit.html?brand=${br}&channel=${encodeURIComponent(channel || "")}`;
    default:
      return "index.html";
  }
}

export function getQueryParam(key) {
  const u = new URL(window.location.href);
  return u.searchParams.get(key);
}

// =========================
// Internal helpers
// =========================
async function safeJson(resp) {
  try { return await resp.json(); } catch { return {}; }
}

function synthesizeError(status, fallbackMsg = "Request failed") {
  return { ok: false, error: fallbackMsg, _httpStatus: status };
}

async function finalizeResponse(resp, fallbackMsg) {
  const data = await safeJson(resp);
  // Selalu sisipkan _httpStatus
  if (typeof data === "object" && data !== null) {
    data._httpStatus = resp.status;
  }
  // Jika HTTP OK, kembalikan apa adanya
  if (resp.ok) return data;

  // Jika server sudah kirim { ok:false, error:... } biarkan
  if (data && (data.ok === false) && (typeof data.error === "string")) return data;

  // Jika tidak ada struktur ok/error, buatkan sintetis
  const msg = (data && typeof data.error === "string" && data.error) || fallbackMsg || `HTTP ${resp.status}`;
  return synthesizeError(resp.status, msg);
}

function withTimeout(ms, signal) {
  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort("timeout"), ms);
  // jika ada signal luar, sinkronkan
  if (signal) {
    if (signal.aborted) controller.abort("upstream aborted");
    else signal.addEventListener("abort", () => controller.abort("upstream aborted"), { once: true });
  }
  return { signal: controller.signal, cancel: () => clearTimeout(timer) };
}

// =========================
// Fetch helpers (JSON-first, cookie include)
// - Tambahan: timeout default 20s + error sintetis
// =========================

/**
 * apiFetch — ke ADMIN panel (same-origin)
 * @param {string} path - ex: "/api/users"
 * @param {object} opts - fetch init + opsi custom:
 *   - json: object -> otomatis set content-type & stringify ke body
 *   - timeoutMs: number (default 20000)
 *
 * Contoh:
 *   await apiFetch("/api/users");
 *   await apiFetch("/api/users", { method:"POST", json: payload });
 *   await apiFetch("/api/users", { method:"POST", headers:{...}, body: JSON.stringify(payload) }); // tetap didukung
 */
export async function apiFetch(path, opts = {}) {
  const url = path.startsWith("http") ? path : `${ADMIN_API_BASE}${path}`;
  const { json, timeoutMs = 20000, signal, ...rest } = opts;

  const init = {
    credentials: "include",
    // mode default fetch sudah "cors" utk cross-origin, tapi same-origin juga aman
    ...rest,
  };

  if (json !== undefined) {
    init.method = init.method || "POST";
    init.headers = { ...(init.headers || {}), "content-type": "application/json" };
    init.body = JSON.stringify(json);
  }

  const t = withTimeout(timeoutMs, signal);
  try {
    const resp = await fetch(url, { ...init, signal: t.signal });
    return await finalizeResponse(resp, "Admin API request failed");
  } catch (e) {
    return synthesizeError(0, String(e && e.message ? e.message : e));
  } finally {
    t.cancel();
  }
}

export async function apiFetchAsUser(path, opts = {}) {
  // Ambil sesi untuk tahu username
  const s = await requireSession();
  const h = new Headers(opts.headers || {});
  if (s?.username && !h.has("x-panel-user")) {
    h.set("x-panel-user", s.username);
  }
  // Teruskan request ke apiFetch (JSON handling tetap jalan)
  return apiFetch(path, { ...opts, headers: h });
}

/**
 * panelApiFetch — ke PANEL-API (subdomain terpisah)
 * Cookie JWT (panel_token) akan otomatis ikut karena credentials: "include"
 * Opsi sama dengan apiFetch (json, timeoutMs, dst)
 */
export async function panelApiFetch(path, opts = {}) {
  const url = path.startsWith("http") ? path : `${PANEL_API_BASE}${path}`;
  const { json, timeoutMs = 20000, signal, ...rest } = opts;

  const init = {
    credentials: "include",
    cache: "no-store", // <- opsional tapi bagus untuk /api/*
    ...rest,
  };

  if (json !== undefined) {
    init.method = init.method || "POST";
    init.headers = { ...(init.headers || {}), "content-type": "application/json" };
    init.body = JSON.stringify(json);
  }

  const t = withTimeout(timeoutMs, signal);
  try {
    const resp = await fetch(url, { ...init, signal: t.signal });
    return await finalizeResponse(resp, "Panel API request failed");
  } catch (e) {
    return synthesizeError(0, String(e && e.message ? e.message : e));
  } finally {
    t.cancel();
  }
}

// =========================
/** Session guard */
// =========================
export async function requireSession() {
  const session = await apiFetch("/api/session");
  if (!session || session.ok === false) {
    // Jika worker mengembalikan 401 / ok:false -> redirect
    try { window.location = "login.html"; } catch {}
    throw new Error(session?.error || "unauthorized");
  }
  return session;
}

// =========================
// Navbar helper (lama, tetap disediakan untuk kompatibilitas)
// =========================
export function attachNavbar({ username, brand, pageKind, channel }) {
  const nav = document.getElementById("navbar");
  if (!nav) return;

  const brandSwitcherHtml = brand
    ? `
      <div class="flex flex-col">
        <label class="text-[11px] font-medium text-slate-400 uppercase tracking-wide mb-1">Brand aktif</label>
        <select class="bg-slate-100 border border-slate-300 rounded-md text-[13px] font-medium text-slate-800 px-2 py-2"
          id="brandSwitcherSel">
          <option value="${buildBrandUrl("tiara", pageKind, channel)}" ${brand === "tiara" ? "selected" : ""}>TIARATOTO</option>
          <option value="${buildBrandUrl("tts", pageKind, channel)}" ${brand === "tts" ? "selected" : ""}>TOTOSAKTI</option>
          <option value="${buildBrandUrl("ttm", pageKind, channel)}" ${brand === "ttm" ? "selected" : ""}>TOTOMANTAP</option>
        </select>
      </div>
    `
    : "";

  nav.innerHTML = `
    <div class="w-full bg-white border-b border-slate-200 shadow-md px-4 py-3 flex flex-wrap justify-between items-start gap-4">
      <div class="flex flex-wrap items-start gap-4">
        <a class="flex items-center gap-2 text-[14px] font-medium text-slate-900" href="index.html">
          <div class="w-7 h-7 rounded-lg bg-gradient-to-br from-blue-400 to-blue-900 text-white text-[11px] font-semibold flex items-center justify-center shadow-lg">CFG</div>
          <div class="flex flex-col leading-tight">
            <span class="text-[13px] font-semibold text-slate-900">Bot Config Panel</span>
            <span class="text-[12px] text-slate-500 font-normal">Dashboard Admin</span>
          </div>
        </a>
        ${brandSwitcherHtml}
      </div>
      <div>
        <button id="logoutBtn"
          class="flex items-center gap-2 text-[12px] font-medium text-red-600 bg-red-50 border border-red-200 rounded-md px-3 py-2">
          <svg xmlns="http://www.w3.org/2000/svg" width="15" height="15" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" viewBox="0 0 24 24"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg>
          <span>Logout (<span id="navUsername">${username || "admin"}</span>)</span>
        </button>
      </div>
    </div>
  `;

  const sel = document.getElementById("brandSwitcherSel");
  if (sel) sel.addEventListener("change", (e) => {
    const v = e.target.value;
    if (v) window.location = v;
  });

  const logoutBtn = document.getElementById("logoutBtn");
  if (logoutBtn) {
    logoutBtn.addEventListener("click", async () => {
      await apiFetch("/api/logout", { method: "POST" });
      window.location = "login.html";
    });
  }
}

// =========================
// Flash helper
// =========================
export function showFlash(type, text) {
  const box = document.getElementById("flashBox");
  if (!box) return;
  if (!text) {
    box.innerHTML = "";
    return;
  }
  const base =
    type === "err"
      ? "bg-red-50 border border-red-300 text-red-600"
      : "bg-green-50 border border-green-300 text-green-600";
  box.innerHTML = `
    <div class="${base} rounded-md px-3 py-2 text-[13px] font-medium leading-[1.4] mb-4">
      ${text}
    </div>
  `;
}

