// ── ZeqSimpleAuth (extension) — Simple tier (email + password), zero-storage ──
// Origin-aware port of apps/zeq-dev/public/js/zeq-simple-auth.js. Identical
// derivation (so the SAME ZID resolves here as on the website), but talks to
// the live fork via absolute URLs from ZeqConfig and uses bearer tokens
// (no same-origin cookies — the extension is cross-origin).
//
// Depends on window.HiteCrypto (hmacHite) from lib/hite-auth.js and
// window.ZeqConfig from lib/zeq-config.js. Load BOTH before this file.
(function (root) {
  "use strict";

  function utf8(s) { return new TextEncoder().encode(s); }
  function hexOf(buf) {
    var s = "", b = new Uint8Array(buf);
    for (var i = 0; i < b.length; i++) s += b[i].toString(16).padStart(2, "0");
    return s;
  }

  // Deterministic email-salt (64-hex). Email is never stored or sent — only
  // this one-way digest is used as the HITE salt, re-derived at login.
  async function deriveSaltFromEmail(email) {
    var norm = String(email || "").trim().toLowerCase();
    var d = await crypto.subtle.digest("SHA-256", utf8("HULYAS.HITE.simple-salt.v1|" + norm));
    return hexOf(d);
  }

  // Browser deriveZid — MUST match server routes/zeqAuthV3.ts deriveZid().
  // ── ZID v2 (server: routes/zeqAuthV3.ts deriveZid -> lib/zid.ts) ──────────
  // Widened 2026-07-10 to 128-bit Crockford-base32. The OLD form was
  //     "ZEQ07" + (first 8 bytes % 1e9).padStart(9,"0")
  // which projected a unique 256-bit hash into a 10^9 namespace: different
  // equations collided on the UNIQUE zid at ~31k users and BLOCKED
  // REGISTRATION. This extension kept deriving the old, colliding form for
  // three weeks after the server moved — so the same credentials resolved to a
  // DIFFERENT identity here than on the website. Byte-for-byte the canonical
  // implementation from apps/zeq-dev/public/js/zeq-simple-auth.js. Do not
  // re-type it: if it drifts again, identities silently fork.
  var ZID_B32 = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
  function zidB32(bytes, symbols) {
    var out = "", buf = 0, cnt = 0;
    for (var i = 0; i < bytes.length && out.length < symbols; i++) {
      buf = ((buf << 8) | bytes[i]) >>> 0; cnt += 8;
      while (cnt >= 5 && out.length < symbols) { out += ZID_B32[(buf >>> (cnt - 5)) & 0x1f]; cnt -= 5; }
      buf = buf & ((1 << cnt) - 1);
    }
    if (out.length < symbols) out += ZID_B32[(buf << (5 - cnt)) & 0x1f];
    while (out.length < symbols) out += "0";
    return out;
  }

  async function deriveZid(equationHash) {
    var d = new Uint8Array(await crypto.subtle.digest("SHA-256", utf8(equationHash)));
    return "ZEQ7" + zidB32(d.subarray(0, 16), 26);
  }

  async function buildCredential(email, complexPassword) {
    if (!root.HiteCrypto || typeof root.HiteCrypto.hmacHite !== "function") {
      throw new Error("HiteCrypto required (load lib/hite-auth.js first)");
    }
    var salt = await deriveSaltFromEmail(email);
    var equation_hash = await root.HiteCrypto.hmacHite(complexPassword, salt);
    var zid = await deriveZid(equation_hash);
    return { salt: salt, equation_hash: equation_hash, zid: zid };
  }

  async function _api() {
    if (!root.ZeqConfig) throw new Error("ZeqConfig required (load lib/zeq-config.js first)");
    return await root.ZeqConfig.api();
  }

  async function register(email, complexPassword, displayName) {
    var c = await buildCredential(email, complexPassword);
    var api = await _api();
    var resp = await fetch(api + "/zeq-auth/register-v3", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ equation_hash: c.equation_hash, equation_salt: c.salt, display_name: displayName || "zeq-simple", hash_version: 2 }),
    });
    var data = await resp.json().catch(function () { return {}; });
    return { ok: !!(resp.ok && data.ok), status: resp.status, zid: c.zid, data: data };
  }

  async function login(email, complexPassword) {
    var c = await buildCredential(email, complexPassword);
    var api = await _api();
    var resp = await fetch(api + "/zeq-auth/login-v3", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ zid: c.zid, candidate_hash: c.equation_hash }),
    });
    var data = await resp.json().catch(function () { return {}; });
    return { ok: !!(resp.ok && data.ok), status: resp.status, zid: c.zid, data: data };
  }

  async function loginOrRegister(email, complexPassword, displayName) {
    var li = await login(email, complexPassword);
    if (li.ok) return Object.assign({ created: false }, li);
    var re = await register(email, complexPassword, displayName);
    return Object.assign({ created: true }, re);
  }

  root.ZeqSimpleAuth = {
    VERSION: "1",
    deriveSaltFromEmail: deriveSaltFromEmail,
    deriveZid: deriveZid,
    buildCredential: buildCredential,
    register: register,
    login: login,
    loginOrRegister: loginOrRegister,
  };
})(typeof self !== "undefined" ? self : this);
