/* global firebase, L */
// ===========================================================
// 스킨 라이선스 redeem — todoary-licenses Firebase (작업방 앱과 분리)
// named app: "licenses" · Callable redeemSkin · 영수증만 반환
// ===========================================================

(function () {
  if (window.skinLicensesBridge) return;

  const APP_NAME = "licenses";
  const DEFAULT_REGION = "us-central1";
  const DEFAULT_FN = "redeemSkin";

  let initPromise = null;
  let licensesApp = null;
  let redeemCallable = null;

  function cfg() {
    return window.FIREBASE_LICENSES_CONFIG || {};
  }

  function hasSdkConfig() {
    const c = cfg();
    return !!(c.apiKey && c.projectId);
  }

  function callableHttpUrl() {
    return (
      window.FIREBASE_LICENSES_CALLABLE_URL
      || (cfg().region && cfg().projectId && cfg().callableName
        ? `https://${cfg().region}-${cfg().projectId}.cloudfunctions.net/${cfg().callableName}`
        : "")
    );
  }

  function loadScript(src) {
    return new Promise((res, rej) => {
      const s = document.createElement("script");
      s.src = src;
      s.async = true;
      s.onload = () => res();
      s.onerror = () => rej(new Error("script load failed: " + src));
      document.head.appendChild(s);
    });
  }

  async function ensureSdkLoaded() {
    if (window.firebase?.functions) return;
    const v = window.FIREBASE_LICENSES_VERSION || "10.13.0";
    const base = `https://www.gstatic.com/firebasejs/${v}`;
    await loadScript(`${base}/firebase-app-compat.js`);
    await loadScript(`${base}/firebase-functions-compat.js`);
  }

  async function initSdk() {
    await ensureSdkLoaded();
    const c = cfg();
    const region = c.region || DEFAULT_REGION;
    const fnName = c.callableName || DEFAULT_FN;
    try {
      licensesApp = firebase.app(APP_NAME);
    } catch (_) {
      licensesApp = firebase.initializeApp(
        {
          apiKey: c.apiKey,
          authDomain: c.authDomain || `${c.projectId}.firebaseapp.com`,
          projectId: c.projectId,
          storageBucket: c.storageBucket,
          messagingSenderId: c.messagingSenderId,
          appId: c.appId,
        },
        APP_NAME,
      );
    }
    redeemCallable = firebase.app(APP_NAME).functions(region).httpsCallable(fnName);
  }

  function mapRedeemError(err) {
    const code = err?.code || err?.details?.code || "";
    const msg = String(err?.message || err?.details || err || "");
    const lower = (code + " " + msg).toLowerCase();

    if (code === "functions/invalid-argument" || lower.includes("licensekey and skinid")) {
      return L("skin.keyRequired") || "Enter a license key.";
    }
    if (code === "functions/unauthenticated" || lower.includes("invalid license") || lower.includes("polar validation")) {
      return L("skin.redeemInvalidKey") || "Invalid license key.";
    }
    if (code === "functions/permission-denied" || lower.includes("forbidden") || lower.includes("does not include")) {
      return L("skin.redeemForbidden") || "This license does not include this skin.";
    }
    if (lower.includes("failed to fetch") || lower.includes("network") || lower.includes("networkerror")) {
      return L("skin.redeemNetwork") || "Network error. Check your connection and try again.";
    }
    if (lower.includes("bundle not found") || lower.includes("skin bundle")) {
      return L("skin.redeemBundleMissing") || "Skin bundle is not installed in this app build.";
    }
    if (lower.includes("invalid receipt") || lower.includes("signature")) {
      return L("skin.redeemReceiptInvalid") || "License verification failed (invalid receipt).";
    }
    if (lower.includes("licensesconfig") || lower.includes("firebase licenses")) {
      return L("skin.licensesConfigMissing") || "License server is not configured (firebase-licenses-config).";
    }
    return msg || L("skin.redeemFailed") || "Redeem failed.";
  }

  async function callRedeemViaHttp(licenseKey, skinId) {
    const url = callableHttpUrl();
    if (!url) throw new Error(L("skin.licensesConfigMissing") || "License server URL missing");

    let res;
    try {
      res = await fetch(url, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ data: { licenseKey, skinId } }),
      });
    } catch (e) {
      const err = new Error(L("skin.redeemNetwork") || "Network error");
      err.code = "network";
      throw err;
    }

    let body;
    try {
      body = await res.json();
    } catch (_) {
      throw new Error(L("skin.redeemFailed") || "Invalid server response");
    }

    if (body?.error) {
      const e = new Error(body.error.message || "redeem failed");
      e.code = body.error.status ? `functions/${String(body.error.status).toLowerCase()}` : "functions/internal";
      throw e;
    }

    const receipt = body?.result?.receipt;
    if (!receipt?.payload || !receipt?.signature) {
      throw new Error(L("skin.redeemFailed") || "Missing receipt in response");
    }
    return receipt;
  }

  async function callRedeemViaSdk(licenseKey, skinId) {
    const result = await redeemCallable({ licenseKey, skinId });
    const receipt = result?.data?.receipt;
    if (!receipt?.payload || !receipt?.signature) {
      throw new Error(L("skin.redeemFailed") || "Missing receipt in response");
    }
    return receipt;
  }

  async function init() {
    if (initPromise) return initPromise;
    initPromise = (async () => {
      if (hasSdkConfig()) {
        await initSdk();
      }
    })();
    return initPromise;
  }

  async function callRedeemSkin(licenseKey, skinId) {
    await init();
    const key = String(licenseKey || "").trim();
    const id = String(skinId || "").trim();
    if (!key || !id) throw new Error(L("skin.keyRequired") || "License key required");

    try {
      if (redeemCallable) return await callRedeemViaSdk(key, id);
      return await callRedeemViaHttp(key, id);
    } catch (e) {
      throw new Error(mapRedeemError(e));
    }
  }

  window.skinLicensesBridge = {
    init,
    callRedeemSkin,
    hasSdkConfig,
    callableHttpUrl,
    appName: APP_NAME,
  };
})();
