/**
 * OKX 期权复盘:待复盘交易(5行) → 点复盘出表单 → 复盘记录详情 → 统计.
 */
(function (global) {
  "use strict";

  var PAGE_SIZE = 5;
  var TAB_LABELS = {
    option_spot: "期权交易记录",
    options_options: "期期对冲记录",
    perp_options: "永期对冲记录",
  };
  var FORM_PRESETS = {
    option_spot: {
      strategy: ["顺势", "反转"],
      direction: ["多", "空"],
      entry: ["假突破", "结构突破"],
    },
    hedge: {
      strategy: ["横盘", "趋势"],
      direction: ["多", "空"],
      entry: ["横盘博弈方向", "趋势对冲止损"],
    },
  };
  var RESULT_OPTIONS = ["盈利", "亏损", "持平"];
  var activeSource = "option_spot";
  var currentTradeId = null;
  var draftId = "";
  var tradesCache = {};
  var reviewedCache = {};
  var tradesPage = 0;
  var tradesPages = 1;
  var reviewedPage = 0;
  var reviewedPages = 1;

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

  function escapeHtml(s) {
    return String(s == null ? "" : s)
      .replace(/&/g, "&amp;")
      .replace(/</g, "&lt;")
      .replace(/>/g, "&gt;")
      .replace(/"/g, "&quot;");
  }

  function fmtPnl(v) {
    if (v == null || v === "") return "—";
    var n = Number(v);
    if (Number.isNaN(n)) return "—";
    return (n >= 0 ? "+" : "") + n.toFixed(2);
  }

  function fmtHold(sec) {
    if (sec == null) return "—";
    var s = Math.max(0, Number(sec) || 0);
    if (s < 3600) return Math.round(s / 60) + "m";
    if (s < 86400) return (s / 3600).toFixed(1) + "h";
    return (s / 86400).toFixed(1) + "d";
  }

  function toLocalInput(ts) {
    if (!ts) return "";
    var s = String(ts).trim().replace(" ", "T");
    if (s.length >= 16) return s.slice(0, 16);
    return s;
  }

  function tradeTitle(t) {
    if (!t) return "—";
    if (t.source_type === "option_spot") return t.inst_id || "—";
    return (
      (t.underlying || "") +
      (t.direction ? " " + t.direction : "") +
      (t.plan_close_reason ? " · " + t.plan_close_reason : "")
    );
  }

  function pnlStyle(v) {
    var n = Number(v);
    if (n > 0) return "color:#3dd68c";
    if (n < 0) return "color:#f07178";
    return "";
  }

  function newDraftId() {
    if (global.crypto && typeof global.crypto.randomUUID === "function") {
      return global.crypto.randomUUID().replace(/-/g, "");
    }
    var s = "";
    for (var i = 0; i < 32; i++) s += Math.floor(Math.random() * 16).toString(16);
    return s;
  }

  function baseQs() {
    var p = new URLSearchParams();
    p.set("source_type", activeSource);
    var uly = ($("or-filter-uly") || {}).value || "";
    var opt = ($("or-filter-opt") || {}).value || "";
    var strategy = (($("or-filter-strategy") || {}).value || "").trim();
    var from = ($("or-filter-from") || {}).value || "";
    var to = ($("or-filter-to") || {}).value || "";
    if (uly) p.set("underlying", uly);
    if (opt) p.set("opt_type", opt);
    if (strategy) p.set("strategy_tag", strategy);
    if (from) p.set("closed_from", from.replace("T", " ") + ":00");
    if (to) p.set("closed_to", to.replace("T", " ") + ":00");
    if (($("or-include-hedge-legs") || {}).checked) p.set("include_hedge_legs", "1");
    return p;
  }

  function setSyncStatus(text) {
    var el = $("or-sync-status");
    if (el) el.textContent = text || "";
  }

  function reloadAll() {
    setSyncStatus("读取本地记录…");
    loadTrades({ sync: true });
    loadReviewed({ sync: false });
    loadStats();
  }

  function isHedgeSource(sourceType) {
    return sourceType === "options_options" || sourceType === "perp_options";
  }

  function fillSelect(el, options, placeholder) {
    if (!el) return;
    var keep = el.value;
    el.innerHTML = "";
    var first = document.createElement("option");
    first.value = "";
    first.textContent = placeholder || "";
    el.appendChild(first);
    (options || []).forEach(function (v) {
      var opt = document.createElement("option");
      opt.value = v;
      opt.textContent = v;
      el.appendChild(opt);
    });
    if (keep) setSelectValue(el, keep);
  }

  function setSelectValue(el, value) {
    if (!el) return;
    var v = value == null ? "" : String(value);
    if (!v) {
      el.value = "";
      return;
    }
    var found = false;
    for (var i = 0; i < el.options.length; i++) {
      if (el.options[i].value === v) {
        found = true;
        break;
      }
    }
    if (!found) {
      var opt = document.createElement("option");
      opt.value = v;
      opt.textContent = v;
      el.appendChild(opt);
    }
    el.value = v;
  }

  function applyFormPresets(sourceType) {
    var preset = isHedgeSource(sourceType) ? FORM_PRESETS.hedge : FORM_PRESETS.option_spot;
    fillSelect($("or-f-strategy"), preset.strategy, "策略标签");
    fillSelect($("or-f-direction"), preset.direction, "方向判断");
    fillSelect($("or-f-entry"), preset.entry, "入场逻辑");
    fillSelect($("or-f-result"), RESULT_OPTIONS, "结果标签");
  }

  function autoDirection(t) {
    if (!t) return "";
    if (isHedgeSource(t.source_type)) {
      var d = String(t.direction || "").trim().toLowerCase();
      if (d === "long" || d === "buy" || d === "多") return "多";
      if (d === "short" || d === "sell" || d === "空") return "空";
      return "";
    }
    var ot = String(t.opt_type || "").trim().toUpperCase();
    if (ot === "C" || ot === "CALL") return "多";
    if (ot === "P" || ot === "PUT") return "空";
    return "";
  }

  function autoResultTag(pnl) {
    if (pnl == null || pnl === "") return "";
    var n = Number(pnl);
    if (Number.isNaN(n)) return "";
    if (n > 0) return "盈利";
    if (n < 0) return "亏损";
    return "持平";
  }

  function setActiveTab(source) {
    activeSource = source || "option_spot";
    tradesPage = 0;
    reviewedPage = 0;
    document.querySelectorAll(".or-tab").forEach(function (btn) {
      btn.classList.toggle("active", btn.getAttribute("data-source") === activeSource);
    });
    var title = $("or-list-title");
    if (title) title.textContent = TAB_LABELS[activeSource] || "记录";
    applyFormPresets(activeSource);
    hideJournalForm();
    hideDetail();
    reloadAll();
  }

  function updateTradesPager() {
    var label = $("or-trades-page-label");
    var prev = $("or-trades-prev");
    var next = $("or-trades-next");
    if (label) {
      label.textContent = "第 " + (tradesPage + 1) + " / " + tradesPages + " 页";
    }
    if (prev) prev.disabled = tradesPage <= 0;
    if (next) next.disabled = tradesPage + 1 >= tradesPages;
  }

  function updateReviewedPager() {
    var label = $("or-reviewed-page-label");
    var prev = $("or-reviewed-prev");
    var next = $("or-reviewed-next");
    if (label) {
      label.textContent = "第 " + (reviewedPage + 1) + " / " + reviewedPages + " 页";
    }
    if (prev) prev.disabled = reviewedPage <= 0;
    if (next) next.disabled = reviewedPage + 1 >= reviewedPages;
  }

  function applyPagerMeta(data, kind) {
    var pages = Number(data.pages || 1);
    if (!pages || pages < 1) pages = 1;
    var clamped = false;
    if (kind === "trades") {
      tradesPages = pages;
      if (tradesPage >= tradesPages) {
        tradesPage = Math.max(0, tradesPages - 1);
        clamped = true;
      }
      updateTradesPager();
    } else {
      reviewedPages = pages;
      if (reviewedPage >= reviewedPages) {
        reviewedPage = Math.max(0, reviewedPages - 1);
        clamped = true;
      }
      updateReviewedPager();
    }
    return clamped;
  }

  function beginListLoad(wrapId, soft) {
    var wrap = $(wrapId);
    if (!wrap) return null;
    if (soft) {
      if (!wrap.style.minHeight) {
        wrap.style.minHeight = Math.max(wrap.offsetHeight, 1) + "px";
      }
      wrap.classList.add("or-list-loading");
    } else {
      wrap.classList.remove("or-list-loading");
      wrap.style.minHeight = "";
    }
    return wrap;
  }

  function endListLoad(wrap) {
    if (!wrap) return;
    wrap.classList.remove("or-list-loading");
    wrap.style.minHeight = "";
  }

  function loadTrades(opts) {
    opts = opts || {};
    var doSync = opts.sync !== false;
    var soft = !!opts.soft;
    var tbody = $("or-trades-tbody");
    if (!tbody) return;
    var wrap = beginListLoad("or-trades-wrap", soft);
    if (!soft) {
      tbody.innerHTML = '<tr><td colspan="6" class="muted">加载中…</td></tr>';
    }
    var p = baseQs();
    p.set("reviewed", "0");
    p.set("limit", String(PAGE_SIZE));
    p.set("offset", String(tradesPage * PAGE_SIZE));
    if (!doSync) p.set("sync", "0");
    fetch("/api/options/review/trades?" + p.toString(), { credentials: "same-origin" })
      .then(function (r) {
        return r.json();
      })
      .then(function (data) {
        if (doSync) setSyncStatus("本地记录已加载");
        if (!data.ok) {
          tbody.innerHTML = '<tr><td colspan="6" class="muted">加载失败</td></tr>';
          endListLoad(wrap);
          return;
        }
        if (applyPagerMeta(data, "trades") && Number(data.total || 0) > 0) {
          loadTrades(opts);
          return;
        }
        var rows = data.trades || [];
        tradesCache = {};
        if (!rows.length) {
          tbody.innerHTML =
            '<tr><td colspan="6" class="muted">暂无待复盘记录</td></tr>';
          endListLoad(wrap);
          return;
        }
        tbody.innerHTML = rows
          .map(function (t) {
            tradesCache[t.id] = t;
            var active = currentTradeId === t.id ? " or-row-active" : "";
            return (
              '<tr class="or-trade-row' +
              active +
              '" data-id="' +
              t.id +
              '">' +
              "<td><span class=\"or-badge\">" +
              escapeHtml(t.source_label || t.source_type) +
              "</span></td>" +
              "<td>" +
              escapeHtml(tradeTitle(t)) +
              "</td>" +
              '<td style="' +
              pnlStyle(t.realized_pnl_total) +
              '">' +
              fmtPnl(t.realized_pnl_total) +
              "</td>" +
              '<td class="muted" style="font-size:12px">' +
              escapeHtml(t.opened_at || "—") +
              "<br>" +
              escapeHtml(t.closed_at || "—") +
              "</td>" +
              "<td>" +
              fmtHold(t.hold_seconds) +
              "</td>" +
              '<td><button type="button" class="btn or-review-btn" data-id="' +
              t.id +
              '" style="font-size:.72rem;padding:2px 8px">复盘</button> ' +
              '<button type="button" class="btn-secondary or-hide-btn" data-id="' +
              t.id +
              '" style="font-size:.72rem;padding:2px 8px">删除</button></td>' +
              "</tr>"
            );
          })
          .join("");
        tbody.querySelectorAll(".or-review-btn").forEach(function (btn) {
          btn.addEventListener("click", function (ev) {
            ev.preventDefault();
            ev.stopPropagation();
            openJournalForm(Number(btn.getAttribute("data-id")));
          });
        });
        tbody.querySelectorAll(".or-hide-btn").forEach(function (btn) {
          btn.addEventListener("click", function (ev) {
            ev.preventDefault();
            ev.stopPropagation();
            hideTrade(Number(btn.getAttribute("data-id")));
          });
        });
        endListLoad(wrap);
      })
      .catch(function () {
        tbody.innerHTML = '<tr><td colspan="6" class="muted">加载失败</td></tr>';
        endListLoad(wrap);
      });
  }

  function loadReviewed(opts) {
    opts = opts || {};
    var doSync = opts.sync === true;
    var soft = !!opts.soft;
    var tbody = $("or-reviewed-tbody");
    if (!tbody) return;
    var wrap = beginListLoad("or-reviewed-wrap", soft);
    if (!soft) {
      tbody.innerHTML = '<tr><td colspan="6" class="muted">加载中…</td></tr>';
    }
    var p = baseQs();
    p.set("reviewed", "1");
    p.set("limit", String(PAGE_SIZE));
    p.set("offset", String(reviewedPage * PAGE_SIZE));
    if (!doSync) p.set("sync", "0");
    fetch("/api/options/review/trades?" + p.toString(), { credentials: "same-origin" })
      .then(function (r) {
        return r.json();
      })
      .then(function (data) {
        if (!data.ok) {
          tbody.innerHTML = '<tr><td colspan="6" class="muted">加载失败</td></tr>';
          endListLoad(wrap);
          return;
        }
        if (applyPagerMeta(data, "reviewed") && Number(data.total || 0) > 0) {
          loadReviewed(opts);
          return;
        }
        var rows = data.trades || [];
        reviewedCache = {};
        if (!rows.length) {
          tbody.innerHTML = '<tr><td colspan="6" class="muted">暂无复盘记录</td></tr>';
          endListLoad(wrap);
          return;
        }
        tbody.innerHTML = rows
          .map(function (t) {
            reviewedCache[t.id] = t;
            return (
              '<tr class="or-reviewed-row" data-id="' +
              t.id +
              '">' +
              "<td><span class=\"or-badge\">" +
              escapeHtml(t.source_label || t.source_type) +
              "</span></td>" +
              "<td>" +
              escapeHtml(tradeTitle(t)) +
              "</td>" +
              '<td style="' +
              pnlStyle(t.realized_pnl_total) +
              '">' +
              fmtPnl(t.realized_pnl_total) +
              "</td>" +
              "<td>" +
              escapeHtml(t.strategy_tag || "—") +
              "</td>" +
              "<td>" +
              escapeHtml(t.result_tag || "—") +
              "</td>" +
              '<td class="muted" style="font-size:12px">' +
              escapeHtml(t.reviewed_at || "—") +
              "</td>" +
              "</tr>"
            );
          })
          .join("");
        tbody.querySelectorAll(".or-reviewed-row").forEach(function (tr) {
          tr.addEventListener("click", function () {
            openDetail(Number(tr.getAttribute("data-id")));
          });
        });
        endListLoad(wrap);
      })
      .catch(function () {
        tbody.innerHTML = '<tr><td colspan="6" class="muted">加载失败</td></tr>';
        endListLoad(wrap);
      });
  }

  function hideDetail() {
    var panel = $("or-detail-panel");
    if (panel) panel.classList.add("hidden");
  }

  function openDetail(tradeId) {
    var panel = $("or-detail-panel");
    if (!panel) return;
    panel.classList.remove("hidden");
    ($("or-detail-title") || {}).textContent = "加载中…";
    ($("or-detail-meta") || {}).innerHTML = "";
    ($("or-detail-text") || {}).innerHTML = "";
    ($("or-detail-images") || {}).innerHTML = "";
    panel.scrollIntoView({ behavior: "smooth", block: "nearest" });

    fetch("/api/options/review/trades/" + tradeId, { credentials: "same-origin" })
      .then(function (r) {
        return r.json();
      })
      .then(function (data) {
        if (!data.ok || !data.trade) {
          ($("or-detail-title") || {}).textContent = "加载失败";
          return;
        }
        renderDetail(data.trade);
      })
      .catch(function () {
        ($("or-detail-title") || {}).textContent = "加载失败";
      });
  }

  function renderDetail(t) {
    var e = t.entry || {};
    reviewedCache[t.id] = t;
    ($("or-detail-title") || {}).textContent =
      "复盘详情 · " + (t.source_label || "") + " · " + tradeTitle(t);
    var editBtn = $("or-detail-edit-btn");
    if (editBtn) editBtn.setAttribute("data-id", String(t.id));

    var meta = $("or-detail-meta");
    if (meta) {
      var cells = [
        ["标的", t.underlying || "—"],
        ["合约/计划", tradeTitle(t)],
        ["盈亏", fmtPnl(t.realized_pnl_total)],
        ["持有", fmtHold(t.hold_seconds)],
        ["开仓", t.opened_at || "—"],
        ["平仓", t.closed_at || "—"],
        ["策略", e.strategy_tag || "—"],
        ["方向", e.direction_view || "—"],
        ["结果", e.result_tag || "—"],
        ["离场", e.exit_reason || "—"],
        ["按计划", e.followed_plan || "—"],
        ["入场逻辑", e.entry_logic || "—"],
      ];
      if (t.is_hedge) {
        cells.push(["永续盈亏", fmtPnl(t.realized_pnl_perp)]);
        cells.push(["期权盈亏", fmtPnl(t.realized_pnl_options)]);
      }
      meta.innerHTML = cells
        .map(function (pair) {
          return (
            "<div><div class=\"muted\" style=\"font-size:11px\">" +
            escapeHtml(pair[0]) +
            "</div><div>" +
            escapeHtml(pair[1]) +
            "</div></div>"
          );
        })
        .join("");
    }

    var text = $("or-detail-text");
    if (text) {
      var lines = [];
      if (e.mistake_tags) lines.push("<div><b>心理标签</b>：" + escapeHtml(e.mistake_tags) + "</div>");
      if (e.note) lines.push("<div><b>备注</b>：" + escapeHtml(e.note).replace(/\n/g, "<br>") + "</div>");
      if (t.legs && t.legs.length) {
        lines.push(
          "<div style=\"margin-top:6px\"><b>计划腿</b></div><table class=\"options-strike-table\"><thead><tr><th>腿</th><th>合约</th><th>盈亏</th><th>原因</th></tr></thead><tbody>" +
            t.legs
              .map(function (leg) {
                return (
                  "<tr><td>" +
                  escapeHtml(leg.leg_role || "") +
                  "</td><td>" +
                  escapeHtml(leg.inst_id || leg.symbol || "") +
                  "</td><td>" +
                  fmtPnl(leg.realized_pnl) +
                  "</td><td>" +
                  escapeHtml(leg.close_reason || "") +
                  "</td></tr>"
                );
              })
              .join("") +
            "</tbody></table>"
        );
      }
      text.innerHTML = lines.join("") || '<div class="muted">无额外备注</div>';
    }

    var imagesHost = $("or-detail-images");
    if (imagesHost) {
      var images = e.images || [];
      if (!images.length) {
        imagesHost.innerHTML = '<div class="muted">无截图</div>';
      } else {
        imagesHost.innerHTML = images
          .map(function (img) {
            var file = String(img.file || "").trim();
            if (!file) return "";
            var src = "/static/images/options_journal/" + encodeURIComponent(file).replace(/%2F/g, "/");
            var label = escapeHtml(img.tf || "截图");
            return (
              '<div class="or-detail-img-cell">' +
              '<span class="or-detail-img-label">' +
              label +
              "</span>" +
              '<img class="or-detail-img-thumb" src="' +
              src +
              '" alt="' +
              label +
              '" data-src="' +
              src +
              '">' +
              "</div>"
            );
          })
          .join("");
        imagesHost.querySelectorAll("img").forEach(function (img) {
          img.addEventListener("click", function () {
            if (typeof global.showImage === "function") {
              global.showImage(img.getAttribute("data-src"));
            } else {
              global.open(img.getAttribute("data-src"), "_blank");
            }
          });
        });
      }
    }
  }

  function renderGroup(title, items) {
    if (!items || !items.length) {
      return (
        '<div class="or-stat-card"><div class="muted">' +
        title +
        '</div><div class="muted">无数据</div></div>'
      );
    }
    var lines = items
      .slice(0, 8)
      .map(function (g) {
        return (
          '<div style="display:flex;justify-content:space-between;gap:8px;font-size:13px">' +
          "<span>" +
          escapeHtml(g.key) +
          " · " +
          g.count +
          "笔</span>" +
          "<span>" +
          fmtPnl(g.pnl_sum) +
          " / 胜" +
          (g.win_rate || 0) +
          "%</span>" +
          "</div>"
        );
      })
      .join("");
    return (
      '<div class="or-stat-card"><div style="font-weight:600;margin-bottom:6px">' +
      title +
      "</div>" +
      lines +
      "</div>"
    );
  }

  function loadStats() {
    var kpi = $("or-kpi");
    var groups = $("or-stats-groups");
    if (!kpi || !groups) return;
    fetch("/api/options/review/stats?" + baseQs().toString(), { credentials: "same-origin" })
      .then(function (r) {
        return r.json();
      })
      .then(function (data) {
        if (!data.ok) return;
        var k = data.kpi || {};
        kpi.innerHTML = [
          ["笔数", k.total],
          ["已复盘率", (k.review_rate || 0) + "%"],
          ["胜率", (k.win_rate || 0) + "%"],
          ["累计盈亏", fmtPnl(k.pnl_sum)],
          ["平均盈亏", fmtPnl(k.avg_pnl)],
          ["平均持有", fmtHold(k.avg_hold_sec)],
        ]
          .map(function (pair) {
            return (
              '<div><div class="muted" style="font-size:12px">' +
              pair[0] +
              '</div><div style="font-weight:600">' +
              pair[1] +
              "</div></div>"
            );
          })
          .join("");
        groups.innerHTML = [
          renderGroup("按类型", data.by_source_type),
          renderGroup("按标的", data.by_underlying),
          renderGroup("按策略", data.by_strategy),
          renderGroup("对冲结束原因", data.by_close_reason),
          renderGroup("持有周期", data.by_hold_bucket),
          renderGroup("Call/Put", data.by_opt_type),
        ].join("");
      })
      .catch(function () {});
  }

  function resetUploadSlots() {
    draftId = newDraftId();
    var draftEl = $("or-draft-id");
    if (draftEl) draftEl.value = draftId;
    document.querySelectorAll("#or-upload-slots .or-upload-hidden").forEach(function (el) {
      el.value = "";
    });
    document.querySelectorAll("#or-upload-slots .or-upload-input").forEach(function (el) {
      el.value = "";
    });
    document.querySelectorAll("#or-upload-slots .or-upload-status").forEach(function (el) {
      el.textContent = "";
    });
  }

  function bindUploadSlots() {
    document.querySelectorAll("#or-upload-slots .or-upload-input").forEach(function (input) {
      if (input.dataset.orBound === "1") return;
      input.dataset.orBound = "1";
      input.addEventListener("change", function () {
        var file = input.files && input.files[0];
        var row = input.closest(".journal-upload-row");
        var status = row && row.querySelector(".or-upload-status");
        var hidden = row && row.querySelector(".or-upload-hidden");
        if (!file) {
          if (hidden) hidden.value = "";
          if (status) {
            status.textContent = "";
            status.className = "journal-upload-status or-upload-status";
          }
          return;
        }
        if (!draftId) draftId = newDraftId();
        if (status) {
          status.textContent = "上传中…";
          status.className = "journal-upload-status or-upload-status journal-upload-status--pending";
        }
        var fd = new FormData();
        fd.append("draft_id", draftId);
        fd.append("tf", input.getAttribute("data-tf") || "");
        fd.append("file", file);
        fetch("/api/options/review/upload_slot", {
          method: "POST",
          body: fd,
          credentials: "same-origin",
        })
          .then(function (r) {
            return r.json();
          })
          .then(function (data) {
            if (!data.ok) throw new Error(data.error || "fail");
            if (hidden) hidden.value = data.file;
            if (status) {
              status.textContent = "上传成功 " + data.file;
              status.className = "journal-upload-status or-upload-status journal-upload-status--ok";
            }
            input.value = "";
          })
          .catch(function () {
            if (hidden) hidden.value = "";
            if (status) {
              status.textContent = "上传失败";
              status.className = "journal-upload-status or-upload-status journal-upload-status--err";
            }
          });
      });
    });
  }

  function setMoodTags(raw) {
    var set = {};
    String(raw || "")
      .split(/[,，]/)
      .map(function (x) {
        return x.trim();
      })
      .filter(Boolean)
      .forEach(function (x) {
        set[x] = true;
      });
    document.querySelectorAll(".or-mood").forEach(function (cb) {
      cb.checked = !!set[cb.value];
    });
  }

  function collectMoodTags() {
    var out = [];
    document.querySelectorAll(".or-mood:checked").forEach(function (cb) {
      out.push(cb.value);
    });
    return out.join(",");
  }

  function collectImages() {
    var out = [];
    document.querySelectorAll("#or-upload-slots .or-upload-hidden").forEach(function (el) {
      var file = (el.value || "").trim();
      if (file) out.push({ tf: el.getAttribute("data-tf") || "", file: file });
    });
    return out;
  }

  function hideJournalForm() {
    currentTradeId = null;
    var card = $("or-journal-card");
    if (card) card.classList.add("hidden");
    document.querySelectorAll(".or-trade-row").forEach(function (tr) {
      tr.classList.remove("or-row-active");
    });
    ($("or-trade-id") || {}).value = "";
    ($("or-f-open") || {}).value = "";
    ($("or-f-close") || {}).value = "";
    ($("or-f-coin") || {}).value = "";
    ($("or-f-inst") || {}).value = "";
    ($("or-f-pnl") || {}).value = "";
    ($("or-f-hold") || {}).value = "";
    ($("or-f-strategy") || {}).value = "";
    ($("or-f-direction") || {}).value = "";
    ($("or-f-exit") || {}).value = "";
    ($("or-f-followed") || {}).value = "";
    ($("or-f-result") || {}).value = "";
    ($("or-f-entry") || {}).value = "";
    ($("or-f-note") || {}).value = "";
    setMoodTags("");
    resetUploadSlots();
    var summary = $("or-journal-summary");
    if (summary) {
      summary.textContent = "截图槽位与合约复盘相同(5m / 15m / 1h / 4h).";
    }
    var legsHost = $("or-legs-host");
    if (legsHost) legsHost.innerHTML = "";
    ($("or-save-status") || {}).textContent = "";
  }

  function openJournalForm(tradeId) {
    currentTradeId = tradeId;
    var card = $("or-journal-card");
    if (!card) return;
    card.classList.remove("hidden");
    card.scrollIntoView({ behavior: "smooth", block: "start" });
    document.querySelectorAll(".or-trade-row").forEach(function (tr) {
      tr.classList.toggle("or-row-active", Number(tr.getAttribute("data-id")) === tradeId);
    });
    resetUploadSlots();
    bindUploadSlots();
    ($("or-save-status") || {}).textContent = "加载中…";

    fetch("/api/options/review/trades/" + tradeId, { credentials: "same-origin" })
      .then(function (r) {
        return r.json();
      })
      .then(function (data) {
        if (!data.ok || !data.trade) {
          ($("or-save-status") || {}).textContent = "加载失败";
          return;
        }
        fillForm(data.trade);
        ($("or-save-status") || {}).textContent = "已选中 #" + tradeId;
      })
      .catch(function () {
        ($("or-save-status") || {}).textContent = "加载失败";
      });
  }

  function fillForm(t) {
    var e = t.entry || {};
    applyFormPresets(t.source_type || activeSource);
    ($("or-trade-id") || {}).value = String(t.id || "");
    ($("or-f-open") || {}).value = toLocalInput(t.opened_at);
    ($("or-f-close") || {}).value = toLocalInput(t.closed_at);
    ($("or-f-coin") || {}).value = t.underlying || "";
    ($("or-f-inst") || {}).value =
      t.source_type === "option_spot"
        ? t.inst_id || ""
        : (t.source_label || "") + (t.plan_close_reason ? " · " + t.plan_close_reason : "");
    ($("or-f-pnl") || {}).value = fmtPnl(t.realized_pnl_total);
    ($("or-f-hold") || {}).value = fmtHold(t.hold_seconds);
    setSelectValue($("or-f-strategy"), e.strategy_tag || "");
    setSelectValue($("or-f-direction"), e.direction_view || autoDirection(t));
    ($("or-f-exit") || {}).value = e.exit_reason || t.plan_close_reason || "";
    ($("or-f-followed") || {}).value = e.followed_plan || "";
    setSelectValue($("or-f-result"), e.result_tag || autoResultTag(t.realized_pnl_total));
    setSelectValue($("or-f-entry"), e.entry_logic || "");
    ($("or-f-note") || {}).value = e.note || "";
    setMoodTags(e.mistake_tags);

    var summary = $("or-journal-summary");
    if (summary) {
      summary.textContent =
        (t.source_label || "") +
        " · " +
        (t.inst_id || t.underlying || "#" + t.id) +
        " · 盈亏 " +
        fmtPnl(t.realized_pnl_total) +
        (t.is_hedge
          ? " (永续 " + fmtPnl(t.realized_pnl_perp) + " / 期权 " + fmtPnl(t.realized_pnl_options) + ")"
          : "");
    }

    (e.images || []).forEach(function (img) {
      var hidden = document.querySelector(
        '#or-upload-slots .or-upload-hidden[data-tf="' + img.tf + '"]'
      );
      var status = document.querySelector(
        '#or-upload-slots .or-upload-status[data-tf="' + img.tf + '"]'
      );
      if (hidden && img.file) {
        hidden.value = img.file;
        if (status) status.textContent = "已有 " + img.file;
      }
    });

    var legsHost = $("or-legs-host");
    if (legsHost) {
      if (t.legs && t.legs.length) {
        legsHost.innerHTML =
          "<h3>计划腿</h3><table class=\"options-strike-table\"><thead><tr><th>腿</th><th>合约</th><th>盈亏</th><th>原因</th></tr></thead><tbody>" +
          t.legs
            .map(function (leg) {
              return (
                "<tr><td>" +
                escapeHtml(leg.leg_role || "") +
                "</td><td>" +
                escapeHtml(leg.inst_id || leg.symbol || "") +
                "</td><td>" +
                fmtPnl(leg.realized_pnl) +
                "</td><td>" +
                escapeHtml(leg.close_reason || "") +
                "</td></tr>"
              );
            })
            .join("") +
          "</tbody></table>";
      } else {
        legsHost.innerHTML = "";
      }
    }
  }

  function hideTrade(tradeId) {
    if (!tradeId) return;
    if (!confirm("从待复盘列表删除并隐藏?刷新后也不会再出现.")) return;
    fetch("/api/options/review/trades/" + tradeId, {
      method: "DELETE",
      credentials: "same-origin",
    })
      .then(function (r) {
        return r.json();
      })
      .then(function (data) {
        if (!data.ok) {
          alert(data.msg || "删除失败");
          return;
        }
        if (currentTradeId === tradeId) hideJournalForm();
        reloadAll();
      })
      .catch(function () {
        alert("删除失败");
      });
  }

  function saveEntry() {
    var tradeId = Number(($("or-trade-id") || {}).value || 0);
    if (!tradeId) {
      alert("请先点击交易记录中的「复盘」");
      return;
    }
    var strategy = (($("or-f-strategy") || {}).value || "").trim();
    if (!strategy) {
      alert("请选择策略标签");
      return;
    }
    var payload = {
      trade_id: tradeId,
      strategy_tag: strategy,
      direction_view: ($("or-f-direction") || {}).value || "",
      exit_reason: ($("or-f-exit") || {}).value || "",
      followed_plan: ($("or-f-followed") || {}).value || "",
      result_tag: ($("or-f-result") || {}).value || "",
      mistake_tags: collectMoodTags(),
      entry_logic: ($("or-f-entry") || {}).value || "",
      note: ($("or-f-note") || {}).value || "",
      images: collectImages(),
    };
    ($("or-save-status") || {}).textContent = "保存中…";
    fetch("/api/options/review/entry", {
      method: "POST",
      credentials: "same-origin",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(payload),
    })
      .then(function (r) {
        return r.json();
      })
      .then(function (data) {
        if (!data.ok) {
          ($("or-save-status") || {}).textContent = data.msg || "保存失败";
          return;
        }
        ($("or-save-status") || {}).textContent = "已保存";
        hideJournalForm();
        reloadAll();
        openDetail(tradeId);
      })
      .catch(function () {
        ($("or-save-status") || {}).textContent = "保存失败";
      });
  }

  function deleteEntry() {
    var tradeId = Number(($("or-trade-id") || {}).value || 0);
    if (!tradeId) return;
    if (!confirm("删除该条复盘内容与图片?交易记录会回到待复盘列表.")) return;
    fetch("/api/options/review/entry/" + tradeId, {
      method: "DELETE",
      credentials: "same-origin",
    })
      .then(function (r) {
        return r.json();
      })
      .then(function () {
        hideJournalForm();
        hideDetail();
        reloadAll();
      });
  }

  function init() {
    if (!$("options-review-root")) return;
    document.querySelectorAll(".or-tab").forEach(function (btn) {
      btn.addEventListener("click", function () {
        setActiveTab(btn.getAttribute("data-source"));
      });
    });
    var reloadBtn = $("or-reload-btn");
    var saveBtn = $("or-save-btn");
    var clearBtn = $("or-clear-btn");
    var delBtn = $("or-del-btn");
    var prevBtn = $("or-trades-prev");
    var nextBtn = $("or-trades-next");
    var reviewedPrev = $("or-reviewed-prev");
    var reviewedNext = $("or-reviewed-next");
    var detailClose = $("or-detail-close-btn");
    var detailEdit = $("or-detail-edit-btn");
    if (reloadBtn) reloadBtn.addEventListener("click", reloadAll);
    if (saveBtn) saveBtn.addEventListener("click", saveEntry);
    if (clearBtn) clearBtn.addEventListener("click", hideJournalForm);
    if (delBtn) delBtn.addEventListener("click", deleteEntry);
    if (prevBtn) {
      prevBtn.addEventListener("click", function (ev) {
        ev.preventDefault();
        ev.stopPropagation();
        if (tradesPage <= 0) return;
        tradesPage -= 1;
        updateTradesPager();
        loadTrades({ sync: false, soft: true });
      });
    }
    if (nextBtn) {
      nextBtn.addEventListener("click", function (ev) {
        ev.preventDefault();
        ev.stopPropagation();
        if (tradesPage + 1 >= tradesPages) return;
        tradesPage += 1;
        updateTradesPager();
        loadTrades({ sync: false, soft: true });
      });
    }
    if (reviewedPrev) {
      reviewedPrev.addEventListener("click", function (ev) {
        ev.preventDefault();
        ev.stopPropagation();
        if (reviewedPage <= 0) return;
        reviewedPage -= 1;
        updateReviewedPager();
        loadReviewed({ sync: false, soft: true });
      });
    }
    if (reviewedNext) {
      reviewedNext.addEventListener("click", function (ev) {
        ev.preventDefault();
        ev.stopPropagation();
        if (reviewedPage + 1 >= reviewedPages) return;
        reviewedPage += 1;
        updateReviewedPager();
        loadReviewed({ sync: false, soft: true });
      });
    }
    if (detailClose) detailClose.addEventListener("click", hideDetail);
    if (detailEdit) {
      detailEdit.addEventListener("click", function () {
        var id = Number(detailEdit.getAttribute("data-id") || 0);
        if (id) openJournalForm(id);
      });
    }
    ["or-filter-uly", "or-filter-opt", "or-include-hedge-legs"].forEach(function (id) {
      var el = $(id);
      if (el) {
        el.addEventListener("change", function () {
          tradesPage = 0;
          reviewedPage = 0;
          reloadAll();
        });
      }
    });
    ["or-filter-strategy", "or-filter-from", "or-filter-to"].forEach(function (id) {
      var el = $(id);
      if (el) {
        el.addEventListener("change", function () {
          tradesPage = 0;
          reviewedPage = 0;
          reloadAll();
        });
      }
    });
    bindUploadSlots();
    hideJournalForm();
    hideDetail();
    setActiveTab("option_spot");
  }

  global.OptionsReview = {
    init: init,
    openJournalForm: openJournalForm,
    hideJournalForm: hideJournalForm,
  };

  if (document.readyState === "loading") {
    document.addEventListener("DOMContentLoaded", init);
  } else {
    init();
  }
})(typeof window !== "undefined" ? window : globalThis);
