from __future__ import annotations

BASE_JS = """
function mvpTokenGet() {
  return (localStorage.getItem("mvp_token") || "").trim();
}
function mvpTokenSet(v) {
  localStorage.setItem("mvp_token", (v || "").trim());
}
function mvpSftpPasswordGet() {
  return (localStorage.getItem("mvp_sftp_password") || "").trim();
}
function mvpSftpPasswordSet(v) {
  localStorage.setItem("mvp_sftp_password", (v || "").trim());
}
async function apiFetch(path, opts) {
  opts = opts || {};
  opts.headers = opts.headers || {};
  const tok = mvpTokenGet();
  if (tok) opts.headers["Authorization"] = "Bearer " + tok;
  return fetch(path, opts);
}
async function apiJson(path, opts) {
  const resp = await apiFetch(path, opts);
  const text = await resp.text();
  if (!resp.ok) {
    const err = new Error("HTTP " + resp.status);
    err.status = resp.status;
    err.body = text;
    throw err;
  }
  return JSON.parse(text);
}
function fmtJson(obj) {
  try { return JSON.stringify(obj, null, 2); } catch (e) { return String(obj); }
}
function curOriginWithPort(port) {
  const proto = window.location.protocol;
  const host = window.location.hostname;
  return proto + "//" + host + ":" + port;
}
async function copyText(v) {
  if (!v) return false;
  try {
    await navigator.clipboard.writeText(v);
    return true;
  } catch (e) {
    // Fallback for non-secure contexts (http) or older browsers.
    try {
      const ta = document.createElement("textarea");
      ta.value = v;
      ta.style.position = "fixed";
      ta.style.opacity = "0";
      document.body.appendChild(ta);
      ta.focus();
      ta.select();
      const ok = document.execCommand("copy");
      document.body.removeChild(ta);
      return ok;
    } catch (e2) {
      return false;
    }
  }
}
document.addEventListener("DOMContentLoaded", () => {
  const el = document.getElementById("nav-ray-dashboard");
  if (el) el.href = curOriginWithPort(8265);
});
""".strip()

