/**
 * 键共振 Destiny · 价位／权限／会员案例规定（Web 事实源）
 * 对齐 PRICE_PERMISSION_CANON.md + AppConfig / BillingSku / tiers.dart / membership.dart（2026-07-31）
 * 结账未接通：本模块只提供价目、SKU、档位判断、案件配额，不伪造支付成功。
 * © 2026 Jason Li（泽森）
 */
(function (global) {
  "use strict";

  var TIER_KEY = "kr_product_tier";
  var SUB_KEY = "kr_sub_expires_ms";
  var SINGLE_KEY = "kr_single_judgment_expires_ms";
  var PREVIEW_TIER_KEY = "kr_preview_tier";
  var PREVIEW_SINGLE_KEY = "kr_preview_single";

  var SKUS = {
    free: { id: "kr_free", usd: 0, cny: 0, label: "免费版", see: "①基础【初断】", stripePrice: "", stripeProduct: "" },
    pro: { id: "kr_pro_499", usd: 4.99, cny: 38, label: "专业板 · 买断", see: "①＋②专业【细断】", stripePrice: "price_1U1XoxBogkBcYEebJZYIA00x", stripeProduct: "prod_V1b0sZg9VUCTx3" },
    resonance: { id: "kr_resonance_2499", usd: 24.99, cny: 168, label: "键共振 · 买断", see: "①②③详断＋④结论", stripePrice: "price_1U1Y4dBogkBcYEeb1dKxxjSM", stripeProduct: "prod_V1bH1bUhZAh4iK" },
    resonanceMo: { id: "kr_resonance_mo_999", usd: 9.99, cny: 68, per: "月", label: "键共振 · 月订", see: "键共振全功能（订阅期内）", stripePrice: "price_1U1Y8xBogkBcYEeble34gE2s" },
    resonanceYr: { id: "kr_resonance_yr_7900", usd: 79, cny: 528, per: "年", label: "键共振 · 年订", see: "键共振全功能（订阅期内）", stripePrice: "price_1U1YFUBogkBcYEebqkITbvWI" },
    single: { id: "kr_single_judgment_199", usd: 1.99, cny: 15, label: "单次判局 24h", see: "判局全文＋导出 · 不升档", stripePrice: "price_1U1YK5BogkBcYEebmVGR6Ozt" },
    upgrade: { id: "kr_resonance_upgrade_1999", usd: 20, cny: 130, label: "专业→键共振补差", see: "已购专业板升买断", stripePrice: "price_1U1YMsBogkBcYEeblJcIvI8X" },
  };

  var FEATURES = {
    free: ["basicChart", "orientYongJi", "tutorialBasics", "keyTeaser"],
    pro: ["basicChart", "orientYongJi", "tutorialBasics", "keyTeaser", "proDetail", "tutorialProfessional", "onionStack", "fullMetaTable"],
    resonance: ["basicChart", "orientYongJi", "tutorialBasics", "keyTeaser", "proDetail", "tutorialProfessional", "onionStack", "fullMetaTable", "tutorialInnovation", "keyResonanceFull", "entanglementFull", "judgmentReport", "coreTheoryDetail", "liuQinDeep"],
  };

  /** 会员案例规定：按看局档位，不升档、不伪造付款。配额为 Web 产品规则（Flutter 无条数上限）。 */
  var CASE_POLICY = {
    free: { quota: 3, note: false, events: false, showPattern: false, showIntensity: false, exportJson: false, importJson: false, exportJudgment: false, save: true, load: true },
    pro: { quota: 30, note: true, events: false, showPattern: true, showIntensity: false, exportJson: true, importJson: true, exportJudgment: false, save: true, load: true },
    resonance: { quota: 300, note: true, events: true, showPattern: true, showIntensity: true, exportJson: true, importJson: true, exportJudgment: true, save: true, load: true },
  };

  var TIER_ZH = { free: "免费版", pro: "专业板", resonance: "键共振版" };
  var memLocal = {};
  var memSess = {};

  function usd(n) {
    if (!n) return "$0";
    return "$" + (Math.round(n * 100) % 100 ? n.toFixed(2) : String(n));
  }
  function labelZh(sku) {
    var s = SKUS[sku] || SKUS.free;
    if (!s.usd) return "免费";
    return usd(s.usd) + (s.per ? "/" + s.per : "") + "（约 ¥" + s.cny + "）";
  }
  function storeGet(kind, key) {
    try {
      if (kind === "local" && typeof localStorage !== "undefined") return localStorage.getItem(key);
      if (kind === "session" && typeof sessionStorage !== "undefined") return sessionStorage.getItem(key);
    } catch (e) { /* ignore */ }
    var bag = kind === "session" ? memSess : memLocal;
    return bag[key] == null ? null : bag[key];
  }
  function storeSet(kind, key, val) {
    try {
      var api = kind === "session" ? (typeof sessionStorage !== "undefined" ? sessionStorage : null) : (typeof localStorage !== "undefined" ? localStorage : null);
      if (api) {
        if (val == null) api.removeItem(key);
        else api.setItem(key, String(val));
        return;
      }
    } catch (e) { /* ignore */ }
    var bag = kind === "session" ? memSess : memLocal;
    if (val == null) delete bag[key];
    else bag[key] = String(val);
  }
  function nowMs() { return Date.now(); }
  function normTier(raw) {
    if (raw === "pro") return "pro";
    if (raw === "resonance" || raw === "resonanceMaster") return "resonance";
    return "free";
  }
  function isAuthor() {
    var A = global.KRAuthor;
    return !!(A && (A.unlocked || (A.ensure && A.ensure())));
  }
  function purchasedTier() { return normTier(storeGet("local", TIER_KEY)); }
  function expiresAt(key) {
    var raw = storeGet("local", key);
    var ms = raw ? parseInt(raw, 10) : 0;
    if (!ms || nowMs() >= ms) {
      if (ms) storeSet("local", key, null);
      return null;
    }
    return ms;
  }
  function subscriptionExpiresAt() { return expiresAt(SUB_KEY); }
  function subscriptionActive() { return !!subscriptionExpiresAt(); }
  function singleJudgmentExpiresAt() { return expiresAt(SINGLE_KEY); }
  function previewSingle() { return isAuthor() && storeGet("session", PREVIEW_SINGLE_KEY) === "1"; }
  function singleJudgmentActive() { return previewSingle() || !!singleJudgmentExpiresAt(); }
  function previewTier() {
    if (!isAuthor()) return null;
    var raw = storeGet("session", PREVIEW_TIER_KEY);
    if (raw === "free" || raw === "pro" || raw === "resonance") return raw;
    return null;
  }
  function setPreviewTier(tier) {
    if (!isAuthor()) return;
    if (tier == null || tier === "" || tier === "off") storeSet("session", PREVIEW_TIER_KEY, null);
    else storeSet("session", PREVIEW_TIER_KEY, normTier(tier));
  }
  function setPreviewSingle(on) {
    if (!isAuthor()) return;
    storeSet("session", PREVIEW_SINGLE_KEY, on ? "1" : null);
  }

  /** 有效档：作者预览 > 作者解锁 > 有效订阅 > 本机购买档。单次 24h 不升档。 */
  function currentTier() {
    var prev = previewTier();
    if (prev) return prev;
    if (isAuthor()) return "resonance";
    if (subscriptionActive()) return "resonance";
    return purchasedTier();
  }
  function hasPro() { var t = currentTier(); return t === "pro" || t === "resonance"; }
  function hasResonance() { return currentTier() === "resonance"; }
  function allows(feature) {
    var list = FEATURES[currentTier()] || FEATURES.free;
    if (list.indexOf(feature) >= 0) return true;
    if (singleJudgmentActive() && (feature === "judgmentReport" || feature === "coreTheoryDetail")) return true;
    return false;
  }
  function casePolicy() {
    var base = CASE_POLICY[currentTier()] || CASE_POLICY.free;
    var out = {};
    Object.keys(base).forEach(function (k) { out[k] = base[k]; });
    if (singleJudgmentActive()) out.exportJudgment = true;
    out.tier = currentTier();
    out.single = singleJudgmentActive();
    return out;
  }
  function sanitizeCase(cs, full) {
    if (!cs) return cs;
    if (full) return cs;
    var copy = {};
    ["id", "name", "gender", "cal", "date", "time", "city", "lon", "lat", "standCity", "standName", "pillars", "dayMaster", "note", "createdAt", "updatedAt"].forEach(function (k) {
      if (cs[k] != null) copy[k] = cs[k];
    });
    var pol = casePolicy();
    if (pol.showPattern) {
      copy.pattern = cs.pattern || "";
      copy.yong = cs.yong || "";
      copy.ji = cs.ji || "";
    }
    return copy;
  }
  function checkout(skuKey) {
    return { ok: false, connected: false, sku: skuKey || "", message: "结账链接未接通" };
  }
  function fmtTime(ms) {
    if (!ms) return "";
    var d = new Date(ms);
    function z(n) { return (n < 10 ? "0" : "") + n; }
    return d.getFullYear() + "-" + z(d.getMonth() + 1) + "-" + z(d.getDate()) + " " + z(d.getHours()) + ":" + z(d.getMinutes());
  }
  function entitlement() {
    var pol = casePolicy();
    return {
      author: isAuthor(),
      preview: previewTier(),
      previewSingle: previewSingle(),
      purchased: purchasedTier(),
      effective: currentTier(),
      effectiveZh: TIER_ZH[currentTier()] || currentTier(),
      subscriptionExpires: subscriptionExpiresAt(),
      singleExpires: singleJudgmentExpiresAt(),
      singleActive: singleJudgmentActive(),
      policy: pol,
    };
  }
  function applyUrlPreview() {
    try {
      if (typeof location === "undefined") return;
      var q = new URLSearchParams(location.search);
      var t = q.get("tier");
      if ((t === "free" || t === "pro" || t === "resonance") && isAuthor()) setPreviewTier(t);
      if (q.get("single") === "1" && isAuthor()) setPreviewSingle(true);
    } catch (e) { /* ignore */ }
  }

  global.KRPricing = {
    version: "2026-07-31",
    caseRulesVersion: "2026-08-14",
    checkoutConnected: false,
    checkoutNote: "结账链接未接通",
    skus: SKUS,
    features: FEATURES,
    casePolicies: CASE_POLICY,
    usd: usd,
    labelZh: labelZh,
    tierZh: function (t) { return TIER_ZH[t] || t; },
    currentTier: currentTier,
    purchasedTier: purchasedTier,
    hasPro: hasPro,
    hasResonance: hasResonance,
    allows: allows,
    casePolicy: casePolicy,
    sanitizeCase: sanitizeCase,
    checkout: checkout,
    entitlement: entitlement,
    subscriptionActive: subscriptionActive,
    subscriptionExpiresAt: subscriptionExpiresAt,
    singleJudgmentActive: singleJudgmentActive,
    singleJudgmentExpiresAt: singleJudgmentExpiresAt,
    previewTier: previewTier,
    setPreviewTier: setPreviewTier,
    setPreviewSingle: setPreviewSingle,
    fmtTime: fmtTime,
    applyUrlPreview: applyUrlPreview,
    pageArrowZh: "①基础【初断】：地后 → ②专业【细断】：生克后运前 → ③键共振【详断】：运岁／外环境 → ④结论：指标→象义→结果",
  };

  if (typeof document !== "undefined") {
    function boot() {
      try { if (global.KRAuthor && global.KRAuthor.ensure) global.KRAuthor.ensure(); } catch (e) { /* ignore */ }
      applyUrlPreview();
    }
    if (document.readyState === "loading") document.addEventListener("DOMContentLoaded", boot);
    else boot();
  }
})(typeof window !== "undefined" ? window : globalThis);
