import { useEffect, useState } from "react";
import { apiFetch, MarketSnapshot, PlanState } from "../api/client";
import { fmtBidLiqEx, fmtExPx, fmtTopEx } from "../format";

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

/** 期权杠杆 = 标的 ÷ 权利金 */
function optionLevLabel(
  underlying: number | null | undefined,
  premium: number | null | undefined,
) {
  if (
    underlying == null ||
    premium == null ||
    !Number.isFinite(underlying) ||
    !Number.isFinite(premium) ||
    underlying <= 0 ||
    premium <= 0
  ) {
    return "—";
  }
  return `${(underlying / premium).toFixed(0)}x`;
}

function pnlClass(n: number | null | undefined) {
  if (n == null || Number.isNaN(n) || n === 0) return "";
  return n > 0 ? "pos-pnl-profit" : "pos-pnl-loss";
}

/** OKX 期权到期：YYMMDD 当日 08:00 UTC（上海 16:00） */
function expiryMsFromYmd(ymd: string | null | undefined): number | null {
  if (!ymd || ymd.length !== 6) return null;
  const yy = 2000 + Number(ymd.slice(0, 2));
  const mm = Number(ymd.slice(2, 4));
  const dd = Number(ymd.slice(4, 6));
  if (![yy, mm, dd].every((x) => Number.isFinite(x))) return null;
  return Date.UTC(yy, mm - 1, dd, 8, 0, 0);
}

function formatCountdown(msLeft: number): string {
  if (msLeft <= 0) return "已到期";
  const s = Math.floor(msLeft / 1000);
  const d = Math.floor(s / 86400);
  const h = Math.floor((s % 86400) / 3600);
  const m = Math.floor((s % 3600) / 60);
  const sec = s % 60;
  if (d > 0) return `${d}天 ${h}时 ${String(m).padStart(2, "0")}分`;
  if (h > 0) return `${h}时 ${String(m).padStart(2, "0")}分 ${String(sec).padStart(2, "0")}秒`;
  return `${m}分 ${String(sec).padStart(2, "0")}秒`;
}

/** 上海时区开仓时间 */
function fmtOpenTime(ms: number | null | undefined) {
  if (ms == null || !Number.isFinite(ms) || ms <= 0) return "—";
  return new Date(ms).toLocaleString("zh-CN", {
    timeZone: "Asia/Shanghai",
    hour12: false,
    month: "2-digit",
    day: "2-digit",
    hour: "2-digit",
    minute: "2-digit",
    second: "2-digit",
  });
}

/** 持仓时长（实时） */
function fmtHoldDuration(openAtMs: number | null | undefined, now: number) {
  if (openAtMs == null || !Number.isFinite(openAtMs) || openAtMs <= 0) return "—";
  const ms = Math.max(0, now - openAtMs);
  const totalSec = Math.floor(ms / 1000);
  const h = Math.floor(totalSec / 3600);
  const m = Math.floor((totalSec % 3600) / 60);
  const s = totalSec % 60;
  if (h > 0) return `${h}时${m}分${s}秒`;
  if (m > 0) return `${m}分${s}秒`;
  return `${s}秒`;
}

const PHASE_ZH: Record<string, string> = {
  idle: "空闲",
  wait_signal: "等待信号",
  opening: "开仓中",
  open: "持仓中",
  closing: "平仓中",
  resting: "休息中",
  paused: "已暂停",
  stopped: "已停开",
  outside_window: "窗外",
  liquidity_wait: "流动性等待",
  weekend_skip: "周末跳过",
  wait_funds: "资金不足",
};

function fmtBidLiquidity(
  bidPx: number | null | undefined,
  bidSzEth: number | null | undefined,
): string {
  if (bidPx == null && bidSzEth == null) return "—";
  const px = bidPx == null ? "—" : fmtExPx("option", bidPx);
  const sz = bidSzEth == null ? "—" : fmt(bidSzEth, 2);
  return `${px} / ${sz}`;
}

export default function PlanPage() {
  const [snap, setSnap] = useState<MarketSnapshot | null>(null);
  const [plan, setPlan] = useState<PlanState | null>(null);
  const [err, setErr] = useState("");
  const [busy, setBusy] = useState("");
  const [residualBusy, setResidualBusy] = useState("");
  const [nowMs, setNowMs] = useState(() => Date.now());

  async function refresh() {
    try {
      const [m, p] = await Promise.all([
        apiFetch<MarketSnapshot>("/api/market/snapshot"),
        apiFetch<PlanState>("/api/plan/state"),
      ]);
      setSnap(m);
      setPlan(p);
      setErr("");
    } catch (e) {
      setErr(e instanceof Error ? e.message : String(e));
    }
  }

  useEffect(() => {
    refresh();
    const t = window.setInterval(refresh, 1500);
    return () => window.clearInterval(t);
  }, []);

  useEffect(() => {
    const t = window.setInterval(() => setNowMs(Date.now()), 1000);
    return () => window.clearInterval(t);
  }, []);

  async function act(path: string, label: string) {
    setBusy(label);
    setErr("");
    try {
      await apiFetch(path, { method: "POST", body: "{}" });
      await refresh();
    } catch (e) {
      setErr(e instanceof Error ? e.message : String(e));
    } finally {
      setBusy("");
    }
  }

  async function closeResidual(groupId: string, optionInstId: string) {
    const ok = window.confirm(
      `确认平掉残留期权？\n\n组：${groupId}\n合约：${optionInstId}\n\n仅校验买一流动性，不要求权利金回收比例。`,
    );
    if (!ok) return;
    setResidualBusy(groupId);
    setErr("");
    try {
      await apiFetch("/api/plan/residual/close", {
        method: "POST",
        body: JSON.stringify({ group_id: groupId }),
      });
      await refresh();
    } catch (e) {
      setErr(e instanceof Error ? e.message : String(e));
    } finally {
      setResidualBusy("");
    }
  }

  const bias = snap?.ask_compare?.bias;
  const biasTag =
    bias === "strike_below_spot" ||
    bias === "call_ask_gt_put" ||
    bias === "fixed_short_call" ? (
      <span className="tag up">买 Call + 永续空</span>
    ) : bias === "strike_above_spot" ||
      bias === "put_ask_gt_call" ||
      bias === "fixed_long_put" ? (
      <span className="tag down">买 Put + 永续多</span>
    ) : (
      <span className="tag">等待 / 相等</span>
    );

  const pos = plan?.position;
  const isOo =
    plan?.hedge_mode === "option_option" ||
    snap?.hedge_mode === "option_option" ||
    pos?.hedge_mode === "option_option" ||
    !!pos?.option2_inst_id;
  const open = !!pos?.has_position;
  const exitMode = plan?.exit_mode ?? "fixed_usdt";
  const riskBased =
    plan?.risk_based === true || plan?.sizing_mode === "risk_based";
  const riskLocked =
    open &&
    (plan?.risk_sizing_locked === true ||
      plan?.risk_sizing_preview?.locked === true);
  const riskLiveOk =
    !riskBased || riskLocked || plan?.risk_sizing_preview?.ok === true;
  const displayPerpQty = riskLiveOk ? (plan?.perp_qty_eth ?? 1) : null;
  const displayOptQty = riskLiveOk ? (plan?.option_qty_eth ?? 2) : null;
  const exitTarget = riskLiveOk
    ? (plan?.exit_target_usdt ?? plan?.net_profit_target ?? 15)
    : null;
  const netPnl = pos?.net_pnl ?? 0;
  const movePct = pos?.move_pct ?? 0;
  const ooRatio = Number(plan?.oo_reward_ratio ?? 2);
  const ooBudget = plan?.risk_sizing_preview?.budget;
  const exitRuleLabel = isOo
    ? exitTarget != null
      ? `${riskLocked ? "锁定 " : ""}净盈≥${fmt(exitTarget)} U（${
          ooBudget != null ? `${fmt(ooBudget)}×` : "预算×"
        }${fmt(ooRatio, 1)}）`
      : `净盈≥预算×${fmt(ooRatio, 1)}（达标只平盈利腿）`
    : exitMode === "premium_multiple"
      ? `权利金×${fmt(plan?.premium_exit_multiple ?? 1, 2)}`
      : riskBased
        ? exitTarget != null
          ? `${riskLocked ? "锁定 " : "固定 "}${fmt(exitTarget)} U（基数${fmt(plan?.risk_exit_unit ?? 15)}）`
          : `待估算（基数${fmt(plan?.risk_exit_unit ?? 15)}）`
        : `固定 ${fmt(plan?.net_profit_target ?? 15)} U`;
  const riskRatioLabel = isOo
    ? "预算平分 Call/Put"
    : `比例${Number(plan?.risk_perp_unit ?? 1)}:${Number(plan?.risk_option_unit ?? 2)}`;
  const sizingModeLabel = riskBased
    ? [
        isOo ? "期期对冲" : "以损定仓",
        riskRatioLabel,
        !isOo && plan?.risk_last_k != null
          ? `k=${fmt(plan.risk_last_k, 1)}`
          : null,
        riskLocked
          ? exitTarget != null
            ? `目标锁定${fmt(exitTarget, 2)}U`
            : "目标已锁定"
          : plan?.risk_sizing_preview?.budget != null
            ? `预算${fmt(plan.risk_sizing_preview.budget, 2)}U`
            : null,
        plan?.martingale_enabled &&
        (plan?.martingale_doubles ?? 0) > 0 &&
        !riskLocked
          ? `倍投×${2 ** Number(plan.martingale_doubles)}(${fmt(plan.risk_effective_loss_pct ?? plan.risk_loss_pct ?? 0, 2)}%)`
          : plan?.martingale_enabled && !riskLocked
            ? "倍投开"
            : null,
        !riskLocked && plan?.risk_sizing_preview?.ok === false
          ? String(plan.risk_sizing_preview.detail || "预览失败")
          : null,
      ]
        .filter(Boolean)
        .join("  ")
    : isOo
      ? "期期对冲"
      : "手动仓位";
  const phaseLabel = PHASE_ZH[plan?.phase || ""] || plan?.phase || "—";
  const atmRule = plan?.fixed_direction_enabled
    ? plan?.fixed_perp_side === "short"
      ? "固定：永续空+买Call(实/平)"
      : "固定：永续多+买Put(实/平)"
    : plan?.atm_open_offset_enabled
      ? `ATM偏差≤${fmt(plan?.max_atm_open_offset ?? 3, 0)}`
      : "ATM偏差关";
  const ooSelectLabel = [
    plan?.oo_amplitude_filter_enabled
      ? `振幅≤${fmt(plan?.oo_amplitude_pct ?? 1.5, 1)}%/${fmt(plan?.oo_amplitude_hours ?? 12, 0)}h`
      : `振幅回看${fmt(plan?.oo_amplitude_hours ?? 12, 0)}h(过滤关)`,
    `贴高低≤${fmt(plan?.oo_strike_max_dev_pct ?? 1, 1)}%`,
    "虚值Call@高·Put@低",
    `剩余≥${fmt(plan?.oo_min_option_hours ?? 24, 0)}h`,
    `杠杆≥${fmt(plan?.oo_min_leverage ?? 200, 0)}x`,
    displayOptQty != null
      ? `Call${fmt(displayOptQty, 1)}/Put${fmt(
          Number(
            plan?.risk_sizing_preview?.put_qty_eth ??
              plan?.oo_put_qty_eth ??
              displayOptQty,
          ),
          1,
        )}ETH`
      : null,
  ]
    .filter(Boolean)
    .join(" · ");
  const exitDetail = isOo
    ? `净盈利≥预算×${fmt(ooRatio, 1)} → 只平盈利腿，亏损腿残留`
    : exitMode === "premium_multiple"
      ? `净盈利≥初始权利金×${fmt(plan?.premium_exit_multiple ?? 1, 2)}`
      : `净盈利≥${fmt(plan?.net_profit_target ?? 15)} U`;
  const expiryMs =
    pos?.expiry_ms ?? expiryMsFromYmd(pos?.expiry_ymd) ?? null;
  const countdown =
    open && expiryMs != null ? formatCountdown(expiryMs - nowMs) : "—";
  const countdownUrgent =
    open && expiryMs != null && expiryMs - nowMs > 0 && expiryMs - nowMs < 6 * 3600_000;

  const venueShort =
    plan?.mode === "LIVE"
      ? `实盘·${(snap?.exchange || "okx").toUpperCase()}`
      : "模拟盘";
  const openAtMs = pos?.open_at_ms ?? null;
  const openTimeLabel = fmtOpenTime(openAtMs);
  const holdDurationLabel = open ? fmtHoldDuration(openAtMs, nowMs) : "—";

  return (
    <div className="plan-page">
      {/* 手机端一屏监控卡：状态 / 净利 / 倒计时 */}
      <section className="plan-mobile-hero" aria-label="监控摘要">
        <div className="plan-mobile-hero-top">
          <span
            className={
              plan?.running
                ? "plan-pill plan-pill-on"
                : plan?.phase === "paused"
                  ? "plan-pill plan-pill-pause"
                  : "plan-pill plan-pill-off"
            }
          >
            {plan?.running ? "启动中" : plan?.phase === "paused" ? "已暂停" : "已停"}
          </span>
          <span className="plan-pill plan-pill-muted mono">{venueShort}</span>
          <span className="plan-mobile-phase mono">{phaseLabel}</span>
        </div>
        <div className="plan-mobile-hero-pnl">
          <div className="plan-mobile-pnl-block">
            <span className="plan-mobile-label">净盈利</span>
            <span className={`plan-mobile-pnl-num mono ${pnlClass(open ? netPnl : null)}`}>
              {open ? fmt(netPnl) : "—"}
            </span>
            <span className="plan-mobile-sub mono">
              目标 {exitTarget != null ? `${fmt(exitTarget)} U` : "—"}
            </span>
          </div>
          <div className="plan-mobile-pnl-block">
            <span className="plan-mobile-label">到期</span>
            <span
              className={`plan-mobile-countdown mono ${countdownUrgent ? "pos-countdown-urgent" : ""}`}
            >
              {countdown}
            </span>
            <span className="plan-mobile-sub mono">
              {open ? pos?.group_id || "持仓中" : "空仓"}
            </span>
          </div>
        </div>
        {plan?.last_error ? (
          <div className="plan-mobile-err">{plan.last_error}</div>
        ) : null}
      </section>

      {err ? <div className="err">{err}</div> : null}

      <div className="plan-rules-fold">
        <details>
          <summary>规则说明</summary>
          <div className="plan-rules-body">
            <p>
              <span className="plan-rules-k">行情</span>
              {String(plan?.exchange || "okx").toUpperCase()} · ETH-USDT-SWAP
            </p>
            <p>
              <span className="plan-rules-k">模式</span>
              {sizingModeLabel}
            </p>
            <p>
              <span className="plan-rules-k">开仓</span>
              {isOo ? (
                <>
                  {ooSelectLabel}
                  {plan?.skip_weekends ? " · 周末跳过开仓" : ""}
                  {plan?.one_expiry_per_day !== false
                    ? " · 每个到期只开一次"
                    : ""}
                </>
              ) : (
                <>
                  永续{" "}
                  {displayPerpQty != null
                    ? `${fmt(displayPerpQty, 2)} ETH`
                    : "—"}{" "}
                  / {fmt(plan?.leverage, 0)}x
                  · 期权{" "}
                  {displayOptQty != null
                    ? `${fmt(displayOptQty, 2)} ETH`
                    : "—"}{" "}
                  名义 · 剩余≥
                  {fmt(plan?.min_option_hours, 0)}h · 期权杠杆≥
                  {fmt(plan?.min_option_leverage, 0)}x · {atmRule}
                  {plan?.skip_weekends ? " · 周末跳过开仓" : ""}
                  {plan?.one_expiry_per_day !== false
                    ? " · 每个到期只开一次"
                    : ""}
                </>
              )}
            </p>
            <p>
              <span className="plan-rules-k">平仓</span>
              {isOo
                ? `${exitDetail}；否则到期结算`
                : `${exitDetail} → 双腿全平；期权远虚则只平永续、期权到期结算；未达标拖到期`}
            </p>
            <p>
              <span className="plan-rules-k">节奏</span>
              组间休息 {plan?.rest_seconds ?? "—"}s · 可开判定看交易账户
              {plan?.one_expiry_per_day !== false
                ? " · 同到期用过后改开下一到期"
                : ""}
            </p>
          </div>
        </details>
      </div>

      <div className="plan-actions">
        <button
          className={plan?.running ? "btn btn-running" : "btn"}
          type="button"
          disabled={
            !!busy ||
            !!plan?.running ||
            (plan?.mode === "LIVE" && plan.live_ready === false)
          }
          title={
            plan?.mode === "LIVE" && plan.live_ready === false
              ? plan.live_ready_reason || "LIVE 未就绪"
              : undefined
          }
          onClick={() => act("/api/plan/start", "start")}
        >
          {plan?.running ? "启动中" : "启动策略"}
        </button>
        <button
          className="btn ghost"
          type="button"
          disabled={!!busy || !plan?.running}
          onClick={() => act("/api/plan/pause", "pause")}
        >
          暂停
        </button>
        {plan?.show_manual_trade_buttons ? (
          <>
            <button
              className="btn ghost"
              type="button"
              disabled={
                !!busy ||
                !!plan?.running ||
                (plan?.mode === "LIVE" && plan.live_ready === false)
              }
              title={
                plan?.running
                  ? "策略自动运行中，禁止手动开仓"
                  : plan?.mode === "LIVE" && plan.live_ready === false
                    ? plan.live_ready_reason || "LIVE 未就绪"
                    : undefined
              }
              onClick={() => act("/api/sim/open-group", "open")}
            >
              手动开一组
            </button>
            <button
              className="btn ghost"
              type="button"
              disabled={!!busy}
              onClick={() => act("/api/sim/close-group", "close")}
            >
              手动全平
            </button>
          </>
        ) : null}
        <button
          className="btn danger"
          type="button"
          disabled={!!busy}
          onClick={() => act("/api/plan/emergency-close", "emg")}
        >
          紧急全平
        </button>
        {busy ? <span className="meta">{busy}…</span> : null}
      </div>

      <div className="plan-shell">
        <div className="plan-board">
          <div className="card plan-strategy">
            <h3 className="plan-panel-title">策略</h3>
            <div className="plan-metrics">
              <div className="kv">
                <span>状态</span>
                <span>
                  {plan?.running ? (
                    <span className="status-running">启动中</span>
                  ) : (
                    <span className="status-stopped">已停</span>
                  )}
                  <span className="mono">
                    {" "}
                    · {phaseLabel} · 已完成 {plan?.rounds_done ?? 0} 组
                  </span>
                </span>
              </div>
              <div className="kv">
                <span>模式</span>
                <span className="mono">
                  {riskBased ? (
                    <span className="status-running">{sizingModeLabel}</span>
                  ) : (
                    sizingModeLabel
                  )}
                </span>
              </div>
              <div className="kv">
                <span>选约条件</span>
                <span className="mono">
                  {isOo ? (
                    ooSelectLabel
                  ) : (
                    <>
                      永续
                      {displayPerpQty != null
                        ? `${fmt(displayPerpQty, 2)}ETH`
                        : "—"}
                      /期权
                      {displayOptQty != null
                        ? `${fmt(displayOptQty, 2)}ETH`
                        : "—"}{" "}
                      · 剩余≥
                      {fmt(plan?.min_option_hours, 0)}h · 期权杠杆≥
                      {fmt(plan?.min_option_leverage, 0)}x
                      {plan?.fixed_direction_enabled
                        ? plan?.fixed_perp_side === "short"
                          ? " · 固定空+Call(实/平)"
                          : " · 固定多+Put(实/平)"
                        : plan?.atm_open_offset_enabled
                          ? ` · ATM偏差≤${fmt(plan?.max_atm_open_offset ?? 3, 0)}`
                          : " · ATM偏差关"}
                    </>
                  )}
                </span>
              </div>
              <div className="kv">
                <span>休息</span>
                <span className="mono">
                  {plan?.rest_left_sec ? `${plan.rest_left_sec}s / ${plan.rest_seconds}s` : "—"}
                </span>
              </div>
              <div className="kv">
                <span>权益 / 杠杆</span>
                <span className="open-cap-row">
                  <span
                    className={
                      plan?.open_capacity?.perp_can_open === true
                        ? "open-cap-ok"
                        : plan?.open_capacity?.perp_can_open === false
                          ? "open-cap-bad"
                          : "mono"
                    }
                    title={
                      plan?.open_capacity?.perp_need_usdt != null
                        ? `需≈${plan.open_capacity.perp_need_usdt}U / 有${plan.open_capacity.perp_have_usdt ?? "—"}U`
                        : undefined
                    }
                  >
                    {plan?.open_capacity?.perp_label ||
                      `永续${fmt(plan?.leverage, 0)}x —`}
                  </span>
                  <span className="open-cap-sep">·</span>
                  <span
                    className={
                      plan?.open_capacity?.option_can_open === true
                        ? "open-cap-ok"
                        : plan?.open_capacity?.option_can_open === false
                          ? "open-cap-bad"
                          : "mono"
                    }
                    title={
                      plan?.open_capacity?.option_need_usdc != null
                        ? `需≈${plan.open_capacity.option_need_usdc}U / 有${plan.open_capacity.option_have_usdc ?? "—"}U`
                        : undefined
                    }
                  >
                    {plan?.open_capacity?.option_label || "期权 —"}
                  </span>
                </span>
              </div>
              {isOo ? (
                <div className="kv">
                  <span>开仓结构</span>
                  <span className="mono">
                    <span className="tag">买 Call + 买 Put</span>
                    <span className="meta"> · 不按永期方向信号</span>
                  </span>
                </div>
              ) : (
                <div className="kv">
                  <span>信号方向</span>
                  <span className="mono">{biasTag}</span>
                </div>
              )}
              <div className="kv">
                <span>出场规则</span>
                <span className="mono">{exitRuleLabel}</span>
              </div>
              <div className="kv">
                <span>净盈利 / 目标</span>
                <span className="mono">
                  <span className={pnlClass(open ? netPnl : null)}>
                    {open ? fmt(netPnl) : "—"}
                  </span>
                  {" / "}
                  {open || exitMode === "fixed_usdt" || isOo
                    ? exitTarget != null
                      ? fmt(exitTarget)
                      : "—"
                    : "—"}
                </span>
              </div>
              <div className="kv">
                <span>{isOo ? "Call/Put 浮盈" : "永续/期权浮盈"}</span>
                <span className="mono">
                  <span className={pnlClass(pos?.perp_upl)}>
                    {fmt(isOo ? pos?.option_upl : pos?.perp_upl)}
                  </span>
                  {" / "}
                  <span className={pnlClass(isOo ? pos?.option2_upl : pos?.option_upl)}>
                    {fmt(isOo ? pos?.option2_upl : pos?.option_upl)}
                  </span>
                </span>
              </div>
              {plan?.mode === "LIVE" && open ? (
                <>
                  <div className="kv">
                    <span>已付手续费</span>
                    <span className="mono">{fmt(pos?.fees_paid)}</span>
                  </div>
                  <div className="kv">
                    <span>资金费</span>
                    <span className={`mono ${pnlClass(pos?.funding_usdt)}`}>
                      {fmt(pos?.funding_usdt)}
                    </span>
                  </div>
                </>
              ) : null}
              {plan?.last_error ? (
                <div className="kv">
                  <span>最近错误</span>
                  <span className="err" style={{ margin: 0 }}>
                    {plan.last_error}
                  </span>
                </div>
              ) : null}
            </div>
          </div>

          <div className="plan-positions">
            {open ? (
              <>
                {isOo ? (
                  <>
                    <div className="pos-card">
                      <div className="pos-card-head">
                        <div className="pos-card-symbol">
                          <strong>{pos?.option_inst_id || "Call"}</strong>
                          <span className="pos-side-badge pos-side-long">
                            看涨 Call
                          </span>
                        </div>
                        <div
                          className={`pos-countdown mono ${countdownUrgent ? "pos-countdown-urgent" : ""}`}
                          title="到期倒计时"
                        >
                          {countdown}
                        </div>
                      </div>
                      <div className="pos-meta">
                        <span className="pos-meta-item">期期 · Call</span>
                        <span className="pos-meta-item">
                          到期 {pos?.expiry_ymd || "—"}
                        </span>
                        <span className="pos-meta-item">
                          行权{" "}
                          {pos?.strike != null
                            ? Math.round(Number(pos.strike))
                            : "—"}
                        </span>
                        <span className="pos-meta-item mono">
                          {fmt(pos?.option_qty_eth, 2)} ETH ·{" "}
                          {fmt(pos?.option_qty_contracts, 0)} 张
                        </span>
                        <span
                          className="pos-meta-item mono"
                          title="开仓指数÷开仓均价"
                        >
                          杠杆 {fmt(pos?.option_leverage, 0)}x
                        </span>
                      </div>
                      <div className="pos-grid">
                        <div className="pos-cell">
                          <span className="pos-label">开仓均价</span>
                          <span className="pos-value mono">
                            {fmtExPx("option", pos?.option_entry_px)}
                          </span>
                        </div>
                        <div className="pos-cell">
                          <span className="pos-label">买一</span>
                          <span className="pos-value mono">
                            {fmtBidLiqEx(
                              "option",
                              pos?.option_mark_px,
                              pos?.option_bid_sz,
                            )}
                          </span>
                        </div>
                        <div className="pos-cell">
                          <span className="pos-label">
                            {plan?.mode === "LIVE" ? "净盈亏" : "浮盈亏"}
                          </span>
                          <span
                            className={`pos-value mono ${pnlClass(pos?.option_upl)}`}
                          >
                            {fmt(pos?.option_upl)}
                          </span>
                        </div>
                        <div className="pos-cell">
                          <span className="pos-label">初始权利金</span>
                          <span className="pos-value mono">
                            {fmt(pos?.initial_premium)}
                          </span>
                        </div>
                        <div className="pos-time-row">
                          <div className="pos-cell">
                            <span className="pos-label">开仓时间</span>
                            <span className="pos-value mono">{openTimeLabel}</span>
                          </div>
                          <div className="pos-cell">
                            <span className="pos-label">持仓时长</span>
                            <span className="pos-value mono">
                              {holdDurationLabel}
                            </span>
                          </div>
                        </div>
                      </div>
                    </div>

                    <div className="pos-card">
                      <div className="pos-card-head">
                        <div className="pos-card-symbol">
                          <strong>{pos?.option2_inst_id || "Put"}</strong>
                          <span className="pos-side-badge pos-side-long">
                            看跌 Put
                          </span>
                        </div>
                        <div
                          className={`pos-countdown mono ${countdownUrgent ? "pos-countdown-urgent" : ""}`}
                          title="到期倒计时"
                        >
                          {countdown}
                        </div>
                      </div>
                      <div className="pos-meta">
                        <span className="pos-meta-item">期期 · Put</span>
                        <span className="pos-meta-item">
                          到期 {pos?.expiry_ymd || "—"}
                        </span>
                        <span className="pos-meta-item">
                          行权{" "}
                          {pos?.strike2 != null
                            ? Math.round(Number(pos.strike2))
                            : "—"}
                        </span>
                        <span className="pos-meta-item mono">
                          {fmt(
                            pos?.option2_qty_eth ??
                              plan?.oo_put_qty_eth ??
                              plan?.risk_sizing_preview?.put_qty_eth,
                            2,
                          )}{" "}
                          ETH · {fmt(pos?.option2_qty_contracts, 0)} 张
                        </span>
                        <span
                          className="pos-meta-item mono"
                          title="开仓指数÷开仓均价"
                        >
                          杠杆{" "}
                          {pos?.option2_leverage != null
                            ? `${fmt(pos.option2_leverage, 0)}x`
                            : optionLevLabel(
                                pos?.entry_index_px ?? snap?.index_px,
                                pos?.option2_entry_px,
                              )}
                        </span>
                      </div>
                      <div className="pos-grid">
                        <div className="pos-cell">
                          <span className="pos-label">开仓均价</span>
                          <span className="pos-value mono">
                            {fmtExPx("option", pos?.option2_entry_px)}
                          </span>
                        </div>
                        <div className="pos-cell">
                          <span className="pos-label">买一</span>
                          <span className="pos-value mono">
                            {fmtBidLiqEx(
                              "option",
                              pos?.option2_mark_px ?? snap?.put?.bid,
                              pos?.option2_bid_sz ?? snap?.put?.bid_sz,
                            )}
                          </span>
                        </div>
                        <div className="pos-cell">
                          <span className="pos-label">
                            {plan?.mode === "LIVE" ? "净盈亏" : "浮盈亏"}
                          </span>
                          <span
                            className={`pos-value mono ${pnlClass(pos?.option2_upl)}`}
                          >
                            {fmt(pos?.option2_upl)}
                          </span>
                        </div>
                        <div className="pos-cell">
                          <span className="pos-label">初始权利金</span>
                          <span className="pos-value mono">
                            {fmt(pos?.initial_premium2)}
                          </span>
                        </div>
                        <div className="pos-time-row">
                          <div className="pos-cell">
                            <span className="pos-label">开仓时间</span>
                            <span className="pos-value mono">{openTimeLabel}</span>
                          </div>
                          <div className="pos-cell">
                            <span className="pos-label">持仓时长</span>
                            <span className="pos-value mono">
                              {holdDurationLabel}
                            </span>
                          </div>
                        </div>
                      </div>
                    </div>
                  </>
                ) : (
                  <>
                    <div className="pos-card">
                      <div className="pos-card-head">
                        <div className="pos-card-symbol">
                          <strong>{pos?.perp_inst_id || "ETH-USDT-SWAP"}</strong>
                          <span
                            className={
                              pos?.perp_side === "long"
                                ? "pos-side-badge pos-side-long"
                                : "pos-side-badge pos-side-short"
                            }
                          >
                            {pos?.perp_side === "long" ? "做多" : "做空"}
                          </span>
                        </div>
                      </div>
                      <div className="pos-meta">
                        <span className="pos-meta-item">永续持仓</span>
                        <span className="pos-meta-item">组 {pos?.group_id}</span>
                        <span className="pos-meta-item mono">
                          数量 {fmt(pos?.perp_qty_eth, 2)} ETH
                        </span>
                        <span className="pos-meta-item mono">
                          {fmt(pos?.leverage ?? plan?.leverage, 0)}x
                        </span>
                      </div>
                      <div className="pos-grid">
                        <div className="pos-cell">
                          <span className="pos-label">开仓价</span>
                          <span className="pos-value mono">
                            {fmtExPx("perp", pos?.perp_entry_px)}
                          </span>
                        </div>
                        <div className="pos-cell">
                          <span className="pos-label">可平价</span>
                          <span className="pos-value mono">
                            {fmtExPx("perp", pos?.perp_mark_px)}
                          </span>
                        </div>
                        <div className="pos-cell">
                          <span className="pos-label">浮盈亏</span>
                          <span
                            className={`pos-value mono ${pnlClass(pos?.perp_upl)}`}
                          >
                            {fmt(pos?.perp_upl)}
                          </span>
                        </div>
                        <div className="pos-cell">
                          <span className="pos-label">保证金</span>
                          <span className="pos-value mono">
                            {fmt(pos?.perp_margin)}
                          </span>
                        </div>
                        <div className="pos-cell">
                          <span className="pos-label">名义价值</span>
                          <span className="pos-value mono">
                            {fmt(pos?.perp_notional)}
                          </span>
                        </div>
                        <div className="pos-cell">
                          <span className="pos-label">波动比例</span>
                          <span className="pos-value mono">
                            {fmt(movePct, 2)}%
                          </span>
                        </div>
                        <div className="pos-time-row">
                          <div className="pos-cell">
                            <span className="pos-label">开仓时间</span>
                            <span className="pos-value mono">{openTimeLabel}</span>
                          </div>
                          <div className="pos-cell">
                            <span className="pos-label">持仓时长</span>
                            <span className="pos-value mono">
                              {holdDurationLabel}
                            </span>
                          </div>
                        </div>
                      </div>
                    </div>

                    <div className="pos-card">
                      <div className="pos-card-head">
                        <div className="pos-card-symbol">
                          <strong>{pos?.option_inst_id || "期权"}</strong>
                          <span
                            className={
                              pos?.option_side === "call"
                                ? "pos-side-badge pos-side-long"
                                : "pos-side-badge pos-side-short"
                            }
                          >
                            {pos?.option_side === "call"
                              ? "看涨 Call"
                              : "看跌 Put"}
                          </span>
                        </div>
                        <div
                          className={`pos-countdown mono ${countdownUrgent ? "pos-countdown-urgent" : ""}`}
                          title="到期倒计时"
                        >
                          {countdown}
                        </div>
                      </div>
                      <div className="pos-meta">
                        <span className="pos-meta-item">期权持仓</span>
                        <span className="pos-meta-item">
                          到期 {pos?.expiry_ymd || "—"}
                        </span>
                        <span className="pos-meta-item">
                          行权{" "}
                          {pos?.strike != null
                            ? Math.round(Number(pos.strike))
                            : "—"}
                        </span>
                        <span className="pos-meta-item mono">
                          {fmt(pos?.option_qty_eth, 2)} ETH ·{" "}
                          {fmt(pos?.option_qty_contracts, 0)} 张
                        </span>
                        <span
                          className="pos-meta-item mono"
                          title="开仓指数÷开仓均价"
                        >
                          杠杆 {fmt(pos?.option_leverage, 0)}x
                        </span>
                      </div>
                      <div className="pos-grid">
                        <div className="pos-cell">
                          <span className="pos-label">开仓均价</span>
                          <span className="pos-value mono">
                            {fmtExPx("option", pos?.option_entry_px)}
                          </span>
                        </div>
                        <div className="pos-cell">
                          <span className="pos-label">买一</span>
                          <span className="pos-value mono">
                            {fmtBidLiqEx(
                              "option",
                              pos?.option_mark_px,
                              pos?.option_bid_sz,
                            )}
                          </span>
                        </div>
                        <div className="pos-cell">
                          <span className="pos-label">
                            {plan?.mode === "LIVE" ? "净盈亏" : "浮盈亏"}
                          </span>
                          <span
                            className={`pos-value mono ${pnlClass(pos?.option_upl)}`}
                          >
                            {fmt(pos?.option_upl)}
                          </span>
                        </div>
                        <div className="pos-cell">
                          <span className="pos-label">初始权利金</span>
                          <span className="pos-value mono">
                            {fmt(pos?.initial_premium)}
                          </span>
                        </div>
                        <div className="pos-time-row">
                          <div className="pos-cell">
                            <span className="pos-label">开仓时间</span>
                            <span className="pos-value mono">{openTimeLabel}</span>
                          </div>
                          <div className="pos-cell">
                            <span className="pos-label">持仓时长</span>
                            <span className="pos-value mono">
                              {holdDurationLabel}
                            </span>
                          </div>
                        </div>
                      </div>
                    </div>
                  </>
                )}
              </>
            ) : isOo ? (
              <>
                <div className="pos-empty">Call 持仓 · 暂无</div>
                <div className="pos-empty">Put 持仓 · 暂无</div>
              </>
            ) : (
              <>
                <div className="pos-empty">永续持仓 · 暂无</div>
                <div className="pos-empty">期权持仓 · 暂无</div>
              </>
            )}
          </div>
        </div>

        <div className="plan-market">
          {isOo ? (
            <div className="card">
              <h3 className="plan-panel-title">指数 / 振幅</h3>
              <div className="kv">
                <span>指数</span>
                <span className="mono">{fmtExPx("index", snap?.index_px)}</span>
              </div>
              <div className="kv">
                <span>
                  高点
                  {snap?.oo_amplitude?.hours != null
                    ? `（${fmt(snap.oo_amplitude.hours, 0)}h）`
                    : ""}
                </span>
                <span className="mono">
                  {fmtExPx("index", snap?.oo_amplitude?.high)}
                </span>
              </div>
              <div className="kv">
                <span>低点</span>
                <span className="mono">
                  {fmtExPx("index", snap?.oo_amplitude?.low)}
                </span>
              </div>
              <div className="kv">
                <span>振幅</span>
                <span className="mono">
                  {snap?.oo_amplitude?.range_pct != null
                    ? `${fmt(snap.oo_amplitude.range_pct, 2)}%`
                    : "—"}
                  {(snap?.oo_amplitude?.max_pct ?? snap?.oo_amplitude?.min_pct) !=
                  null
                    ? ` · 上限≤${fmt(
                        Number(
                          snap.oo_amplitude?.max_pct ??
                            snap.oo_amplitude?.min_pct,
                        ),
                        1,
                      )}%`
                    : ""}
                  {snap?.oo_amplitude?.ok === false
                    ? " · 超限"
                    : snap?.oo_amplitude?.ok === true
                      ? " · 可开"
                      : ""}
                </span>
              </div>
            </div>
          ) : (
            <div className="card">
              <h3 className="plan-panel-title">永续行情</h3>
              <div className="kv">
                <span>买一</span>
                <span className="mono">{fmtExPx("perp", snap?.perp?.bid)}</span>
              </div>
              <div className="kv">
                <span>卖一</span>
                <span className="mono">{fmtExPx("perp", snap?.perp?.ask)}</span>
              </div>
              <div className="kv">
                <span>市价</span>
                <span className="mono">
                  {fmtExPx(
                    "perp",
                    snap?.perp?.mark_px ??
                      (snap?.perp?.bid != null && snap?.perp?.ask != null
                        ? (snap.perp.bid + snap.perp.ask) / 2
                        : null),
                  )}
                </span>
              </div>
              <div className="kv">
                <span>指数</span>
                <span className="mono">{fmtExPx("index", snap?.index_px)}</span>
              </div>
            </div>
          )}
          <div className="card">
            <h3 className="plan-panel-title">
              {isOo
                ? open
                  ? "持仓虚值"
                  : "期期虚值"
                : open
                  ? "持仓期权"
                  : "期权 ATM"}
              {isOo && snap?.pair
                ? ` · C@${Math.round(
                    Number(
                      snap.pair.call_strike ?? snap.pair.strike ?? 0,
                    ),
                  )} / P@${Math.round(
                    Number(
                      snap.pair.put_strike ?? snap.pair.strike ?? 0,
                    ),
                  )}`
                : snap?.pair
                  ? ` @ ${
                      snap.pair.strike != null
                        ? Math.round(Number(snap.pair.strike))
                        : "—"
                    }`
                  : ""}
            </h3>
            {(() => {
              const under =
                snap?.index_px ??
                (snap?.perp?.bid != null && snap?.perp?.ask != null
                  ? (snap.perp.bid + snap.perp.ask) / 2
                  : snap?.perp?.mark_px ?? null);
              const callPx = open ? snap?.call?.bid : snap?.call?.ask;
              const callSz = open ? snap?.call?.bid_sz : snap?.call?.ask_sz;
              const putPx = open ? snap?.put?.bid : snap?.put?.ask;
              const putSz = open ? snap?.put?.bid_sz : snap?.put?.ask_sz;
              const sideLabel = open ? "买一/流动性" : "卖一/流动性";
              const callLev = optionLevLabel(under, callPx);
              const putLev = optionLevLabel(under, putPx);
              const heldSide = String(pos?.option_side || "").toLowerCase();
              const heldLev =
                open && pos?.option_leverage != null
                  ? `${fmt(pos.option_leverage, 0)}x`
                  : open && heldSide === "call"
                    ? callLev
                    : open && heldSide === "put"
                      ? putLev
                      : null;
              const callK = snap?.pair?.call_strike ?? snap?.pair?.strike;
              const putK = snap?.pair?.put_strike ?? snap?.pair?.strike;
              return (
                <>
                  <div className="kv">
                    <span>
                      Call {sideLabel}
                      {isOo && callK != null
                        ? ` @${Math.round(Number(callK))}`
                        : ""}
                    </span>
                    <span className="mono">
                      {fmtTopEx("option", callPx, callSz)}
                      {!open ? ` · 杠杆 ${callLev}` : ""}
                    </span>
                  </div>
                  <div className="kv">
                    <span>
                      Put {sideLabel}
                      {isOo && putK != null
                        ? ` @${Math.round(Number(putK))}`
                        : ""}
                    </span>
                    <span className="mono">
                      {fmtTopEx("option", putPx, putSz)}
                      {!open ? ` · 杠杆 ${putLev}` : ""}
                    </span>
                  </div>
                  <div className="kv">
                    <span>实际杠杆</span>
                    <span className="mono">
                      {open && !isOo
                        ? heldLev ||
                          (heldSide
                            ? "—"
                            : `Call ${callLev} · Put ${putLev}`)
                        : `Call ${callLev} · Put ${putLev}`}
                    </span>
                  </div>
                </>
              );
            })()}
            {isOo ? (
              <div className="kv">
                <span>相对现价</span>
                <span className="mono">
                  {(() => {
                    const px = snap?.index_px;
                    const ck = snap?.pair?.call_strike ?? snap?.pair?.strike;
                    const pk = snap?.pair?.put_strike;
                    if (px == null || ck == null) return "—";
                    const cOff = Number(ck) - Number(px);
                    const pOff =
                      pk != null ? Number(pk) - Number(px) : null;
                    const fmtOff = (n: number) =>
                      `${n > 0 ? "+" : ""}${n.toFixed(0)}`;
                    return pOff != null
                      ? `C ${fmtOff(cOff)} · P ${fmtOff(pOff)}`
                      : `C ${fmtOff(cOff)}`;
                  })()}
                </span>
              </div>
            ) : (
              <div className="kv">
                <span>距现价</span>
                <span className="mono">
                  {(() => {
                    const strike = snap?.pair?.strike;
                    const px =
                      snap?.index_px ??
                      (snap?.perp?.bid != null && snap?.perp?.ask != null
                        ? (snap.perp.bid + snap.perp.ask) / 2
                        : null);
                    if (strike == null || px == null) return "—";
                    const abs = Math.abs(strike - px);
                    const sign = strike - px > 0 ? "+" : "";
                    const delta = `${sign}${(strike - px).toFixed(0)}`;
                    if (!plan?.atm_open_offset_enabled) {
                      return `${delta} · 偏差限制关`;
                    }
                    const lim = plan?.max_atm_open_offset ?? 3;
                    const ok = abs <= lim + 1e-9;
                    return `${delta} · 开仓${ok ? "可" : "不可"}(|Δ|≤${lim})`;
                  })()}
                </span>
              </div>
            )}
            <div className="kv">
              <span>到期</span>
              <span className="mono">{snap?.pair?.expiry_ymd || "—"}</span>
            </div>
          </div>
        </div>

        {plan?.residuals && plan.residuals.length > 0 ? (
          <div className="card plan-residual-block">
            <div className="plan-residual-head">
              <h4>残留期权</h4>
              <span className="meta">
                自动平仓仍要求权利金≥设定比例；「平仓」仅验流动性
              </span>
            </div>
            <div className="plan-residual-wrap">
              <table className="plan-residual-table">
                <thead>
                  <tr>
                    <th>组名</th>
                    <th>期权名</th>
                    <th>数量</th>
                    <th>开仓权利金</th>
                    <th title="最新买一价格 / 买一数量(ETH)">买一流动性</th>
                    <th title="买一价 × 持仓数量">买一权利金</th>
                    <th title="买一权利金 ÷ 开仓权利金">占比</th>
                    <th>操作</th>
                  </tr>
                </thead>
                <tbody>
                  {plan.residuals.map((r) => {
                    const gid = String(r.group_id || "");
                    const inst = String(r.option_inst_id || "—");
                    const liqOk = r.liquidity_ok === true;
                    return (
                      <tr key={`${gid}:${inst}`}>
                        <td className="mono">{gid || "—"}</td>
                        <td className="mono">{inst}</td>
                        <td className="mono">{fmt(r.option_qty_eth, 2)}</td>
                        <td className="mono">{fmt(r.initial_premium, 2)}</td>
                        <td
                          className="mono"
                          title={
                            liqOk
                              ? "买一深度可覆盖持仓"
                              : "买一不足或盘口不可用"
                          }
                        >
                          {fmtBidLiquidity(r.bid_px, r.bid_sz_eth)}
                        </td>
                        <td className="mono">{fmt(r.current_premium, 2)}</td>
                        <td className="mono">
                          {r.recovery_pct == null
                            ? "—"
                            : `${fmt(r.recovery_pct, 1)}%`}
                        </td>
                        <td>
                          <button
                            type="button"
                            className="btn ghost"
                            style={{ padding: "4px 10px", fontSize: 12 }}
                            disabled={!!residualBusy || !!busy || !liqOk}
                            title={
                              liqOk
                                ? "按最新买一 IOC 平仓（不验权利金比例）"
                                : "买一流动性不足或盘口不可用"
                            }
                            onClick={() => void closeResidual(gid, inst)}
                          >
                            {residualBusy === gid ? "平仓中…" : "平仓"}
                          </button>
                        </td>
                      </tr>
                    );
                  })}
                </tbody>
              </table>
            </div>
          </div>
        ) : null}
      </div>
    </div>
  );
}
