/* 采集节点客户端的界面逻辑。
 *
 * 没有框架，也不需要——整个界面就是「一秒拉一次状态，重画三块区域」。
 * 引一个框架进来只会让打包变大、让 webview 里多一层要排查的东西。
 *
 * 状态是拉的不是推的：推需要 Python 跨线程调 evaluate_js，两个平台上的
 * 时序表现不一样，出问题极难查。拉一个小字典的代价可以忽略。
 */

const POLL_MS = 1000;

const $ = (id) => document.getElementById(id);

const views = {
  setup: $("setup-view"),
  dashboard: $("dashboard-view"),
  settings: $("settings-view"),
};

let current = null; // 最近一次状态，供设置页读取
let showingSettings = false;

function show(name) {
  for (const [key, node] of Object.entries(views)) {
    node.classList.toggle("hidden", key !== name);
  }
  $("settings-btn").classList.toggle("hidden", name !== "dashboard");
}

/* ---------- 渲染 ---------- */

const DOT_BY_CONNECTION = {
  idle: "",
  connecting: "warn",
  online: "ok",
  error: "err",
};

function renderStatus(state) {
  const busy = state.devices.some((d) => d.state === "busy");
  const cls = busy ? "busy" : DOT_BY_CONNECTION[state.connection] ?? "";
  $("status-dot").className = `dot ${cls}`;
  $("headline").textContent = state.headline;

  const bits = [];
  if (state.connection === "online" || busy) bits.push(`已连接 ${state.server}`);
  else if (state.last_error) bits.push(state.last_error);
  else bits.push(state.server);
  if (state.completed_today > 0) bits.push(`今天已完成 ${state.completed_today} 次`);
  $("status-sub").textContent = bits.join(" · ");
}

function renderDevices(state) {
  const container = $("devices");
  const usable = state.devices.filter((d) => d.state === "idle" || d.state === "busy").length;
  const skipped = state.devices.filter((d) => d.state === "skipped").length;

  $("device-count").textContent = state.devices.length
    ? `${usable} 台可用${skipped ? ` · ${skipped} 台跳过` : ""}`
    : "0 台";

  if (!state.devices.length) {
    // 空状态要负责教学：这个窗口是客户唯一的自助界面
    container.innerHTML = `
      <div class="empty">
        <b>没检测到手机</b>
        用 USB 连上安卓手机，并在手机上允许「USB 调试」授权。<br />
        模拟器和云手机采不到价格，会被自动跳过。
      </div>`;
    return;
  }

  container.innerHTML = state.devices
    .map((d) => {
      const stateLabel = {
        busy: '<i class="dot busy"></i>采集中',
        idle: (d.problems || []).length
          ? '<i class="dot warn"></i>待处理'
          : '<i class="dot ok"></i>空闲',
        offline: "未授权",
        skipped: "已跳过",
      }[d.state];

      const detail = d.detail ? `<div class="device-task">${escapeHtml(d.detail)}</div>` : "";
      // 缺 App / 缺输入法要在这里就说清楚——客户第一眼是在这个窗口看到手机的
      // 装了彩色、没装灰度。三态：true/false/null（没探测到）——
      // null 画成"没装"会让客户白跑一趟去装已经装好的东西
      const appIcon = (src, name, installed) => {
        const state = installed === null || installed === undefined
          ? "unknown"
          : installed ? "on" : "off";
        const title = state === "unknown"
          ? `${name}：未检测到`
          : installed ? `${name}：已安装` : `${name}：未安装`;
        return `<span class="app-icon app-icon-${state}" title="${escapeHtml(title)}">` +
               `<img src="./app-icons/${src}" alt="${escapeHtml(name)}" width="18" height="18"></span>`;
      };
      const apps =
        d.state === "offline"
          ? ""
          : `<div class="app-icons">
               ${appIcon("target-app-64.png", "目标 App", d.has_target_app)}
               ${appIcon("adbkeyboard-64.png", "ADBKeyboard", d.has_ime)}
               ${d.has_ime && d.ime_enabled === false ? '<i class="app-icon-warn"></i>' : ""}
             </div>`;

      const problems = (d.problems || []).length
        ? `<div class="device-problem">${d.problems.map(escapeHtml).join(" · ")}</div>`
        : "";
      // 缺什么给什么操作：没启用能一键修，没装只能给指引
      const action =
        d.fixable === "ime_disabled"
          ? `<button class="device-fix" data-serial="${escapeHtml(d.serial)}">启用输入法</button>`
          : d.fixable === "ime_missing"
            ? `<button class="device-fix" data-hint="1">怎么安装</button>`
            : "";
      const serial =
        d.state === "idle" ? `<div class="device-serial">${escapeHtml(d.serial)}</div>` : "";
      const bar =
        d.progress !== null && d.progress !== undefined
          ? `<div class="bar"><i style="width:${Math.round(d.progress * 100)}%"></i></div>`
          : "";

      return `
        <div class="device ${d.state === "busy" ? "active" : ""} ${
          d.state === "skipped" || d.state === "offline" ? "skipped" : ""
        }">
          <div class="device-top">
            <span class="device-name">${escapeHtml(d.label)}</span>
            <span class="device-state">${stateLabel}</span>
          </div>
          ${apps}${detail}${problems}${action}${serial}${bar}
        </div>`;
    })
    .join("");
}

function renderFeed(state) {
  const feed = $("feed");
  if (!state.events.length) {
    feed.innerHTML = '<div class="event"><span class="msg">还没有活动记录。</span></div>';
    return;
  }
  feed.innerHTML = state.events
    .map(
      (e) =>
        `<div class="event ${e.level}"><time>${escapeHtml(e.at)}</time>` +
        `<span class="msg">${escapeHtml(e.message)}</span></div>`,
    )
    .join("");
}

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

/* ---------- 轮询 ---------- */

async function refresh() {
  let state;
  try {
    state = await window.pywebview.api.get_state();
  } catch {
    return; // 窗口正在关闭时会拿不到，忽略
  }
  current = state;

  $("version").textContent = state.version;
  $("default-server").textContent = `默认连接 ${hostOf(state.default_server)}`;

  if (showingSettings) {
    $("settings-server").textContent = `已连接 ${state.server}`;
    $("pause-btn").textContent = state.connection === "idle" ? "继续采集" : "暂停采集";
    show("settings");
    return;
  }

  if (!state.configured) {
    if (state.setup_error) setHint(state.setup_error, "bad");
    show("setup");
    return;
  }

  show("dashboard");
  renderStatus(state);
  renderDevices(state);
  renderFeed(state);
}

function hostOf(url) {
  try {
    return new URL(url).host;
  } catch {
    return url;
  }
}

function setHint(text, kind) {
  const node = $("token-hint");
  node.textContent = text;
  node.className = `hint${kind ? ` ${kind}` : ""}`;
}

/* ---------- 交互 ---------- */

$("token").addEventListener("input", async (event) => {
  const raw = event.target.value;
  // 后台把整条命令拼好了，直接粘进来最省事——识别到就自动拆开
  if (raw.includes("--token") || raw.includes("--server")) {
    const parsed = await window.pywebview.api.parse_command(raw);
    if (parsed.token) {
      event.target.value = parsed.token;
      if (parsed.server) {
        $("server").value = parsed.server;
        $("server-field").classList.remove("hidden");
      }
      setHint("已从命令中识别出令牌", "good");
      return;
    }
  }
  const value = raw.trim();
  if (!value) setHint("", "");
  else if (value.startsWith("bnra_")) setHint("格式正确", "good");
  else setHint("令牌应该以 bnra_ 开头", "bad");
});

$("toggle-server").addEventListener("click", () => {
  $("server-field").classList.toggle("hidden");
});

$("connect-btn").addEventListener("click", async () => {
  const btn = $("connect-btn");
  btn.disabled = true;
  btn.textContent = "连接中…";
  const result = await window.pywebview.api.connect($("token").value, $("server").value);
  btn.disabled = false;
  btn.textContent = "连接";
  if (!result.ok) setHint(result.error, "bad");
  else await refresh();
});

$("settings-btn").addEventListener("click", () => {
  showingSettings = true;
  refresh();
});

$("back-btn").addEventListener("click", () => {
  showingSettings = false;
  refresh();
});

$("pause-btn").addEventListener("click", async () => {
  if (current && current.connection === "idle") {
    await window.pywebview.api.resume();
  } else {
    await window.pywebview.api.disconnect();
  }
  refresh();
});

$("dir-btn").addEventListener("click", () => window.pywebview.api.open_data_dir());
$("open-dir").addEventListener("click", () => window.pywebview.api.open_data_dir());

$("forget-btn").addEventListener("click", async () => {
  await window.pywebview.api.forget();
  showingSettings = false;
  $("token").value = "";
  setHint("", "");
  refresh();
});

// 设备卡片上的修复按钮。用事件委托——卡片每秒重画一次，
// 直接绑在按钮上的监听会跟着被丢掉。
$("devices").addEventListener("click", async (event) => {
  const btn = event.target.closest(".device-fix");
  if (!btn) return;

  if (btn.dataset.hint) {
    const hint = await window.pywebview.api.install_hint();
    if (confirm(`${hint.text}\n\n现在打开下载页面？`)) {
      window.pywebview.api.open_url(hint.url);
    }
    return;
  }

  btn.disabled = true;
  btn.textContent = "处理中…";
  const result = await window.pywebview.api.enable_ime(btn.dataset.serial);
  if (!result.ok) alert(result.error);
  // 下一次轮询会重画卡片，成功的话按钮自然消失
  refresh();
});

window.addEventListener("pywebviewready", () => {
  refresh();
  setInterval(refresh, POLL_MS);
});
