/**
 * 三所实例共用 UI:复盘详情,盈亏着色等.
 */
(function (global) {
  "use strict";

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

  function pnlClassFromValue(val) {
    const n = Number(String(val == null ? "" : val).replace(/[^\d.-]/g, ""));
    if (!Number.isFinite(n) || n === 0) return "";
    return n > 0 ? "pnl-profit" : "pnl-loss";
  }

  function formatPnlSpan(val, suffix) {
    const sfx = suffix == null ? "U" : suffix;
    const cls = pnlClassFromValue(val);
    const text = escapeHtml(val == null || val === "" ? "-" : val) + sfx;
    return cls ? `<span class="${cls}">${text}</span>` : text;
  }

  function buildJournalDetailHtml(o, formatExitLine) {
    const moodTags =
      Array.isArray(o.mood_issues) && o.mood_issues.length
        ? o.mood_issues.join(",")
        : o.mood_issues || "无";
    const exitText =
      typeof formatExitLine === "function" ? formatExitLine(o) : o.exit_reason || "无";
    const lines = [
      `币种/周期:${escapeHtml(o.coin || "-")} ${escapeHtml(o.tf || "-")}`,
      `方向:${escapeHtml((function(){ const d = inferJournalDirection(o); return d ? d.text : "-"; })())}`,
      `开仓时间:${escapeHtml(o.open_datetime || "-")}`,
      `平仓时间:${escapeHtml(o.close_datetime || "-")}`,
      `持仓时长:${escapeHtml(o.hold_duration || "-")}`,
      `盈亏:${formatPnlSpan(o.pnl)}`,
      `下单类型:${escapeHtml(o.order_type || "无")}`,
      `开仓类型:${escapeHtml(o.entry_reason || "无")}`,
      `平仓/离场:${escapeHtml(exitText)}`,
      `预期RR:${escapeHtml(o.expect_rr || "-")}`,
      `实际RR:${escapeHtml(o.real_rr || "-")}`,
      `保本后盯盘:${escapeHtml(o.post_breakeven_stare || "-")}`,
      `心态标签:${escapeHtml(moodTags)}`,
      `备注:${escapeHtml(o.note || "无")}`,
    ];
    return lines.join("<br>");
  }

  function resolveJournalImages(o) {
    if (Array.isArray(o.images) && o.images.length) return o.images;
    if (o.image) return [{ tf: "", file: o.image }];
    return [];
  }

  function setJournalDetailImages(o) {
    const grid = document.getElementById("detailImages");
    const legacyImg = document.getElementById("detailImage");
    const images = resolveJournalImages(o || {});

    if (grid) {
      if (!images.length) {
        grid.innerHTML = "";
        grid.style.display = "none";
      } else {
        grid.innerHTML = images
          .map(function (img) {
            const tf = String(img.tf || "").trim();
            const file = String(img.file || "").trim();
            if (!file) return "";
            const label = tf ? escapeHtml(tf) : "截图";
            const src = "/static/images/" + encodeURIComponent(file).replace(/%2F/g, "/");
            return (
              '<div class="journal-detail-img-cell">' +
              '<span class="journal-detail-img-label">' +
              label +
              "</span>" +
              '<img class="journal-detail-img-thumb" src="' +
              src +
              '" alt="' +
              label +
              '" onclick="showImage(this.src)">' +
              "</div>"
            );
          })
          .join("");
        grid.style.display = "grid";
      }
      if (legacyImg) {
        legacyImg.src = "";
        legacyImg.style.display = "none";
      }
      return;
    }

    if (legacyImg) {
      if (images.length === 1) {
        legacyImg.src = "/static/images/" + images[0].file;
        legacyImg.style.display = "block";
      } else {
        legacyImg.src = "";
        legacyImg.style.display = "none";
      }
    }
  }

  function clearJournalDetailImages() {
    const grid = document.getElementById("detailImages");
    if (grid) {
      grid.innerHTML = "";
      grid.style.display = "none";
    }
    const legacyImg = document.getElementById("detailImage");
    if (legacyImg) {
      legacyImg.src = "";
      legacyImg.style.display = "none";
    }
  }

  function setJournalDetailBody(o, formatExitLine) {
    const body = document.getElementById("detailBody");
    if (!body) return;
    body.classList.remove("md-review", "trade-record-detail-wrap");
    body.classList.add("journal-detail-meta");
    body.innerHTML = buildJournalDetailHtml(o, formatExitLine);
  }

  function openJournalDetailModal(id, journalCache, formatExitLine) {
    const o = journalCache && journalCache[id];
    if (!o) return;
    const titleEl = document.getElementById("detailTitle");
    if (titleEl) {
      titleEl.innerText = `交易复盘详情｜${o.coin || "-"} ${o.tf || "-"}`;
    }
    setJournalDetailBody(o, formatExitLine);
    clearDetailActions();
    setJournalDetailImages(o);
    if (typeof setDetailModalFullscreen === "function") {
      setDetailModalFullscreen(false);
    }
    const modal = document.getElementById("detailModal");
    if (modal) modal.style.display = "flex";
  }

  function isMobileCompactRecords() {
    if (typeof window === "undefined" || !window.matchMedia) return false;
    return window.matchMedia("(max-width: 720px)").matches;
  }

  function inferJournalDirection(o) {
    const hint = String((o && (o.direction_hint || o.direction)) || "").toLowerCase();
    if (hint === "long" || hint === "buy" || hint === "多") {
      return { text: "做多", cls: "direction-long" };
    }
    if (hint === "short" || hint === "sell" || hint === "空") {
      return { text: "做空", cls: "direction-short" };
    }
    const text = String((o && (o.entry_reason || o.note)) || "");
    if (/做空|空头|short/i.test(text)) {
      return { text: "做空", cls: "direction-short" };
    }
    if (/做多|多头|long/i.test(text)) {
      return { text: "做多", cls: "direction-long" };
    }
    return null;
  }

  function renderJournalListHtml(data) {
    if (!data || !data.length) return "";
    const mobile = isMobileCompactRecords();
    if (mobile) {
      return data
        .map(function (o) {
          const dir = inferJournalDirection(o);
          const pnlCls = pnlClassFromValue(o.pnl);
          const dirHtml = dir
            ? `<span class="badge ${dir.cls}">${escapeHtml(dir.text)}</span>`
            : `<span class="mrr-muted">-</span>`;
          const id = escapeHtml(o.id);
          return `<div class="mobile-record-row-wrap">
            <button type="button" class="mobile-record-row" onclick="openJournalDetail('${id}')">
              <span class="mrr-symbol">${escapeHtml(o.coin || "-")} ${escapeHtml(o.tf || "")}</span>
              <span class="mrr-dir">${dirHtml}</span>
              <span class="mrr-pnl ${pnlCls}">${escapeHtml(o.pnl == null || o.pnl === "" ? "-" : o.pnl)}U</span>
            </button>
            <button type="button" class="mobile-record-del" title="删除" onclick="deleteJournal('${id}')">×</button>
          </div>`;
        })
        .join("");
    }
    const rows = data
      .map(function (o) {
        const moodTags = Array.isArray(o.mood_issues)
          ? o.mood_issues.join(",")
          : o.mood_issues || "";
        const mood = moodTags || "无";
        const id = escapeHtml(o.id);
        const pnlCls = pnlClassFromValue(o.pnl);
        const pnlTxt =
          o.pnl == null || o.pnl === "" ? "-" : String(o.pnl);
        const dir = inferJournalDirection(o);
        const dirHtml = dir
          ? `<span class="badge ${dir.cls}">${escapeHtml(dir.text)}</span>`
          : "-";
        return `<tr id="journal-row-${id}">
          <td>${escapeHtml(o.coin || "-")}</td>
          <td>${escapeHtml(o.tf || "-")}</td>
          <td>${dirHtml}</td>
          <td>${escapeHtml(o.order_type || "-")}</td>
          <td>${escapeHtml(o.entry_reason || "-")}</td>
          <td><span class="${pnlCls}">${escapeHtml(pnlTxt)}</span></td>
          <td>${escapeHtml((o.open_datetime || "-").toString().slice(0, 16))}</td>
          <td>${escapeHtml((o.close_datetime || "-").toString().slice(0, 16))}</td>
          <td>${escapeHtml(o.hold_duration || "-")}</td>
          <td>${escapeHtml(mood)}</td>
          <td>
            <button type="button" class="table-del" style="background:#1f3a5a;color:#8fc8ff;margin-right:6px" onclick="openJournalDetail('${id}')">查看详情</button>
            <button type="button" class="table-del" onclick="deleteJournal('${id}')">删除</button>
          </td>
        </tr>`;
      })
      .join("");
    return `<div class="table-wrap"><table class="rr-journals-table">
      <thead><tr>
        <th>品种</th><th>周期</th><th>方向</th><th>下单类型</th><th>开仓类型</th>
        <th>盈亏U</th><th>开仓时间</th><th>平仓时间</th><th>持仓</th><th>心态标签</th><th>操作</th>
      </tr></thead>
      <tbody>${rows}</tbody>
    </table></div>`;
  }

  function parseTradeRecordRow(tr) {
    const cells = tr.querySelectorAll("td");
    if (cells.length < 15) return null;
    const dirBadge = cells[3].querySelector(".badge");
    return {
      rowId: tr.id,
      symbol: cells[0].textContent.trim(),
      type: cells[1].textContent.trim(),
      entryReason: cells[2].textContent.trim(),
      directionHtml: (dirBadge ? dirBadge.outerHTML : cells[3].innerHTML).trim(),
      directionText: cells[3].textContent.trim(),
      trigger: cells[4].textContent.trim(),
      stopLoss: cells[5].textContent.trim(),
      takeProfit: cells[6].textContent.trim(),
      margin: cells[7].textContent.trim(),
      leverage: cells[8].textContent.trim(),
      holdMinutes: cells[9].textContent.trim(),
      openedAt: cells[10].textContent.trim(),
      closedAt: cells[11].textContent.trim(),
      pnlHtml: cells[12].innerHTML.trim(),
      pnlText: cells[12].textContent.trim(),
      resultHtml: cells[13].innerHTML.trim(),
      resultText: cells[13].textContent.trim(),
      actionsHtml: cells[14].innerHTML,
    };
  }

  function renderMobileTradeRow(tr) {
    const row = parseTradeRecordRow(tr);
    if (!row) return "";
    const pnlCls = pnlClassFromValue(row.pnlText);
    return `<button type="button" class="mobile-record-row" data-row-id="${escapeHtml(row.rowId)}">
      <span class="mrr-symbol">${escapeHtml(row.symbol)}</span>
      <span class="mrr-dir">${row.directionHtml}</span>
      <span class="mrr-pnl ${pnlCls}">${escapeHtml(row.pnlText || "-")}</span>
    </button>`;
  }

  function tradeDetailRow(label, valueHtml) {
    return `<div class="trd-row"><span class="trd-label">${escapeHtml(label)}</span><span class="trd-value">${valueHtml}</span></div>`;
  }

  function buildTradeRecordDetailHtml(row) {
    return `<div class="trade-record-detail">${
      tradeDetailRow("品种", escapeHtml(row.symbol)) +
      tradeDetailRow("下单类型", escapeHtml(row.type)) +
      tradeDetailRow("开仓类型", escapeHtml(row.entryReason || "-")) +
      tradeDetailRow("方向", row.directionHtml) +
      tradeDetailRow("成交价", escapeHtml(row.trigger)) +
      tradeDetailRow("止损(开仓)", escapeHtml(row.stopLoss)) +
      tradeDetailRow("止盈", escapeHtml(row.takeProfit)) +
      tradeDetailRow("基数", escapeHtml(row.margin)) +
      tradeDetailRow("杠杆", escapeHtml(row.leverage)) +
      tradeDetailRow("持仓分钟", escapeHtml(row.holdMinutes)) +
      tradeDetailRow("开仓时间", escapeHtml(row.openedAt)) +
      tradeDetailRow("平仓时间", escapeHtml(row.closedAt)) +
      tradeDetailRow("盈亏U", row.pnlHtml) +
      tradeDetailRow("结果", row.resultHtml)
    }</div>`;
  }

  function clearDetailActions() {
    const el = document.getElementById("detailActions");
    if (el) {
      el.innerHTML = "";
      el.style.display = "none";
    }
  }

  function setDetailActionsHtml(html) {
    let el = document.getElementById("detailActions");
    if (!el) {
      const panel = document.querySelector("#detailModal .panel");
      if (!panel) return;
      el = document.createElement("div");
      el.id = "detailActions";
      el.className = "detail-actions";
      const body = document.getElementById("detailBody");
      if (body && body.parentNode === panel) {
        panel.insertBefore(el, body.nextSibling);
      } else {
        panel.appendChild(el);
      }
    }
    el.innerHTML = html || "";
    el.style.display = html ? "flex" : "none";
  }

  function promptReviewEntryReason(options, currentValue) {
    const opts = Array.isArray(options) ? options : [];
    const cur = String(currentValue == null ? "" : currentValue).trim();
    return new Promise(function (resolve) {
      const backdrop = document.createElement("div");
      backdrop.className = "review-entry-reason-backdrop open";
      const modal = document.createElement("div");
      modal.className = "review-entry-reason-modal";
      modal.setAttribute("role", "dialog");
      modal.setAttribute("aria-modal", "true");

      const title = document.createElement("h3");
      title.textContent = "开仓类型";
      modal.appendChild(title);

      const hint = document.createElement("p");
      hint.className = "review-entry-reason-hint";
      hint.textContent = "请选择下拉选项之一;选「不改该项」则保留原值.";
      modal.appendChild(hint);

      const select = document.createElement("select");
      select.className = "review-entry-reason-select";
      const emptyOpt = document.createElement("option");
      emptyOpt.value = "";
      emptyOpt.textContent = "(不改该项)";
      select.appendChild(emptyOpt);

      const seen = new Set([""]);
      if (cur && opts.indexOf(cur) < 0) {
        const curOpt = document.createElement("option");
        curOpt.value = cur;
        curOpt.textContent = cur + "(当前)";
        select.appendChild(curOpt);
        seen.add(cur);
      }
      opts.forEach(function (opt) {
        const v = String(opt || "").trim();
        if (!v || seen.has(v)) return;
        const o = document.createElement("option");
        o.value = v;
        o.textContent = v;
        select.appendChild(o);
        seen.add(v);
      });
      if (cur) select.value = cur;
      modal.appendChild(select);

      const actions = document.createElement("div");
      actions.className = "review-entry-reason-actions";
      const cancelBtn = document.createElement("button");
      cancelBtn.type = "button";
      cancelBtn.className = "review-entry-reason-cancel";
      cancelBtn.textContent = "取消";
      const okBtn = document.createElement("button");
      okBtn.type = "button";
      okBtn.className = "review-entry-reason-ok";
      okBtn.textContent = "确定";
      actions.appendChild(cancelBtn);
      actions.appendChild(okBtn);
      modal.appendChild(actions);
      backdrop.appendChild(modal);
      document.body.appendChild(backdrop);

      function cleanup(result) {
        document.removeEventListener("keydown", onKey);
        backdrop.remove();
        resolve(result);
      }
      function onKey(ev) {
        if (ev.key === "Escape") cleanup(null);
      }
      cancelBtn.addEventListener("click", function () {
        cleanup(null);
      });
      backdrop.addEventListener("click", function (ev) {
        if (ev.target === backdrop) cleanup(null);
      });
      okBtn.addEventListener("click", function () {
        cleanup(select.value);
      });
      document.addEventListener("keydown", onKey);
      select.focus();
    });
  }

  function openTradeRecordDetailModal(tr) {
    const row = parseTradeRecordRow(tr);
    if (!row) return;
    const titleEl = document.getElementById("detailTitle");
    if (titleEl) {
      titleEl.innerText = `交易记录｜${row.symbol}`;
    }
    const body = document.getElementById("detailBody");
    if (body) {
      body.classList.remove("md-review", "journal-detail-meta");
      body.classList.add("trade-record-detail-wrap");
      body.innerHTML = buildTradeRecordDetailHtml(row);
    }
    setDetailActionsHtml(
      `<div class="detail-actions-inner">${row.actionsHtml}</div>`
    );
    const imgEl = document.getElementById("detailImage");
    if (imgEl) {
      imgEl.src = "";
      imgEl.style.display = "none";
    }
    if (typeof setDetailModalFullscreen === "function") {
      setDetailModalFullscreen(false);
    }
    const modal = document.getElementById("detailModal");
    if (modal) modal.style.display = "flex";
  }

  global.InstanceUI = {
    escapeHtml: escapeHtml,
    pnlClassFromValue: pnlClassFromValue,
    formatPnlSpan: formatPnlSpan,
    buildJournalDetailHtml: buildJournalDetailHtml,
    setJournalDetailBody: setJournalDetailBody,
    openJournalDetailModal: openJournalDetailModal,
    isMobileCompactRecords: isMobileCompactRecords,
    inferJournalDirection: inferJournalDirection,
    renderJournalListHtml: renderJournalListHtml,
    parseTradeRecordRow: parseTradeRecordRow,
    renderMobileTradeRow: renderMobileTradeRow,
    buildTradeRecordDetailHtml: buildTradeRecordDetailHtml,
    openTradeRecordDetailModal: openTradeRecordDetailModal,
    clearDetailActions: clearDetailActions,
    clearJournalDetailImages: clearJournalDetailImages,
    setJournalDetailImages: setJournalDetailImages,
    promptReviewEntryReason: promptReviewEntryReason,
  };
})(typeof window !== "undefined" ? window : globalThis);
