// zcbot dev 控制台入口 + 编排:enterApp(应用初始化)、loadStorage(存储用量)、
// Esc 关弹窗栈、boot。功能逻辑全在各模块(chat/files/preview/media/auth/newtask/embed/layout/…),
// 经各模块顶层 import 拉入依赖图(layout/markdown/media 由 chat 等引入,副作用照常)。
import { state, EMBED, setIdentity, userDisplayName, userDisplayTitle } from "./state.js";
import { humanSize, fmtTime } from "./format.js";
import { $ } from "./dom.js";
import { api } from "./api.js";
import { closeChpwModal } from "./auth.js";
import { closeSkillsModal } from "./skills.js";
import { closeMemoryModal } from "./memory.js";
import { closeCronsModal } from "./crons.js";
import { closeWechatModal } from "./wechat.js";
import { closeChangelogModal, markVersion } from "./changelog.js";
import { closeFilePreview, closeMiniPreview } from "./preview.js";
import { closeSrcPicker, loadFiles } from "./files.js";
import { loadFolderSuggestions } from "./newtask.js";
import { embedInit } from "./embed.js";
import { loadTaskList, loadModels, loadChannelCards } from "./chat.js";
import { refreshProcs } from "./procs.js";

// ───── enter app ─────
export function enterApp() {
  $("login").style.display = "none";
  $("app").classList.add("ready");
  renderWho();   // 顶栏用户:默认显 name(兜底 user_name/email/uid8),hover 显完整身份
  loadTaskList();
  loadChannelCards();  // 渠道镜像对话(微信 / 企业微信)固定卡片,与列表并行拉
  loadFiles();  // 文件面板与 task 解耦 — 启动即拉 user_root
  loadModels(); // 模型清单缓存:chat-meta 下拉 + 新建对话框 + 历史小标
  loadFolderSuggestions();  // 灌 filter-wd select(modal 打开时会重拉,这里让左 pane 先有选项)
  loadStorage(); // 顶栏存储用量(后台扫描快照,非实时)
  loadRole();    // 拉 /v1/me,admin 才显「管理」入口(/static/admin.html)
  refreshProcs(); // 后台进程(bg proc):上个会话遗留的 running proc 恢复轮询/展示
}

// 顶栏用户名:默认显 name(兜底 user_name → email → uid8),title 悬浮给完整身份。
function renderWho() {
  const el = $("hd-who");
  if (!el) return;
  el.textContent = userDisplayName();
  el.title = userDisplayTitle();
}

// 当前用户身份 + 角色:/v1/me 返 {user_id, role, name, user_name, email}。
// admin → 显顶栏「管理」链接;并用服务端权威值校准顶栏用户名(platform_key 登录 / 老 token
// 升级后,name/user_name 这一刻才到齐)。失败静默(增量功能,拉不到就维持登录时的兜底值)。
async function loadRole() {
  const link = $("hd-admin");
  try {
    const me = await api("GET", "/v1/me");
    if (me) {
      setIdentity({ user_id: me.user_id, name: me.name, user_name: me.user_name, email: me.email });
      renderWho();
    }
    if (link) link.style.display = (me && me.role === "admin") ? "" : "none";
  } catch (e) { if (link) link.style.display = "none"; }
}

// 存储用量:拉 /v1/user/storage 渲染文件面板底部进度条。用量来自后台 15min 扫描,
// 故无需高频刷新 —— enterApp 拉一次即可。无配额上限时只显已用、不画进度条(nolimit)。
async function loadStorage() {
  let s;
  try { s = await api("GET", "/v1/user/storage"); } catch (e) { return; }
  const el = $("storage-foot");
  const used = s.bytes_used || 0;
  const limit = s.limit_bytes;
  if (limit && limit > 0) {
    const pct = Math.min(100, Math.round(used / limit * 100));
    $("storage-foot-bar").style.width = pct + "%";
    $("storage-foot-txt").textContent = `${humanSize(used)} / ${humanSize(limit)}`;
    el.classList.remove("nolimit");
    el.classList.toggle("over", used >= limit);
  } else {
    // 不限额:只显已用,隐藏进度条
    $("storage-foot-txt").textContent = humanSize(used);
    el.classList.add("nolimit");
    el.classList.remove("over");
  }
  const when = s.scanned_at ? fmtTime(s.scanned_at) : "尚未统计";
  el.title = `已用 ${humanSize(used)} · ${s.file_count || 0} 个文件\n统计于 ${when}（后台每 15 分钟扫描，非实时）`;
  el.classList.add("show");
}


// 版本号 + 品牌名:/healthz 是 auth 豁免接口,embed / 未登录都拿得到 → boot 时无条件拉一次。
// 版本号填左栏底部;品牌名(ZCBOT_BRAND_NAME,默认「总院科研辅助助手」)覆盖页面标题 /
// 顶栏 / 登录卡 —— 静态 HTML 里写的是默认品牌,env 改名时这里统一刷。失败静默。
async function loadVersion() {
  try {
    const r = await fetch("/healthz");
    const d = await r.json();
    const el = $("app-version");
    if (el && d && d.version) el.textContent = "v" + d.version;
    if (d && d.version) markVersion(d.version); // 与 localStorage 比对,决定新版本红点
    if (d && d.brand) {
      document.title = d.brand;
      const hd = document.querySelector("header .brand .title");
      if (hd) hd.textContent = d.brand;
      const li = document.querySelector("#login .brand .name");
      if (li) li.textContent = d.brand;
    }
  } catch (e) {}
}


// ───── Esc 关弹窗栈(跨模块协调:chpw/选入/文件预览/小预览)─────
document.addEventListener("keydown", (e) => {
  if (e.key !== "Escape") return;
  // 多模态共存:优先关靠前栈顶 — 小预览(z 96)→ 选入(z 95)→ 文件预览(z 90)→ 新任务(z 80)
  if ($("chpw-modal").classList.contains("show")) { closeChpwModal(); return; }
  if ($("skills-modal").classList.contains("show")) { closeSkillsModal(); return; }
  if ($("memory-modal").classList.contains("show")) { closeMemoryModal(); return; }
  if ($("crons-modal").classList.contains("show")) { closeCronsModal(); return; }
  if ($("wechat-modal").classList.contains("show")) { closeWechatModal(); return; }
  if ($("changelog-modal").classList.contains("show")) { closeChangelogModal(); return; }
  if ($("mini-preview-modal").classList.contains("show")) { closeMiniPreview(); return; }
  if ($("src-picker-modal").classList.contains("show")) { closeSrcPicker(); return; }
  if ($("file-preview-modal").classList.contains("show")) { closeFilePreview(); return; }
});


// ───── boot ─────
loadVersion();  // 与登录态无关,立即拉
if (EMBED) {
  embedInit();
} else if (state.token) {
  // 已有 token:试探一下,失败回登录页
  enterApp();
} else {
  $("li-email").focus();
}
