// Prism Translate — workstation / options logic.
import {
  LANGS, PROVIDER_TYPES, PRICE_TABLE,
  langName, newProvider, newPrompt,
} from "../lib/storage.js";
import { mountBrand } from "../lib/brand.js";

const $ = (s, r = document) => r.querySelector(s);
const $$ = (s, r = document) => Array.from(r.querySelectorAll(s));
const fmt = (n) => Number(n || 0).toLocaleString("en-US");

function sendBg(msg) {
  return new Promise((resolve) =>
    chrome.runtime.sendMessage(msg, (r) => {
      if (chrome.runtime.lastError) resolve({ ok: false, error: chrome.runtime.lastError.message });
      else resolve(r || { ok: false, error: "无响应" });
    })
  );
}

let state = { settings: {}, providers: [], prompts: [], glossary: [], usage: {} };
let wsSelected = new Set();

function toast(msg, kind = "") {
  const el = document.createElement("div");
  el.className = "toast " + kind;
  el.textContent = msg;
  $("#toast-host").appendChild(el);
  setTimeout(() => el.remove(), 2600);
}

function fillLangSelect(sel, value, includeAuto) {
  sel.innerHTML = "";
  LANGS.filter((l) => includeAuto || l.code !== "auto").forEach((l) => {
    const o = document.createElement("option");
    o.value = l.code; o.textContent = l.name;
    if (l.code === value) o.selected = true;
    sel.appendChild(o);
  });
}

function priceFor(model, inT, outT) {
  const p = PRICE_TABLE[model];
  if (!p) return null;
  return (inT / 1e6) * p[0] + (outT / 1e6) * p[1];
}

// ---------------- init ----------------
async function init() {
  const r = await sendBg({ cmd: "getState" });
  if (r.ok) state = { settings: r.settings, providers: r.providers, prompts: r.prompts, glossary: r.glossary, usage: r.usage };
  document.body.setAttribute("data-theme", state.settings.theme || "dark");

  mountBrand();
  setupNav();
  renderWorkstation();
  renderProviders();
  renderPrompts();
  renderGlossary();
  renderUsage();
  renderSettings();

  $("#theme").addEventListener("click", toggleTheme);

  // open to hash tab if present
  const tab = (location.hash || "").replace("#", "");
  if (tab) switchTab(tab);
}

function setupNav() {
  $$(".nav-item").forEach((b) =>
    b.addEventListener("click", () => switchTab(b.dataset.tab))
  );
}
function switchTab(tab) {
  $$(".nav-item").forEach((b) => b.classList.toggle("active", b.dataset.tab === tab));
  $$(".tab").forEach((s) => s.classList.toggle("hidden", s.id !== "tab-" + tab));
  if (tab === "usage") renderUsage();
}

async function toggleTheme() {
  const next = state.settings.theme === "light" ? "dark" : "light";
  state.settings.theme = next;
  document.body.setAttribute("data-theme", next);
  await sendBg({ cmd: "saveSettings", settings: state.settings });
}

// ================= WORKSTATION =================
function renderWorkstation() {
  fillLangSelect($("#ws-source"), state.settings.sourceLang || "auto", true);
  fillLangSelect($("#ws-target"), state.settings.targetLang || "zh-CN", false);
  const sc = $("#ws-scenario");
  sc.innerHTML = "";
  state.prompts.forEach((p) => {
    const o = document.createElement("option");
    o.value = p.id; o.textContent = p.name; if (p.id === state.settings.scenario) o.selected = true;
    sc.appendChild(o);
  });

  // provider chips
  wsSelected = new Set(state.providers.filter((p) => p.enabled && p.apiKey).map((p) => p.id));
  renderWsChips();

  $("#ws-swap").onclick = () => {
    const s = $("#ws-source").value, t = $("#ws-target").value;
    if (s === "auto") { toast("源语言为自动检测，无法交换", "err"); return; }
    $("#ws-source").value = t; $("#ws-target").value = s;
  };
  $("#ws-input").addEventListener("input", (e) => {
    $("#ws-charcount").textContent = e.target.value.length + " 字符";
  });
  $("#ws-clear").onclick = () => { $("#ws-input").value = ""; $("#ws-charcount").textContent = "0 字符"; $("#ws-results").innerHTML = ""; };
  $("#ws-run").onclick = runCompare;
  $("#ws-input").addEventListener("keydown", (e) => {
    if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) { e.preventDefault(); runCompare(); }
  });
}

function renderWsChips() {
  const host = $("#ws-provider-chips");
  host.innerHTML = "";
  if (!state.providers.length) {
    host.innerHTML = '<span class="muted">请先在「服务商」页添加翻译服务</span>';
    return;
  }
  state.providers.forEach((p) => {
    const chip = document.createElement("div");
    const usable = p.enabled && p.apiKey;
    chip.className = "chip" + (wsSelected.has(p.id) ? " on" : "") + (usable ? "" : " disabled");
    chip.innerHTML = `<span class="dot"></span>${escapeHtml(p.name)} · ${escapeHtml(p.model)}`;
    if (usable) {
      chip.onclick = () => {
        if (wsSelected.has(p.id)) wsSelected.delete(p.id);
        else wsSelected.add(p.id);
        chip.classList.toggle("on");
      };
    } else {
      chip.title = p.enabled ? "未填写 API Key" : "已停用";
    }
    host.appendChild(chip);
  });
}

async function runCompare() {
  const text = $("#ws-input").value.trim();
  if (!text) { toast("请输入要翻译的文本", "err"); return; }
  const ids = [...wsSelected];
  if (!ids.length) { toast("请至少选择一个翻译服务", "err"); return; }

  const target = $("#ws-target").value;
  const source = $("#ws-source").value;
  const scenario = $("#ws-scenario").value;

  const host = $("#ws-results");
  host.innerHTML = "";
  const cards = {};
  ids.forEach((id) => {
    const p = state.providers.find((x) => x.id === id);
    const card = document.createElement("div");
    card.className = "result-card";
    card.innerHTML =
      `<div class="rc-head"><span class="name">${escapeHtml(p.name)}</span><span class="model">${escapeHtml(p.model)}</span></div>` +
      `<div class="rc-body loading">翻译中…</div>` +
      `<div class="rc-meta"></div>`;
    host.appendChild(card);
    cards[id] = card;
  });

  $("#ws-run").disabled = true;
  const timings = [];
  await Promise.all(
    ids.map(async (id) => {
      const r = await sendBg({ cmd: "compare", text, providerIds: [id], targetLang: target, sourceLang: source, scenario });
      const res = r.ok && r.results && r.results[0] ? r.results[0] : { error: r.error || "失败" };
      const card = cards[id];
      const body = $(".rc-body", card);
      const meta = $(".rc-meta", card);
      if (res.error) {
        body.className = "rc-body error";
        body.textContent = "⚠ " + res.error;
      } else {
        body.className = "rc-body";
        body.textContent = res.text;
        const cost = priceFor(res.model, res.inputTokens, res.outputTokens);
        timings.push({ id, ms: res.ms });
        meta.innerHTML =
          `<span>延迟 <b>${fmt(res.ms)}ms</b></span>` +
          `<span>Tokens <b>${fmt((res.inputTokens || 0) + (res.outputTokens || 0))}</b></span>` +
          `<span>成本 <b>${cost == null ? "—" : "$" + cost.toFixed(5)}</b></span>` +
          `<span class="copy">复制</span>`;
        $(".copy", meta).onclick = () => navigator.clipboard.writeText(res.text).then(() => toast("已复制译文", "ok"));
      }
    })
  );
  // mark fastest
  if (timings.length > 1) {
    const fastest = timings.reduce((a, b) => (a.ms <= b.ms ? a : b));
    const card = cards[fastest.id];
    card.classList.add("best");
    const head = $(".rc-head", card);
    const badge = document.createElement("span");
    badge.className = "badge-best";
    badge.textContent = "最快";
    head.appendChild(badge);
  }
  $("#ws-run").disabled = false;
  // refresh usage silently
  const u = await sendBg({ cmd: "getState" });
  if (u.ok) state.usage = u.usage;
}

// ================= PROVIDERS =================
function renderProviders() {
  const typeSel = $("#prov-type");
  typeSel.innerHTML = "";
  Object.entries(PROVIDER_TYPES).forEach(([k, v]) => {
    const o = document.createElement("option");
    o.value = k; o.textContent = v.label; typeSel.appendChild(o);
  });
  $("#prov-add").onclick = () => {
    state.providers.push(newProvider(typeSel.value));
    persistProviders();
    renderProviders(); renderWsChips();
  };

  const list = $("#prov-list");
  list.innerHTML = "";
  if (!state.providers.length) {
    list.innerHTML = '<div class="empty">还没有任何服务商。从上方选择类型并添加，例如 OpenAI 兼容端点。</div>';
    return;
  }
  state.providers.forEach((p) => list.appendChild(providerCard(p)));
}

function providerCard(p) {
  const t = PROVIDER_TYPES[p.type] || {};
  const card = document.createElement("div");
  card.className = "prov-card" + (p.enabled ? "" : " disabled");
  card.innerHTML = `
    <div class="prov-top">
      <span class="ptype">${escapeHtml(t.label || p.type)}</span>
      <input class="pname" value="${escapeAttr(p.name)}" />
      <label class="switch" title="启用/停用">
        <input type="checkbox" class="p-enabled" ${p.enabled ? "checked" : ""}/>
        <span class="track"></span>
      </label>
    </div>
    <div class="prov-grid">
      <div class="prov-field full"><label>API 端点 (Base URL)</label><input type="text" class="p-base" value="${escapeAttr(p.baseURL)}" placeholder="${escapeAttr(t.defaultBase || "")}"/></div>
      <div class="prov-field full"><label>API Key</label>
        <div class="key-wrap">
          <input type="password" class="p-key" value="${escapeAttr(p.apiKey)}" placeholder="sk-..." autocomplete="off"/>
          <button class="p-eye" type="button">显示</button>
        </div>
      </div>
      <div class="prov-field"><label>模型</label><input type="text" class="p-model" value="${escapeAttr(p.model)}" placeholder="${escapeAttr(t.defaultModel || "")}"/></div>
      <div class="prov-field"><label>温度 (0–1)</label><input type="number" class="p-temp" min="0" max="2" step="0.1" value="${p.temperature ?? 0.2}"/></div>
    </div>
    <div class="prov-note muted" style="margin-top:10px;font-size:12px">${t.note || ""}</div>
    <div class="prov-actions">
      <button class="ghost p-test">测试连接</button>
      <span class="test-result"></span>
      <div class="spacer"></div>
      <button class="ghost p-default">${state.settings.defaultProvider === p.id ? "✓ 默认服务" : "设为默认"}</button>
      <button class="ghost danger p-del">删除</button>
    </div>`;

  const get = (s) => $(s, card);
  const save = () => persistProviders();

  get(".pname").addEventListener("input", (e) => { p.name = e.target.value; save(); renderWsChips(); });
  get(".p-base").addEventListener("input", (e) => { p.baseURL = e.target.value.trim(); save(); });
  get(".p-key").addEventListener("input", (e) => { p.apiKey = e.target.value.trim(); save(); renderWsChips(); });
  get(".p-model").addEventListener("input", (e) => { p.model = e.target.value.trim(); save(); renderWsChips(); });
  get(".p-temp").addEventListener("input", (e) => { p.temperature = parseFloat(e.target.value); save(); });
  get(".p-enabled").addEventListener("change", (e) => { p.enabled = e.target.checked; save(); card.classList.toggle("disabled", !p.enabled); renderWsChips(); });
  get(".p-eye").addEventListener("click", () => {
    const k = get(".p-key");
    const show = k.type === "password";
    k.type = show ? "text" : "password";
    get(".p-eye").textContent = show ? "隐藏" : "显示";
  });
  get(".p-default").addEventListener("click", async () => {
    state.settings.defaultProvider = p.id;
    await sendBg({ cmd: "saveSettings", settings: state.settings });
    renderProviders();
    toast("已设为默认服务", "ok");
  });
  get(".p-del").addEventListener("click", () => {
    if (!confirm(`删除服务商「${p.name}」？`)) return;
    state.providers = state.providers.filter((x) => x.id !== p.id);
    if (state.settings.defaultProvider === p.id) state.settings.defaultProvider = "";
    persistProviders();
    sendBg({ cmd: "saveSettings", settings: state.settings });
    renderProviders(); renderWsChips();
  });
  get(".p-test").addEventListener("click", async () => {
    const rr = get(".test-result");
    rr.className = "test-result"; rr.textContent = "测试中…";
    const r = await sendBg({ cmd: "testProvider", provider: p });
    if (r.ok) { rr.className = "test-result ok"; rr.textContent = `✓ 连接成功 · ${r.ms}ms · 译例「${(r.sample || "").slice(0, 16)}」`; }
    else { rr.className = "test-result err"; rr.textContent = "✗ " + r.error; }
  });
  return card;
}

async function persistProviders() {
  await sendBg({ cmd: "saveProviders", providers: state.providers });
}

// ================= PROMPTS =================
function renderPrompts() {
  $("#prompt-add").onclick = () => {
    state.prompts.push(newPrompt());
    persistPrompts(); renderPrompts(); renderWorkstation();
  };
  const list = $("#prompt-list");
  list.innerHTML = "";
  state.prompts.forEach((p) => list.appendChild(promptCard(p)));
}

function promptCard(p) {
  const card = document.createElement("div");
  card.className = "prompt-card" + (p.builtin ? " builtin" : "");
  card.innerHTML = `
    <div class="prompt-top">
      <input class="pname" value="${escapeAttr(p.name)}" ${p.builtin ? "readonly" : ""}/>
      ${p.builtin ? '<span class="builtin-tag">内置</span>' : '<button class="ghost danger pp-del">删除</button>'}
    </div>
    <textarea class="pp-sys" ${p.builtin ? "readonly" : ""}>${escapeHtml(p.system)}</textarea>`;
  if (!p.builtin) {
    $(".pname", card).addEventListener("input", (e) => { p.name = e.target.value; persistPrompts(); renderWorkstation(); });
    $(".pp-sys", card).addEventListener("input", (e) => { p.system = e.target.value; persistPrompts(); });
    $(".pp-del", card).addEventListener("click", () => {
      if (!confirm(`删除专家「${p.name}」？`)) return;
      state.prompts = state.prompts.filter((x) => x.id !== p.id);
      persistPrompts(); renderPrompts(); renderWorkstation();
    });
  }
  return card;
}
async function persistPrompts() {
  await sendBg({ cmd: "savePrompts", prompts: state.prompts });
}

// ================= GLOSSARY =================
function renderGlossary() {
  $("#gloss-add").onclick = () => { state.glossary.push({ src: "", dst: "", note: "" }); persistGlossary(); renderGlossary(); };
  $("#gloss-export").onclick = exportGlossary;
  $("#gloss-import").onclick = () => $("#gloss-file").click();
  $("#gloss-file").onchange = importGlossary;

  const body = $("#gloss-body");
  body.innerHTML = "";
  if (!state.glossary.length) {
    body.innerHTML = '<tr><td colspan="4" class="muted" style="padding:24px;text-align:center">暂无术语，点击「添加术语」开始。</td></tr>';
    return;
  }
  state.glossary.forEach((g, i) => {
    const tr = document.createElement("tr");
    tr.innerHTML =
      `<td><input type="text" value="${escapeAttr(g.src)}" placeholder="原文术语"/></td>` +
      `<td><input type="text" value="${escapeAttr(g.dst)}" placeholder="指定译文"/></td>` +
      `<td><input type="text" value="${escapeAttr(g.note || "")}" placeholder="备注（可选）"/></td>` +
      `<td><button class="del">×</button></td>`;
    const ins = tr.querySelectorAll("input");
    ins[0].addEventListener("input", (e) => { state.glossary[i].src = e.target.value; persistGlossary(); });
    ins[1].addEventListener("input", (e) => { state.glossary[i].dst = e.target.value; persistGlossary(); });
    ins[2].addEventListener("input", (e) => { state.glossary[i].note = e.target.value; persistGlossary(); });
    tr.querySelector(".del").addEventListener("click", () => { state.glossary.splice(i, 1); persistGlossary(); renderGlossary(); });
    body.appendChild(tr);
  });
}
async function persistGlossary() { await sendBg({ cmd: "saveGlossary", glossary: state.glossary }); }
function exportGlossary() {
  const blob = new Blob([JSON.stringify(state.glossary, null, 2)], { type: "application/json" });
  const a = document.createElement("a");
  a.href = URL.createObjectURL(blob);
  a.download = "prism-glossary.json";
  a.click();
  URL.revokeObjectURL(a.href);
}
function importGlossary(e) {
  const file = e.target.files[0];
  if (!file) return;
  const reader = new FileReader();
  reader.onload = () => {
    try {
      const data = JSON.parse(reader.result);
      if (!Array.isArray(data)) throw new Error("格式应为数组");
      state.glossary = data.filter((x) => x && x.src).map((x) => ({ src: String(x.src), dst: String(x.dst || ""), note: String(x.note || "") }));
      persistGlossary(); renderGlossary();
      toast(`已导入 ${state.glossary.length} 条术语`, "ok");
    } catch (err) { toast("导入失败：" + err.message, "err"); }
  };
  reader.readAsText(file);
  e.target.value = "";
}

// ================= USAGE =================
async function renderUsage() {
  const r = await sendBg({ cmd: "getState" });
  if (r.ok) state.usage = r.usage;
  const u = state.usage || {};
  let req = 0, inT = 0, outT = 0, cost = 0;
  Object.values(u).forEach((x) => { req += x.requests || 0; inT += x.inputTokens || 0; outT += x.outputTokens || 0; cost += x.cost || 0; });

  $("#usage-cards").innerHTML =
    ucard("总请求数", fmt(req)) +
    ucard("输入 Tokens", fmt(inT)) +
    ucard("输出 Tokens", fmt(outT)) +
    ucard("预估总成本", "$" + cost.toFixed(cost < 1 ? 4 : 2));

  const body = $("#usage-body");
  body.innerHTML = "";
  const entries = Object.entries(u);
  if (!entries.length) {
    body.innerHTML = '<tr><td colspan="6" class="muted" style="padding:24px;text-align:center">还没有任何用量记录。</td></tr>';
  } else {
    entries.forEach(([id, x]) => {
      const p = state.providers.find((pp) => pp.id === id);
      const tr = document.createElement("tr");
      tr.innerHTML =
        `<td>${p ? escapeHtml(p.name) : "（已删除）"}</td>` +
        `<td>${escapeHtml(x.model || "")}</td>` +
        `<td class="num">${fmt(x.requests)}</td>` +
        `<td class="num">${fmt(x.inputTokens)}</td>` +
        `<td class="num">${fmt(x.outputTokens)}</td>` +
        `<td class="num">$${(x.cost || 0).toFixed(5)}</td>`;
      body.appendChild(tr);
    });
  }
  $("#usage-reset").onclick = async () => {
    if (!confirm("确认清空所有用量统计？")) return;
    await sendBg({ cmd: "resetUsage" });
    state.usage = {};
    renderUsage();
  };
}
function ucard(label, val) {
  return `<div class="ucard"><div class="label">${label}</div><div class="val">${val}</div></div>`;
}

// ================= SETTINGS =================
function renderSettings() {
  fillLangSelect($("#set-target"), state.settings.targetLang, false);
  fillLangSelect($("#set-source"), state.settings.sourceLang, true);
  const ps = $("#set-provider");
  ps.innerHTML = '<option value="">（自动选第一个可用）</option>';
  state.providers.forEach((p) => {
    const o = document.createElement("option");
    o.value = p.id; o.textContent = `${p.name} · ${p.model}`;
    if (p.id === state.settings.defaultProvider) o.selected = true;
    ps.appendChild(o);
  });
  const sc = $("#set-scenario");
  sc.innerHTML = "";
  state.prompts.forEach((p) => {
    const o = document.createElement("option");
    o.value = p.id; o.textContent = p.name; if (p.id === state.settings.scenario) o.selected = true;
    sc.appendChild(o);
  });
  $("#set-style").value = state.settings.displayStyle;
  $("#set-trigger").value = state.settings.triggerMode;
  $("#set-batch").value = state.settings.batchSize;
  $("#set-concurrency").value = state.settings.concurrency;
  $("#set-cache").checked = state.settings.enableCache;
  $("#set-bubble").checked = state.settings.selectionBubble;
  $("#set-videosubs").checked = state.settings.videoSubs !== false;

  const bind = (sel, key, parse = (v) => v) =>
    $(sel).addEventListener("change", (e) => {
      const v = e.target.type === "checkbox" ? e.target.checked : parse(e.target.value);
      state.settings[key] = v;
      saveSettings();
    });
  bind("#set-target", "targetLang");
  bind("#set-source", "sourceLang");
  bind("#set-provider", "defaultProvider");
  bind("#set-scenario", "scenario");
  bind("#set-style", "displayStyle");
  bind("#set-trigger", "triggerMode");
  bind("#set-batch", "batchSize", (v) => Math.max(1, Math.min(30, parseInt(v) || 8)));
  bind("#set-concurrency", "concurrency", (v) => Math.max(1, Math.min(12, parseInt(v) || 4)));
  bind("#set-cache", "enableCache");
  bind("#set-bubble", "selectionBubble");
  bind("#set-videosubs", "videoSubs");
}
async function saveSettings() {
  await sendBg({ cmd: "saveSettings", settings: state.settings });
  const h = $("#saved-hint");
  h.classList.add("show");
  setTimeout(() => h.classList.remove("show"), 1400);
  // keep ws + other tabs consistent with default changes
  renderWorkstation();
}

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

init();
