const y = "auth", s = "pendingAuthState", U = "pendingImage", C = (t) => t.session ?? t.local, M = () => C(chrome.storage), A = async () => {
  const r = (await chrome.storage.local.get(y))[y];
  return r?.token ? r : null;
}, I = (t) => chrome.storage.local.set({ [y]: t }), g = ("https://formulabridge.online/api/v1".trim() || "https://formulabridge.online/api/v1").replace(/\/$/, ""), P = async (t, r, o) => {
  if (!o || r !== o)
    throw new Error("登录状态校验失败，请重新登录");
  const e = await fetch(`${g}/auth/extension-token`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ code: t, client_id: chrome.runtime.id })
  }), n = await e.json().catch(() => null);
  if (!e.ok || !n?.token || !n.user)
    throw new Error(n?.message ?? `登录失败（${e.status}）`);
  const a = { token: n.token, user: n.user };
  return await I(a), a;
}, D = async (t, r, o = "GET", e) => {
  const n = {
    Authorization: `Bearer ${r}`
  }, a = { method: o, headers: n };
  e !== void 0 && (n["Content-Type"] = "application/json", a.body = JSON.stringify(e));
  const f = await fetch(`${g}${t}`, a), S = await f.json().catch(() => null);
  if (!f.ok) throw new Error(S?.message ?? `请求失败（${f.status}）`);
  return S;
}, N = async (t, r) => {
  await D("/recognition-history", t, "POST", r);
}, i = "pendingSelection", T = "offscreen.html", u = "当前页面不支持截图，请在普通网页中使用", $ = "当前浏览器版本不支持 Lite 识别", l = "formula_bridge_locale", b = (t, r) => {
  try {
    return chrome.i18n.getMessage(t) || r;
  } catch {
    return r;
  }
}, w = (t) => t === "zh-Hans" || t === "zh-Hant" || t === "en", k = (t) => t === "en" ? "Copy selected formula to Formula Bridge" : t === "zh-Hant" ? "複製選取公式到公式橋" : "复制选中公式到公式桥", L = async () => {
  const t = await chrome.storage.local.get(l);
  if (w(t[l]))
    return t[l];
  const r = chrome.i18n.getUILanguage().toLowerCase();
  return r.startsWith("en") ? "en" : r.includes("tw") || r.includes("hk") ? "zh-Hant" : "zh-Hans";
}, E = async (t) => {
  const r = t ?? await L();
  try {
    chrome.contextMenus.update("send-selection", {
      title: t === void 0 ? b(
        "contextMenuSendSelection",
        k(r)
      ) : k(r)
    });
  } catch {
  }
};
let m = null;
const h = M(), c = chrome.offscreen, x = chrome.storage.local;
if (typeof x.setAccessLevel == "function")
  try {
    Promise.resolve(
      x.setAccessLevel({ accessLevel: "TRUSTED_CONTEXTS" })
    ).catch(() => {
    });
  } catch {
  }
const j = async () => {
  if (!c) return !1;
  if (typeof c.hasDocument == "function")
    return c.hasDocument();
  const r = await globalThis.clients.matchAll(), o = chrome.runtime.getURL(T);
  return r.some((e) => e.url === o);
}, B = async () => {
  if (!c?.createDocument)
    throw new Error($);
  await j() || (m ??= c.createDocument({
    url: T,
    reasons: [chrome.offscreen.Reason.WORKERS],
    justification: "Keep the OCR model ready while the popup is closed"
  }).finally(() => {
    m = null;
  }), await m);
}, H = () => {
  if (c?.closeDocument)
    try {
      Promise.resolve(c.closeDocument()).catch(() => {
      });
    } catch {
    }
}, z = () => Array.from(
  crypto.getRandomValues(new Uint8Array(16)),
  (t) => t.toString(16).padStart(2, "0")
).join(""), d = (t, r) => {
  chrome.action.setBadgeText({ text: t }), chrome.action.setBadgeBackgroundColor({ color: r }), setTimeout(() => {
    chrome.action.setBadgeText({ text: "" });
  }, 5e3);
}, v = (t) => {
  if (!t) return !1;
  try {
    const { protocol: r } = new URL(t);
    return r === "http:" || r === "https:";
  } catch {
    return !1;
  }
}, p = async (t) => {
  if (!t.id || !v(t.url))
    throw new Error(u);
  try {
    if ((await chrome.tabs.sendMessage(t.id, {
      type: "content-ping"
    }))?.ok) return;
  } catch {
  }
  if (await chrome.scripting.executeScript({
    target: { tabId: t.id },
    files: ["content.js"]
  }), !(await chrome.tabs.sendMessage(t.id, {
    type: "content-ping"
  }))?.ok) throw new Error("网页脚本未就绪");
}, _ = async (t, r) => {
  if (!t.id || !v(t.url))
    throw new Error(u);
  await p(t);
  try {
    return await chrome.tabs.sendMessage(t.id, r);
  } catch {
    return await p(t), chrome.tabs.sendMessage(t.id, r);
  }
}, O = async () => {
  const t = await chrome.tabs.query({});
  await Promise.allSettled(t.map((r) => p(r)));
};
chrome.runtime.onMessageExternal.addListener((t, r, o) => {
  if (t?.type === "formula-bridge-close-tab") {
    const e = r.tab?.id;
    return e !== void 0 && chrome.tabs.remove(e).catch(() => {
    }), o({ ok: !0 }), !1;
  }
  if (t?.type === "formula-bridge-auth-code")
    return (async () => {
      try {
        const e = await h.get(s), n = await P(
          t.code,
          t.state,
          e[s]
        );
        await h.remove(s), d("✓", "#16a34a"), o({ ok: !0, email: n.user.email });
      } catch (e) {
        o({
          ok: !1,
          error: e instanceof Error ? e.message : "登录失败"
        });
      }
    })(), !0;
});
chrome.runtime.onInstalled.addListener(() => {
  chrome.contextMenus.create({
    id: "send-selection",
    title: b(
      "contextMenuSendSelection",
      "复制选中公式到公式桥"
    ),
    contexts: ["selection"]
  }), E(), O();
});
chrome.runtime.onStartup.addListener(() => {
  E(), O();
});
chrome.contextMenus.onClicked.addListener((t, r) => {
  t.menuItemId !== "send-selection" || !r?.id || (async () => {
    try {
      const o = await _(r, {
        type: "get-selection"
      }), e = (o?.latex || o?.text || "").trim();
      e && (await chrome.storage.local.set({ [i]: e }), d("1", "#2563eb"));
    } catch {
    }
  })();
});
chrome.runtime.onMessage.addListener((t, r, o) => {
  if (t?.type === "get-locale")
    return L().then((e) => o({ locale: e })), !0;
  if (t?.type === "set-locale")
    return w(t.locale) ? ((async () => {
      const e = t.locale;
      await chrome.storage.local.set({ [l]: e }), await E(e);
      const n = await chrome.tabs.query({});
      await Promise.allSettled(
        n.filter((a) => v(a.url) && a.id).map(
          (a) => chrome.tabs.sendMessage(a.id, { type: "locale-changed", locale: e }).catch(() => {
          })
        )
      ), o({ ok: !0 });
    })().catch(() => o({ ok: !1 })), !0) : (o({ ok: !1 }), !1);
  if (t?.type === "lite-ocr-release")
    return o({ ok: !0 }), H(), !1;
  if (t?.type === "save-recognition-history")
    return (async () => {
      try {
        const e = await A(), n = typeof t.latex == "string" ? t.latex : "", a = typeof t.modelVersion == "string" ? t.modelVersion : "";
        if (!e || !n.trim() || !a)
          throw new Error("识别历史参数无效");
        await N(e.token, {
          latex: n,
          recognition_mode: "lite",
          model_version: a
        }), o({ ok: !0 });
      } catch (e) {
        o({
          ok: !1,
          error: e instanceof Error ? e.message : "识别历史保存失败"
        });
      }
    })(), !0;
  if (t?.type === "ocr-init" || t?.type === "ocr-predict")
    return (async () => {
      try {
        await B();
        const e = await chrome.runtime.sendMessage(
          t.type === "ocr-init" ? { type: "lite-ocr-init" } : { type: "lite-ocr-predict", dataUrl: t.dataUrl }
        );
        o(e);
      } catch (e) {
        o({ ok: !1, error: e instanceof Error ? e.message : String(e) });
      }
    })(), !0;
  if (t?.type === "login")
    return w(t.locale) ? ((async () => {
      try {
        const e = z(), n = t.locale;
        await h.set({ [s]: e });
        const a = new URLSearchParams({
          client_id: chrome.runtime.id,
          state: e,
          locale: n
        });
        await chrome.tabs.create({
          url: `${g}/extension/auth/start?${a}`
        }), o({ ok: !0 });
      } catch (e) {
        o({
          ok: !1,
          error: e instanceof Error ? e.message : "登录失败"
        });
      }
    })(), !0) : (o({ ok: !1, error: "无效的语言设置" }), !1);
  if (t?.type === "capture")
    return (async () => {
      try {
        const [e] = await chrome.tabs.query({
          active: !0,
          currentWindow: !0
        });
        if (!e) throw new Error(u);
        await _(e, { type: "start-selection" }), o({ ok: !0 });
      } catch {
        o({
          ok: !1,
          error: u
        });
      }
    })(), !0;
  if (t?.type === "store-formula")
    return (async () => {
      try {
        const e = typeof t.latex == "string" ? t.latex : "";
        if (!e.trim()) throw new Error("公式内容为空");
        await chrome.storage.local.set({ [i]: e }), d("1", "#2563eb"), o({ ok: !0 });
      } catch (e) {
        o({
          ok: !1,
          error: e instanceof Error ? e.message : "公式保存失败"
        });
      }
    })(), !0;
  if (t?.type === "take-selection")
    return (async () => {
      const n = (await chrome.storage.local.get(i))[i] ?? null;
      await chrome.storage.local.remove(i), o({ latex: n });
    })(), !0;
  if (t?.type === "capture-region")
    return (async () => {
      try {
        const e = await chrome.tabs.captureVisibleTab(
          r.tab.windowId,
          { format: "png" }
        );
        o({ ok: !0, dataUrl: e });
      } catch (e) {
        o({
          ok: !1,
          error: e instanceof Error ? e.message : "截图失败"
        });
      }
    })(), !0;
  if (t?.type === "screenshot-crop")
    return (async () => {
      try {
        const e = { id: crypto.randomUUID(), dataUrl: t.dataUrl };
        await h.set({ [U]: e }), d("✓", "#2563eb"), await chrome.action.openPopup().catch(() => {
        }), o({ ok: !0, id: e.id });
      } catch (e) {
        o({ ok: !1, error: e instanceof Error ? e.message : "截图保存失败" });
      }
    })(), !0;
});
