/**
 * OKX 对冲计划 P0:行情 + 永期列表 / 期期 T + 情景测算 + 门禁.
 */
(function () {
  const root = document.getElementById("hedge-plan-root");
  if (!root) return;

  const state = {
    tab: "perp_options",
    mode: "perp_options",
    underlying: root.getAttribute("data-default-underly") || "ETH",
    moneyFilter: "all",
    chain: null,
    selected: null,
    legA: null,
    legB: null,
    market: null,
  };

  function $(id) {
    return document.getElementById(id);
  }

  async function apiJson(url, opts) {
    const res = await fetch(url, Object.assign({ credentials: "same-origin" }, opts || {}));
    const data = await res.json().catch(function () {
      return {};
    });
    if (!res.ok) throw new Error(data.msg || res.statusText || "请求失败");
    return data;
  }

  function fmt(v, d) {
    if (v === null || v === undefined || Number.isNaN(Number(v))) return "—";
    return Number(v).toFixed(d == null ? 2 : d);
  }

  function fmtOptionPx(v, tickSz) {
    if (v === null || v === undefined || Number.isNaN(Number(v))) return "—";
    const n = Number(v);
    const tick = Number(tickSz);
    if (!tickSz || Number.isNaN(tick) || tick <= 0) {
      return String(n).replace(/(\.\d*?[1-9])0+$/, "$1").replace(/\.0+$/, "");
    }
    let decimals = 0;
    if (tick < 1) decimals = Math.max(0, -Math.round(Math.log10(tick)));
    else if (String(tick).indexOf(".") >= 0) decimals = String(tick).split(".")[1].length;
    let s = n.toFixed(decimals);
    // 仅裁小数尾零;整数 tick(BTC=5)时绝不能把 1370 裁成 137
    if (decimals > 0) s = s.replace(/\.?0+$/, "");
    return s || "0";
  }

  /** 价格/流动性(张),价格按 tick_sz 对齐交易所精度. */
  function fmtPxSz(px, sz, estimated, tickSz) {
    if (px === null || px === undefined || Number.isNaN(Number(px))) return "—";
    let price = fmtOptionPx(px, tickSz);
    if (price === "—") return "—";
    if (estimated) price += "~";
    if (sz === null || sz === undefined || sz === "" || Number.isNaN(Number(sz))) return price;
    const s = Number(sz);
    const size = Math.abs(s - Math.round(s)) < 1e-9 ? String(Math.round(s)) : String(s);
    return price + "/" + size;
  }

  function moneynessBadge(c) {
    const m = (c && c.moneyness) || "";
    const label = (c && c.moneyness_label) || "—";
    return '<span class="opt-moneyness opt-moneyness-' + m + '">' + label + "</span>";
  }

  function matchesMoneyFilter(c) {
    const f = state.moneyFilter || "all";
    if (f === "all") return true;
    const m = (c.moneyness || "").toLowerCase();
    if (f === "itm") return m === "itm" || m === "atm";
    if (f === "otm") return m === "otm";
    return true;
  }

  function optTypeForDirection(dir) {
    return dir === "short" ? "C" : "P";
  }

  function syncUnderlyingUI() {
    const uly = state.underlying || "ETH";
    document.querySelectorAll(".hp-uly-btn, .hp-uly-btn-oo").forEach(function (b) {
      const on = b.getAttribute("data-uly") === uly;
      b.classList.toggle("active", on);
      b.setAttribute("aria-pressed", on ? "true" : "false");
    });
    const lab = $("hp-perp-uly-label");
    if (lab) lab.textContent = uly;
    const ooLab = $("hp-oo-uly-label");
    if (ooLab) ooLab.textContent = uly;
  }

  function syncMoneyUI() {
    document.querySelectorAll(".hp-money-btn").forEach(function (b) {
      const on = b.getAttribute("data-money") === state.moneyFilter;
      b.classList.toggle("active", on);
    });
  }

  function syncTabUI() {
    const tab = state.tab || "perp_options";
    document.querySelectorAll(".hp-tab").forEach(function (b) {
      const on = b.getAttribute("data-tab") === tab;
      b.classList.toggle("active", on);
      b.setAttribute("aria-selected", on ? "true" : "false");
    });
    ["perp_options", "options_options", "active", "history", "stats"].forEach(function (id) {
      const panel = $("hp-tab-" + id);
      if (!panel) return;
      const on = id === tab;
      panel.classList.toggle("hidden", !on);
      if (on) panel.removeAttribute("hidden");
      else panel.setAttribute("hidden", "");
    });
    if (tab === "perp_options" || tab === "options_options") {
      state.mode = tab;
    }
  }

  function setGateLine(gates) {
    const el = $("hp-gate-line");
    if (!el) return;
    if (!gates) {
      el.textContent = "";
      return;
    }
    const parts = [
      "计仓:" + (gates.is_full_margin ? "全仓" : "非全仓"),
      "测算:" + (gates.can_preview ? "可" : "否"),
      "开仓:" + (gates.can_start ? "可" : "否"),
    ];
    if (gates.reasons && gates.reasons.length) parts.push(gates.reasons.join("; "));
    el.textContent = parts.join(" · ");
    const start = $("hp-start-btn");
    const startOo = $("hp-start-btn-oo");
    if ((gates.plan_type || state.mode) === "options_options") {
      if (startOo) startOo.disabled = !gates.can_start;
    } else {
      if (start) start.disabled = !gates.can_start;
    }
  }

  function setOptionsBalance(chain) {
    const acct = (chain && chain.options_account) || {};
    const label = (chain && chain.account_label) || acct.label || "期权账户";
    const tag = $("hp-opt-acct-tag");
    if (tag) tag.textContent = label;
    const line =
      label +
      " · 交易 USDC " +
      fmt(acct.trading_usdc, 2) +
      " · 资金 USDC " +
      fmt(acct.funding_usdc, 2);
    const el = $("hp-opt-bal-line");
    if (el) el.textContent = line;
    const oo = $("hp-oo-bal-line");
    if (oo) oo.textContent = line;
  }

  async function loadGates() {
    try {
      const d = await apiJson("/api/hedge-plan/gates?plan_type=" + encodeURIComponent(state.mode));
      setGateLine(d);
    } catch (e) {
      setGateLine({ can_preview: false, can_start: false, reasons: [e.message], is_full_margin: false });
    }
  }

  async function loadMarket() {
    const dir = ($("hp-direction") && $("hp-direction").value) || "long";
    const d = await apiJson(
      "/api/hedge-plan/market?base=" +
        encodeURIComponent(state.underlying) +
        "&direction=" +
        encodeURIComponent(dir)
    );
    state.market = d;
    setGateLine(d.gates);
    const acctLabel = d.account_label || "合约账户";
    const tag = $("hp-perp-acct-tag");
    if (tag) tag.textContent = acctLabel;
    const amtPrec = d.amount_precision != null ? Number(d.amount_precision) : 4;
    const q = $("hp-perp-quote");
    if (q) {
      q.innerHTML =
        "<strong>" +
        (d.base || state.underlying) +
        "</strong> · " +
        acctLabel +
        "可用 <strong>" +
        fmt(d.available_usdt, 2) +
        "</strong> USDT<br/>标记 <strong>" +
        fmt(d.mark, 2) +
        "</strong> · 最新 " +
        fmt(d.last, 2) +
        " · 卖一 " +
        fmt(d.ask, 2) +
        " · 买一 " +
        fmt(d.bid, 2) +
        " · 面值 " +
        fmt(d.contract_size, 4) +
        " · 张精度 " +
        amtPrec +
        " 位";
    }
    const contractsInput = $("hp-contracts");
    if (contractsInput) {
      const step = amtPrec <= 0 ? "1" : String(Math.pow(10, -amtPrec));
      contractsInput.step = step;
    }
    const sz = $("hp-sizing-line");
    if (sz) {
      if (d.full_margin_sizing) {
        const s = d.full_margin_sizing;
        sz.textContent =
          "全仓建议(" +
          acctLabel +
          "):保证金 " +
          fmt(s.margin_capital, 2) +
          " USDT × " +
          s.leverage +
          "x → 名义 " +
          fmt(s.notional_value, 2) +
          " USDT · 建议 " +
          fmt(d.suggest_contracts, amtPrec) +
          " 合约张(已按交易所精度)";
      } else {
        sz.textContent = "非全仓或不具备保证金数据时仅手动填张数;永期开仓需全仓.";
      }
    }
    const entry = $("hp-entry");
    if (entry && d.entry_ref && !entry.value) entry.value = d.entry_ref;
    if (contractsInput && d.suggest_contracts != null && !contractsInput.value) {
      contractsInput.value = fmt(d.suggest_contracts, amtPrec);
    }
    const label = $("hp-opt-type-label");
    if (label) label.textContent = d.suggested_opt_type === "C" ? "Call" : "Put";
    updatePerpPnlHint();
  }

  function updatePerpPnlHint() {
    const el = $("hp-perp-pnl-line");
    if (!el) return;
    const entry = Number(($("hp-entry") && $("hp-entry").value) || NaN);
    const tp = Number(($("hp-tp") && $("hp-tp").value) || NaN);
    const sl = Number(($("hp-sl") && $("hp-sl").value) || NaN);
    const contracts = Number(($("hp-contracts") && $("hp-contracts").value) || NaN);
    const cs = Number((state.market && state.market.contract_size) || 0.01);
    const dir = (($("hp-direction") && $("hp-direction").value) || "long").toLowerCase();
    if (!(entry > 0) || !(contracts > 0) || !(cs > 0)) {
      el.textContent = "填写开仓价与张数后,输入止盈/止损可看永续盈亏金额(USDT)";
      return;
    }
    function pnlAt(exitPx) {
      const coins = contracts * cs;
      if (dir === "short") return (entry - exitPx) * coins;
      return (exitPx - entry) * coins;
    }
    const parts = [];
    if (tp > 0) {
      const p = pnlAt(tp);
      parts.push(
        "止盈预期 <strong class=\"" +
          (p >= 0 ? "hp-pnl-pos" : "hp-pnl-neg") +
          "\">" +
          (p >= 0 ? "+" : "") +
          fmt(p, 2) +
          " USDT</strong>"
      );
    } else {
      parts.push("止盈预期 —");
    }
    if (sl > 0) {
      const p = pnlAt(sl);
      parts.push(
        "止损预期 <strong class=\"" +
          (p >= 0 ? "hp-pnl-pos" : "hp-pnl-neg") +
          "\">" +
          (p >= 0 ? "+" : "") +
          fmt(p, 2) +
          " USDT</strong>"
      );
    } else {
      parts.push("止损预期 —");
    }
    el.innerHTML = parts.join(" · ");
  }

  function fillExpSelect(sel, chain) {
    if (!sel) return;
    const prev = sel.value;
    sel.innerHTML = '<option value="">选择到期日</option>';
    (chain.expiries || []).forEach(function (e) {
      const opt = document.createElement("option");
      opt.value = String(e.exp_time);
      const dt = new Date(Number(e.exp_time));
      opt.textContent = dt.toLocaleString();
      sel.appendChild(opt);
    });
    if (prev) sel.value = prev;
    if (!sel.value && chain.expiries && chain.expiries[0]) {
      sel.value = String(chain.expiries[0].exp_time);
    }
  }

  async function loadChain() {
    const d = await apiJson(
      "/api/hedge-plan/options-chain?underlying=" + encodeURIComponent(state.underlying)
    );
    state.chain = d;
    const uly = d.underlying || state.underlying;
    const idx = $("hp-index-line");
    if (idx) {
      idx.textContent =
        "指数 " + uly + " " + fmt(d.index_px, 2) + " · " + (d.inst_family || "") + " · 实值含平值";
    }
    const ooIdx = $("hp-oo-index");
    if (ooIdx) ooIdx.textContent = "指数 " + uly + " " + fmt(d.index_px, 2);
    setOptionsBalance(d);
    fillExpSelect($("hp-exp-select"), d);
    fillExpSelect($("hp-oo-exp-select"), d);
    renderListStrikes();
    renderTStrikes();
    if (d.index_px) {
      const idx = Number(d.index_px);
      if ($("hp-target-up") && !$("hp-target-up").value) {
        $("hp-target-up").value = String(Math.round(idx * 1.03));
      }
      if ($("hp-target-down") && !$("hp-target-down").value) {
        $("hp-target-down").value = String(Math.round(idx * 0.97));
      }
    }
  }

  function currentExp(selectId) {
    const sel = $(selectId);
    const expMs = sel && sel.value;
    if (!expMs || !state.chain) return null;
    return (state.chain.expiries || []).find(function (e) {
      return String(e.exp_time) === String(expMs);
    });
  }

  function pickContract(c) {
    if (!c) return;
    state.selected = c;
    const el = $("hp-sel-inst");
    if (el) el.textContent = c.inst_id;
    const tbody = $("hp-strike-tbody");
    if (tbody) {
      tbody.querySelectorAll(".opt-strike-row").forEach(function (r) {
        r.classList.toggle("opt-row-selected", r.getAttribute("data-inst") === c.inst_id);
      });
      tbody.querySelectorAll(".hp-pick").forEach(function (b) {
        b.classList.toggle("active", b.getAttribute("data-inst") === c.inst_id);
      });
    }
    updatePremiumLine();
  }

  function renderListStrikes() {
    const tbody = $("hp-strike-tbody");
    if (!tbody) return;
    const dir = ($("hp-direction") && $("hp-direction").value) || "long";
    const want = optTypeForDirection(dir);
    const exp = currentExp("hp-exp-select");
    const prevInst = state.selected && state.selected.inst_id;
    tbody.innerHTML = "";
    if (!exp) {
      tbody.innerHTML = '<tr><td colspan="5" class="muted">请选择到期日</td></tr>';
      return;
    }
    const list = (exp.contracts || []).filter(function (c) {
      return String(c.opt_type || "").toUpperCase() === want && matchesMoneyFilter(c);
    });
    if (!list.length) {
      tbody.innerHTML = '<tr><td colspan="5" class="muted">无匹配合约</td></tr>';
      return;
    }
    list.forEach(function (c) {
      const tr = document.createElement("tr");
      tr.className = "opt-strike-row" + (c.moneyness ? " opt-row-" + c.moneyness : "");
      if (prevInst && c.inst_id === prevInst) tr.classList.add("opt-row-selected");
      tr.setAttribute("data-inst", c.inst_id);
      tr.innerHTML =
        "<td>" +
        c.strike +
        "</td><td>" +
        moneynessBadge(c) +
        '</td><td class="opt-px-sz">' +
        fmtPxSz(c.ask, c.ask_sz, c.ask_estimated, c.tick_sz) +
        '</td><td class="opt-px-sz">' +
        fmtPxSz(c.bid, c.bid_sz, false, c.tick_sz) +
        '</td><td><button type="button" class="btn-secondary hp-pick' +
        (prevInst && c.inst_id === prevInst ? " active" : "") +
        '" data-inst="' +
        c.inst_id +
        '">选用</button></td>';
      tbody.appendChild(tr);
    });
    tbody.querySelectorAll(".hp-pick").forEach(function (btn) {
      btn.addEventListener("click", function () {
        const inst = btn.getAttribute("data-inst");
        const c = list.find(function (x) {
          return x.inst_id === inst;
        });
        pickContract(c);
      });
    });
  }

  function updatePremiumLine() {
    const line = $("hp-premium-line");
    if (!line || !state.selected) {
      if (line) line.textContent = "";
      return;
    }
    const sheets = Number(($("hp-sheets") && $("hp-sheets").value) || 1);
    const ct = Number(state.selected.ct_mult || 0.01);
    const ask = Number(state.selected.ask || 0);
    const prem = ask * sheets * ct;
    line.textContent = "预估权利金 ≈ " + fmt(prem, 4) + " USDC(期权账户)";
  }

  function buildStraddleRows(contracts) {
    const map = {};
    (contracts || []).forEach(function (c) {
      const key = String(c.strike);
      if (!map[key]) map[key] = { strike: c.strike, call: null, put: null };
      const o = (c.opt_type || "").toUpperCase();
      if (o === "C") map[key].call = c;
      else if (o === "P") map[key].put = c;
    });
    return Object.keys(map)
      .map(function (k) {
        return map[k];
      })
      .sort(function (a, b) {
        return Number(a.strike) - Number(b.strike);
      });
  }

  function renderTStrikes() {
    const tbody = $("hp-oo-tbody");
    if (!tbody) return;
    const exp = currentExp("hp-oo-exp-select");
    tbody.innerHTML = "";
    if (!exp) {
      tbody.innerHTML = '<tr><td colspan="7" class="muted">请选择到期日</td></tr>';
      return;
    }
    const rows = buildStraddleRows(exp.contracts);
    rows.forEach(function (row) {
      const tr = document.createElement("tr");
      const call = row.call;
      const put = row.put;
      const callAsk = call ? fmtPxSz(call.ask, call.ask_sz, call.ask_estimated, call.tick_sz) : "—";
      const putAsk = put ? fmtPxSz(put.ask, put.ask_sz, put.ask_estimated, put.tick_sz) : "—";
      tr.innerHTML =
        '<td class="opt-t-call opt-px-sz">' +
        callAsk +
        '</td><td class="opt-t-call">' +
        (call ? moneynessBadge(call) : "—") +
        "</td><td>" +
        (call
          ? '<button type="button" class="btn-secondary hp-oo-pick" data-side="C" data-inst="' +
            call.inst_id +
            '">Call</button>'
          : "—") +
        '</td><td class="opt-t-strike"><strong>' +
        row.strike +
        '</strong></td><td class="opt-t-put">' +
        (put ? moneynessBadge(put) : "—") +
        '</td><td class="opt-t-put opt-px-sz">' +
        putAsk +
        "</td><td>" +
        (put
          ? '<button type="button" class="btn-secondary hp-oo-pick" data-side="P" data-inst="' +
            put.inst_id +
            '">Put</button>'
          : "—") +
        "</td>";
      tbody.appendChild(tr);
    });
    tbody.querySelectorAll(".hp-oo-pick").forEach(function (btn) {
      btn.addEventListener("click", function () {
        const inst = btn.getAttribute("data-inst");
        const exp2 = currentExp("hp-oo-exp-select");
        const c = (exp2.contracts || []).find(function (x) {
          return x.inst_id === inst;
        });
        if (!c) return;
        if (!state.legA) state.legA = c;
        else if (!state.legB || state.legB.inst_id === state.legA.inst_id) state.legB = c;
        else {
          state.legA = c;
          state.legB = null;
        }
        renderOoLegs();
      });
    });
  }

  function renderOoLegs() {
    function fill(tag, c, infoId, sheetsId) {
      const info = $(infoId);
      const sheets = $(sheetsId);
      if (!info) return;
      if (!c) {
        info.textContent = tag + ": 尚未选用";
        if (sheets) {
          sheets.disabled = true;
          sheets.value = "1";
        }
        return;
      }
      info.innerHTML =
        tag +
        ": <strong>" +
        c.opt_type +
        " K" +
        c.strike +
        "</strong> " +
        (c.moneyness_label || "") +
        " · 卖一 " +
        fmtPxSz(c.ask, c.ask_sz, c.ask_estimated, c.tick_sz) +
        " <code>" +
        c.inst_id +
        "</code>";
      if (sheets) sheets.disabled = false;
    }
    fill("腿A", state.legA, "hp-oo-leg-a-info", "hp-oo-sheets-a");
    fill("腿B", state.legB, "hp-oo-leg-b-info", "hp-oo-sheets-b");
    updateOoPremiumLine();
  }

  function ooSheets(id) {
    const n = Number(($(id) && $(id).value) || 1);
    return n > 0 ? n : 1;
  }

  function updateOoPremiumLine() {
    const line = $("hp-oo-prem-line");
    if (!line) return;
    if (!state.legA && !state.legB) {
      line.textContent = "";
      return;
    }
    function prem(c, sheets) {
      if (!c) return 0;
      return Number(c.ask || 0) * sheets * Number(c.ct_mult || 0.01);
    }
    const a = prem(state.legA, ooSheets("hp-oo-sheets-a"));
    const b = prem(state.legB, ooSheets("hp-oo-sheets-b"));
    line.textContent =
      "预估权利金 A " +
      fmt(a, 4) +
      " + B " +
      fmt(b, 4) +
      " ≈ " +
      fmt(a + b, 4) +
      " USDC";
  }

  function legPayload(c, sheets) {
    return {
      opt_type: c.opt_type,
      strike: c.strike,
      sheets: sheets,
      ct_mult: c.ct_mult || 0.01,
      ask: c.ask,
      inst_id: c.inst_id,
    };
  }

  function setUnderlying(uly, forceReload) {
    const next = (uly || "ETH").toUpperCase();
    const changed = next !== state.underlying;
    state.underlying = next;
    syncUnderlyingUI();
    if (!changed && !forceReload) return;
    state.selected = null;
    state.legA = null;
    state.legB = null;
    if ($("hp-entry")) $("hp-entry").value = "";
    if ($("hp-contracts")) $("hp-contracts").value = "";
    if ($("hp-tp")) $("hp-tp").value = "";
    if ($("hp-sl")) $("hp-sl").value = "";
    if ($("hp-target-up")) $("hp-target-up").value = "";
    if ($("hp-target-down")) $("hp-target-down").value = "";
    if ($("hp-sel-inst")) $("hp-sel-inst").textContent = "—";
    if ($("hp-premium-line")) $("hp-premium-line").textContent = "";
    if ($("hp-oo-sheets-a")) {
      $("hp-oo-sheets-a").value = "1";
      $("hp-oo-sheets-a").disabled = true;
    }
    if ($("hp-oo-sheets-b")) {
      $("hp-oo-sheets-b").value = "1";
      $("hp-oo-sheets-b").disabled = true;
    }
    renderOoLegs();
    void refreshAll();
  }

  async function runPreview() {
    const isOo = state.mode === "options_options";
    const tbody = $(isOo ? "hp-result-tbody-oo" : "hp-result-tbody");
    const summary = $(isOo ? "hp-summary-oo" : "hp-summary");
    try {
      let body;
      if (isOo) {
        if (!state.legA || !state.legB) throw new Error("请选用两条期权腿");
        const up = Number(($("hp-target-up") && $("hp-target-up").value) || 0);
        const down = Number(($("hp-target-down") && $("hp-target-down").value) || 0);
        if (!up || !down) throw new Error("请填写上破与下破目标价");
        if (up <= down) throw new Error("上破目标价必须大于下破目标价");
        body = {
          plan_type: "options_options",
          target_price_up: up,
          target_price_down: down,
          target_price: up,
          index_px: (state.chain && state.chain.index_px) || (up + down) / 2,
          leg_a: legPayload(state.legA, ooSheets("hp-oo-sheets-a")),
          leg_b: legPayload(state.legB, ooSheets("hp-oo-sheets-b")),
        };
      } else {
        if (!state.selected) throw new Error("请选用期权腿");
        const entry = Number(($("hp-entry") && $("hp-entry").value) || 0);
        const tp = Number(($("hp-tp") && $("hp-tp").value) || 0);
        const sl = Number(($("hp-sl") && $("hp-sl").value) || 0);
        const contracts = Number(($("hp-contracts") && $("hp-contracts").value) || 0);
        const sheets = Number(($("hp-sheets") && $("hp-sheets").value) || 1);
        if (!entry || !tp || !sl || !contracts) throw new Error("请完整填写开仓/止盈/止损/张数");
        body = {
          plan_type: "perp_options",
          direction: ($("hp-direction") && $("hp-direction").value) || "long",
          entry: entry,
          tp: tp,
          sl: sl,
          contracts: contracts,
          contract_size: (state.market && state.market.contract_size) || 0.01,
          opt_type: state.selected.opt_type,
          strike: state.selected.strike,
          sheets: sheets,
          ct_mult: state.selected.ct_mult || 0.01,
          ask: state.selected.ask,
          index_px: state.chain && state.chain.index_px,
        };
      }
      const d = await apiJson("/api/hedge-plan/preview", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(body),
      });
      setGateLine(d.gates);
      const s = d.summary || {};
      if (summary) {
        if (d.plan_type === "perp_options") {
          summary.innerHTML =
            "止盈合计 <strong>" +
            fmt(s.tp_total) +
            "</strong> · 止损合计 <strong>" +
            fmt(s.sl_total) +
            "</strong> · 保费 " +
            fmt(s.premium_paid) +
            (s.hedge_ratio_at_sl != null ? " · 止损对冲率 " + fmt(s.hedge_ratio_at_sl) + "%" : "");
        } else {
          summary.innerHTML =
            "目标价合计 <strong>" +
            fmt(s.at_target_total) +
            "</strong> · 到期现价 <strong>" +
            fmt(s.expiry_flat_total) +
            "</strong> · 保费 " +
            fmt(s.premium_paid) +
            (s.expiry_is_loss ? " · 到期无盈利(记总亏损)" : "");
        }
      }
      if (!tbody) return;
      tbody.innerHTML = "";
      (d.scenarios || []).forEach(function (sc) {
        const tr = document.createElement("tr");
        let mid;
        if (sc.perp_pnl != null) {
          mid = "永续 " + fmt(sc.perp_pnl);
        } else {
          mid = "A " + fmt(sc.leg_a_pnl) + " / B " + fmt(sc.leg_b_pnl);
        }
        const optCol = sc.options_pnl != null ? fmt(sc.options_pnl) : "—";
        tr.innerHTML =
          "<td>" +
          (sc.label || sc.id) +
          "</td><td>" +
          fmt(sc.spot) +
          "</td><td>" +
          mid +
          "</td><td>" +
          optCol +
          "</td><td><strong>" +
          fmt(sc.total) +
          "</strong></td><td class=\"muted\">" +
          (sc.note || "") +
          "</td>";
        tbody.appendChild(tr);
      });
    } catch (e) {
      if (tbody) tbody.innerHTML = '<tr><td colspan="6" class="err">' + (e.message || e) + "</td></tr>";
      if (summary) summary.textContent = "";
    }
  }

  function bind() {
    document.querySelectorAll(".hp-tab").forEach(function (b) {
      b.addEventListener("click", function () {
        state.tab = b.getAttribute("data-tab") || "perp_options";
        syncTabUI();
        if (state.tab === "perp_options" || state.tab === "options_options") {
          void loadGates();
        } else if (state.tab === "active") {
          void loadActivePlans();
        } else if (state.tab === "history") {
          void loadHistory();
        } else if (state.tab === "stats") {
          void loadStats();
        } else {
          const el = $("hp-gate-line");
          if (el) el.textContent = "";
        }
      });
    });
    document.querySelectorAll(".hp-uly-btn, .hp-uly-btn-oo").forEach(function (b) {
      b.addEventListener("click", function () {
        setUnderlying(b.getAttribute("data-uly") || "ETH", true);
      });
    });
    document.querySelectorAll(".hp-money-btn").forEach(function (b) {
      b.addEventListener("click", function () {
        state.moneyFilter = b.getAttribute("data-money") || "all";
        syncMoneyUI();
        renderListStrikes();
      });
    });
    const dir = $("hp-direction");
    if (dir) {
      dir.addEventListener("change", function () {
        state.selected = null;
        if ($("hp-sel-inst")) $("hp-sel-inst").textContent = "—";
        void loadMarket().then(function () {
          renderListStrikes();
        });
      });
    }
    ["hp-entry", "hp-tp", "hp-sl", "hp-contracts"].forEach(function (id) {
      const el = $(id);
      if (el) el.addEventListener("input", updatePerpPnlHint);
    });
    if ($("hp-refresh"))
      $("hp-refresh").addEventListener("click", function () {
        void refreshAll();
      });
    if ($("hp-load-chain"))
      $("hp-load-chain").addEventListener("click", function () {
        void loadChain();
      });
    if ($("hp-oo-load-chain"))
      $("hp-oo-load-chain").addEventListener("click", function () {
        void loadChain();
      });
    if ($("hp-exp-select")) $("hp-exp-select").addEventListener("change", renderListStrikes);
    if ($("hp-oo-exp-select")) $("hp-oo-exp-select").addEventListener("change", renderTStrikes);
    if ($("hp-sheets")) $("hp-sheets").addEventListener("input", updatePremiumLine);
    ["hp-oo-sheets-a", "hp-oo-sheets-b"].forEach(function (id) {
      const el = $(id);
      if (el) el.addEventListener("input", updateOoPremiumLine);
    });
    if ($("hp-preview-btn"))
      $("hp-preview-btn").addEventListener("click", function () {
        state.mode = "perp_options";
        void runPreview();
      });
    if ($("hp-preview-btn-oo"))
      $("hp-preview-btn-oo").addEventListener("click", function () {
        state.mode = "options_options";
        void runPreview();
      });
    if ($("hp-start-btn"))
      $("hp-start-btn").addEventListener("click", function () {
        void startPlan("perp_options");
      });
    if ($("hp-start-btn-oo"))
      $("hp-start-btn-oo").addEventListener("click", function () {
        void startPlan("options_options");
      });
    if ($("hp-detail-close")) $("hp-detail-close").addEventListener("click", closeModal);
    const modal = $("hp-detail-modal");
    if (modal) {
      modal.addEventListener("click", function (ev) {
        if (ev.target === modal) closeModal();
      });
    }
  }

  async function loadHistory() {
    const tbody = $("hp-history-tbody");
    if (!tbody) return;
    try {
      const d = await apiJson("/api/hedge-plan/history");
      const rows = d.plans || [];
      if (!rows.length) {
        tbody.innerHTML = '<tr><td colspan="10" class="muted">暂无已结束计划</td></tr>';
        return;
      }
      tbody.innerHTML = "";
      rows.forEach(function (p) {
        const tr = document.createElement("tr");
        const typeLabel = p.plan_type === "perp_options" ? "永期" : "期期";
        const contracts = p.contracts_summary || "—";
        const pnl = p.realized_pnl_total;
        const pnlCls =
          pnl == null || Number.isNaN(Number(pnl)) ? "" : Number(pnl) >= 0 ? "hp-pnl-pos" : "hp-pnl-neg";
        tr.innerHTML =
          "<td>#" +
          p.id +
          "</td><td>" +
          typeLabel +
          "</td><td>" +
          (p.underlying || "") +
          "</td><td class=\"hp-contracts-cell\" title=\"" +
          String(contracts).replace(/"/g, "&quot;") +
          "\"><code>" +
          contracts +
          "</code></td><td>" +
          (p.status || "") +
          '</td><td class="' +
          pnlCls +
          '">' +
          fmt(pnl) +
          "</td><td>" +
          reasonLabel(p.close_reason) +
          "</td><td>" +
          (p.opened_at || "—") +
          "</td><td>" +
          (p.closed_at || "—") +
          '</td><td class="hp-hist-actions">' +
          '<button type="button" class="btn-secondary hp-btn-detail" data-id="' +
          p.id +
          '">成交细节</button> ' +
          '<button type="button" class="btn-secondary hp-btn-del" data-id="' +
          p.id +
          '">删除</button>' +
          "</td>";
        tbody.appendChild(tr);
      });
      tbody.querySelectorAll(".hp-btn-detail").forEach(function (btn) {
        btn.addEventListener("click", function () {
          void showPlanDetail(Number(btn.getAttribute("data-id")));
        });
      });
      tbody.querySelectorAll(".hp-btn-del").forEach(function (btn) {
        btn.addEventListener("click", function () {
          void deletePlan(Number(btn.getAttribute("data-id")));
        });
      });
    } catch (e) {
      tbody.innerHTML = '<tr><td colspan="10" class="err">' + (e.message || e) + "</td></tr>";
    }
  }

  function activeTargetLabel(p) {
    if (p.plan_type === "perp_options") {
      return "止盈 " + fmt(p.tp) + " · 止损 " + fmt(p.sl);
    }
    return "上破 " + fmt(p.target_price_up || p.target_price) + " · 下破 " + fmt(p.target_price_down || p.target_price);
  }

  async function loadActivePlans() {
    const tbody = $("hp-active-tbody");
    if (!tbody) return;
    try {
      const d = await apiJson("/api/hedge-plan/active");
      const rows = d.plans || [];
      if (!rows.length) {
        tbody.innerHTML = '<tr><td colspan="8" class="muted">暂无进行中的计划</td></tr>';
        return;
      }
      tbody.innerHTML = "";
      rows.forEach(function (p) {
        const tr = document.createElement("tr");
        const typeLabel = p.plan_type === "perp_options" ? "永期" : "期期";
        const contracts = p.contracts_summary || "—";
        tr.innerHTML =
          "<td>#" +
          p.id +
          "</td><td>" +
          typeLabel +
          "</td><td>" +
          (p.underlying || "") +
          "</td><td class=\"hp-contracts-cell\" title=\"" +
          String(contracts).replace(/"/g, "&quot;") +
          "\"><code>" +
          contracts +
          "</code></td><td>" +
          '<span class="hp-plan-active">进行中</span>' +
          "</td><td>" +
          activeTargetLabel(p) +
          "</td><td>" +
          (p.opened_at || "—") +
          '</td><td class="hp-hist-actions"><button type="button" class="btn-secondary hp-btn-detail" data-id="' +
          p.id +
          '">成交细节</button></td>';
        tbody.appendChild(tr);
      });
      tbody.querySelectorAll(".hp-btn-detail").forEach(function (btn) {
        btn.addEventListener("click", function () {
          void showPlanDetail(Number(btn.getAttribute("data-id")));
        });
      });
    } catch (e) {
      tbody.innerHTML = '<tr><td colspan="8" class="err">' + (e.message || e) + "</td></tr>";
    }
  }

  function reasonLabel(r) {
    const map = {
      perp_tp: "永续止盈",
      perp_sl: "永续止损",
      oo_expiry_loss: "期期到期亏损",
      oo_expiry_win: "期期到期盈利",
      target_win_leg: "期期平盈利腿",
      target_up_win_leg: "期期上破·平盈利腿",
      target_down_win_leg: "期期下破·平盈利腿",
      expiry: "到期",
      manual: "人工结束",
      partial_fail: "半腿失败",
      cancelled: "已取消",
    };
    return map[r] || r || "—";
  }

  function roleLabel(role) {
    const map = {
      perp: "永续腿",
      option_hedge: "保险期权",
      option_a: "期期腿A",
      option_b: "期期腿B",
    };
    return map[role] || role || "—";
  }

  function closeModal() {
    const m = $("hp-detail-modal");
    if (m) m.hidden = true;
  }

  async function showPlanDetail(planId) {
    const modal = $("hp-detail-modal");
    const body = $("hp-detail-body");
    const title = $("hp-detail-title");
    if (!modal || !body) return;
    modal.hidden = false;
    body.innerHTML = '<p class="muted">加载中…</p>';
    if (title) title.textContent = "成交细节 #" + planId;
    try {
      const d = await apiJson("/api/hedge-plan/" + planId);
      const p = d.plan || {};
      const legs = d.legs || [];
      const typeLabel = p.plan_type === "perp_options" ? "永期对冲" : "期期对冲";
      let html = "";
      html += '<div class="hp-detail-summary">';
      html += "<div><span class=\"muted\">类型</span> " + typeLabel + "</div>";
      html += "<div><span class=\"muted\">标的</span> " + (p.underlying || "—");
      if (p.direction) html += " · " + (p.direction === "long" ? "做多" : "做空");
      html += "</div>";
      html += "<div><span class=\"muted\">状态</span> " + (p.status || "—") + " / " + reasonLabel(p.close_reason) + "</div>";
      html += "<div><span class=\"muted\">时间</span> " + (p.opened_at || "—") + " → " + (p.closed_at || "—") + "</div>";
      html +=
        "<div><span class=\"muted\">盈亏</span> 永续 " +
        fmt(p.realized_pnl_perp) +
        " · 期权 " +
        fmt(p.realized_pnl_options) +
        " · 合计 <strong class=\"" +
        (Number(p.realized_pnl_total) >= 0 ? "hp-pnl-pos" : "hp-pnl-neg") +
        '">' +
        fmt(p.realized_pnl_total) +
        "</strong> ≈U</div>";
      if (p.plan_type === "perp_options") {
        html +=
          "<div><span class=\"muted\">参考价</span> 开 " +
          fmt(p.entry_mark) +
          " · 止盈 " +
          fmt(p.tp) +
          " · 止损 " +
          fmt(p.sl) +
          " · 杠杆 " +
          fmt(p.leverage, 0) +
          "x · 张数 " +
          fmt(p.perp_size, 4) +
          "</div>";
      } else {
        html +=
          "<div><span class=\"muted\">目标价</span> 上破 " +
          fmt(p.target_price_up || p.target_price) +
          " · 下破 " +
          fmt(p.target_price_down || p.target_price) +
          "</div>";
      }
      html +=
        "<div><span class=\"muted\">权利金合计</span> " +
        fmt(p.premium_total, 4) +
        " USDC</div>";
      html +=
        "<div><span class=\"muted\">合约摘要</span> <code>" +
        (d.contracts_summary || "—") +
        "</code></div>";
      html += "</div>";
      html += '<table class="options-strike-table hp-detail-legs"><thead><tr>';
      html +=
        "<th>角色</th><th>合约名称</th><th>方向/类型</th><th>数量</th><th>开仓价</th><th>权利金</th><th>状态</th><th>腿盈亏</th><th>成交号</th><th>平仓原因</th>";
      html += "</tr></thead><tbody>";
      if (!legs.length) {
        html += '<tr><td colspan="10" class="muted">无腿记录</td></tr>';
      } else {
        legs.forEach(function (leg) {
          const contract =
            leg.leg_role === "perp"
              ? leg.symbol || "—"
              : leg.inst_id || "—";
          const side =
            leg.leg_role === "perp"
              ? leg.side || "—"
              : (leg.opt_type || "") + (leg.strike != null ? " K" + fmt(leg.strike, 0) : "");
          html += "<tr>";
          html += "<td>" + roleLabel(leg.leg_role) + "</td>";
          html += "<td><code>" + contract + "</code></td>";
          html += "<td>" + side + "</td>";
          html += "<td>" + fmt(leg.size, leg.leg_role === "perp" ? 4 : 0) + "</td>";
          html += "<td>" + fmt(leg.avg_open, 4) + "</td>";
          html += "<td>" + (leg.premium != null ? fmt(leg.premium, 4) : "—") + "</td>";
          html += "<td>" + (leg.status || "—") + "</td>";
          html += "<td>" + fmt(leg.realized_pnl, 4) + "</td>";
          html += "<td><code class=\"hp-ord\">" + (leg.exchange_ord_id || "—") + "</code></td>";
          html += "<td>" + reasonLabel(leg.close_reason) + "</td>";
          html += "</tr>";
        });
      }
      html += "</tbody></table>";
      if (p.note) {
        html += '<p class="hp-detail-note"><span class="muted">备注</span> ' + String(p.note) + "</p>";
      }
      body.innerHTML = html;
    } catch (e) {
      body.innerHTML = '<p class="err">' + (e.message || e) + "</p>";
    }
  }

  async function deletePlan(planId) {
    if (!window.confirm("确认删除历史计划 #" + planId + "？此操作不可恢复。")) return;
    try {
      await apiJson("/api/hedge-plan/" + planId, { method: "DELETE" });
      await loadHistory();
      if (state.tab === "stats") await loadStats();
    } catch (e) {
      window.alert(e.message || String(e));
    }
  }

  function metricCard(title, m) {
    if (!m || !m.count) {
      return (
        '<div class="hp-stats-card"><h3>' +
        title +
        '</h3><p class="muted">暂无已结束样本</p></div>'
      );
    }
    const wr = m.win_rate == null ? "—" : (Number(m.win_rate) * 100).toFixed(1) + "%";
    let pf = "—";
    if (m.profit_factor_infinite) pf = "∞";
    else if (m.profit_factor != null) pf = fmt(m.profit_factor, 2);
    return (
      '<div class="hp-stats-card"><h3>' +
      title +
      "</h3><ul class=\"hp-stats-list\">" +
      "<li><span>笔数</span><strong>" +
      m.count +
      "</strong></li>" +
      "<li><span>胜率</span><strong>" +
      wr +
      "</strong> <span class=\"muted\">(" +
      m.wins +
      "/" +
      m.count +
      ")</span></li>" +
      "<li><span>净盈亏≈U</span><strong class=\"" +
      (Number(m.net_pnl) >= 0 ? "hp-pnl-pos" : "hp-pnl-neg") +
      '">' +
      fmt(m.net_pnl) +
      "</strong></li>" +
      "<li><span>盈亏比</span><strong>" +
      pf +
      "</strong> <span class=\"muted\">毛利/|毛亏|</span></li>" +
      "<li><span>最大盈利</span><strong class=\"hp-pnl-pos\">" +
      fmt(m.max_profit) +
      "</strong></li>" +
      "<li><span>最大亏损</span><strong class=\"hp-pnl-neg\">" +
      fmt(m.max_loss) +
      "</strong></li>" +
      "<li><span>最大回撤</span><strong>" +
      fmt(m.max_drawdown) +
      "</strong></li>" +
      "<li><span>平均保费</span><strong>" +
      fmt(m.avg_premium, 4) +
      "</strong></li>" +
      "</ul></div>"
    );
  }

  async function loadStats() {
    const box = $("hp-stats-box");
    if (!box) return;
    try {
      const d = await apiJson("/api/hedge-plan/stats");
      const by = d.by_type || {};
      let html = '<div class="hp-stats-grid">';
      html +=
        '<div class="hp-stats-card hp-stats-card--overview"><h3>总览</h3><p>活跃 <strong>' +
        (d.active || 0) +
        "</strong> · 已结 <strong>" +
        (d.closed_count || 0) +
        '</strong> · 合计 <strong class="' +
        (Number(d.closed_pnl_total) >= 0 ? "hp-pnl-pos" : "hp-pnl-neg") +
        '">' +
        fmt(d.closed_pnl_total) +
        "</strong> ≈U</p></div>";
      html += metricCard("永期对冲", by.perp_options);
      html += metricCard("期期对冲", by.options_options);
      html += "</div>";
      const poB = (by.perp_options && by.perp_options.buckets) || {};
      const ooB = (by.options_options && by.options_options.buckets) || {};
      if ((poB.tp && poB.tp.count) || (poB.sl && poB.sl.count) || (ooB.expiry_loss && ooB.expiry_loss.count)) {
        html += '<div class="hp-stats-grid hp-stats-grid--sub">';
        if (poB.tp && poB.tp.count) html += metricCard("永期·止盈桶", poB.tp);
        if (poB.sl && poB.sl.count) html += metricCard("永期·止损桶", poB.sl);
        if (ooB.expiry_loss && ooB.expiry_loss.count) html += metricCard("期期·到期亏损", ooB.expiry_loss);
        if (ooB.expiry_win && ooB.expiry_win.count) html += metricCard("期期·到期盈利", ooB.expiry_win);
        html += "</div>";
      }
      box.innerHTML = html;
    } catch (e) {
      box.textContent = e.message || String(e);
    }
  }

  async function startPlan(planType) {
    const isOo = planType === "options_options";
    try {
      let body;
      if (isOo) {
        if (!state.legA || !state.legB) throw new Error("请选用两条期权腿");
        const up = Number(($("hp-target-up") && $("hp-target-up").value) || 0);
        const down = Number(($("hp-target-down") && $("hp-target-down").value) || 0);
        if (!up || !down) throw new Error("请填写上破与下破目标价");
        if (up <= down) throw new Error("上破目标价必须大于下破目标价");
        body = {
          plan_type: "options_options",
          underlying: state.underlying,
          target_price_up: up,
          target_price_down: down,
          target_price: up,
          leg_a: legPayload(state.legA, ooSheets("hp-oo-sheets-a")),
          leg_b: legPayload(state.legB, ooSheets("hp-oo-sheets-b")),
        };
      } else {
        if (!state.selected) throw new Error("请选用期权腿");
        const entry = Number(($("hp-entry") && $("hp-entry").value) || 0);
        const tp = Number(($("hp-tp") && $("hp-tp").value) || 0);
        const sl = Number(($("hp-sl") && $("hp-sl").value) || 0);
        const contracts = Number(($("hp-contracts") && $("hp-contracts").value) || 0);
        const sheets = Number(($("hp-sheets") && $("hp-sheets").value) || 1);
        if (!entry || !tp || !sl || !contracts) throw new Error("请完整填写开仓/止盈/止损/张数");
        body = {
          plan_type: "perp_options",
          underlying: state.underlying,
          direction: ($("hp-direction") && $("hp-direction").value) || "long",
          entry: entry,
          tp: tp,
          sl: sl,
          contracts: contracts,
          sheets: sheets,
          opt_inst_id: state.selected.inst_id,
          opt_type: state.selected.opt_type,
          strike: state.selected.strike,
          exchange_symbol: (state.market && state.market.exchange_symbol) || "",
          leverage: 10,
          margin: state.market && state.market.full_margin_sizing && state.market.full_margin_sizing.margin_capital,
        };
      }
      if (!window.confirm("确认启动对冲计划并真实下单?\n(将按期权账户/合约账户分别下单)")) return;
      const d = await apiJson("/api/hedge-plan/start", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(body),
      });
      setGateLine(d.gates);
      alert("计划已启动 #" + (d.plan_id || "") + (d.dry_run ? " (dry_run)" : ""));
      void loadGates();
    } catch (e) {
      alert(e.message || String(e));
    }
  }

  async function refreshAll() {
    if (state.tab === "perp_options" || state.tab === "options_options") {
      await loadGates();
    }
    try {
      await loadMarket();
    } catch (e) {
      const q = $("hp-perp-quote");
      if (q) q.textContent = e.message || String(e);
    }
    try {
      await loadChain();
    } catch (e) {
      const tbody = $("hp-strike-tbody");
      if (tbody) tbody.innerHTML = '<tr><td colspan="5" class="err">' + (e.message || e) + "</td></tr>";
    }
  }

  syncTabUI();
  syncUnderlyingUI();
  syncMoneyUI();
  bind();
  void refreshAll();
})();
