window.XiaobaiPageModules.register("dragon_tiger", ["dragonView"], {
  enter: ["loadDragonTiger"],
});

/* PRESERVATION-SOURCE-BEGIN app.js:2660-3028 */
function selectDragonViewMode(mode) {
  state.dragonViewMode = mode === "profiles" ? "profiles" : "daily";
  document.querySelectorAll("[data-dragon-view-mode]").forEach((button) => {
    const active = button.dataset.dragonViewMode === state.dragonViewMode;
    button.classList.toggle("active", active);
    button.setAttribute("aria-pressed", String(active));
  });
  if (state.dragonViewMode === "profiles") {
    document.querySelector("#dragonDailyContent").hidden = true;
    document.querySelector("#dragonEmptyState").hidden = true;
    document.querySelector("#dragonProfilesContent").hidden = false;
    if (state.hotMoneyProfiles) renderHotMoneyProfiles();
    else loadHotMoneyProfiles();
  } else {
    document.querySelector("#dragonProfilesContent").hidden = true;
    if (state.dragonTiger) renderDragonTiger();
    else loadDragonTiger();
  }
}

async function loadHotMoneyProfiles(force = false) {
  if (!force && state.hotMoneyProfiles) {
    renderHotMoneyProfiles();
    return;
  }
  setStatus("正在加载游资档案");
  try {
    const query = new URLSearchParams();
    if (force) query.set("force", "1");
    const suffix = query.size ? `?${query}` : "";
    state.hotMoneyProfiles = await apiRequest(`/api/dragon-tiger/profiles${suffix}`);
    renderHotMoneyProfiles();
    const count = number(state.hotMoneyProfiles.summary?.profile_count);
    setStatus(`游资档案已加载 · 共 ${count} 位`);
  } catch (error) {
    showToast(error.message || "游资档案加载失败");
    setStatus("游资档案加载失败");
  }
}

function renderHotMoneyProfiles() {
  const payload = state.hotMoneyProfiles;
  if (!payload) return;
  const profiles = payload.profiles || [];
  const summary = payload.summary || {};
  const query = state.hotMoneyProfileQuery;
  const visible = profiles.filter((profile) => {
    if (!query) return true;
    return [profile.name, profile.description, ...(profile.organizations || [])]
      .join(" ")
      .toLocaleLowerCase("zh-CN")
      .includes(query);
  });
  if (!visible.some((profile) => profile.id === state.selectedHotMoneyProfileId)) {
    state.selectedHotMoneyProfileId = visible[0]?.id || "";
  }
  const selected = visible.find((profile) => profile.id === state.selectedHotMoneyProfileId) || null;

  setText("dragonDateLabel", `收录 ${number(summary.profile_count)} 位`);
  setText("hotMoneyProfileResultCount", query ? `${visible.length} / ${profiles.length} 位` : `${profiles.length} 位`);
  document.querySelector("#hotMoneyProfileSummary").innerHTML = [
    ["收录游资", number(summary.profile_count)],
    ["已有简介", number(summary.described_count)],
    ["关联席位", number(summary.organization_count)],
  ].map(([label, value]) => `<span><small>${label}</small><strong>${value}</strong></span>`).join("");

  const list = document.querySelector("#hotMoneyProfileList");
  list.innerHTML = visible.length ? visible.map((profile, index) => `
    <button class="hot-money-profile-row-v2 ${profile.id === state.selectedHotMoneyProfileId ? "selected" : ""}"
      type="button" role="option" aria-selected="${profile.id === state.selectedHotMoneyProfileId}"
      data-hot-money-profile="${escapeHtml(profile.id)}">
      <span class="hot-money-profile-index-v2">${String(index + 1).padStart(2, "0")}</span>
      <span class="hot-money-profile-monogram-v2">${escapeHtml(profile.name.slice(0, 2))}</span>
      <span class="hot-money-profile-row-copy-v2">
        <strong>${escapeHtml(profile.name)}</strong>
        <small>${escapeHtml(profile.description || "暂未收录简介")}</small>
      </span>
      <span class="hot-money-profile-seat-count-v2">${number(profile.organization_count)} 席</span>
    </button>`).join("") : `
      <div class="hot-money-profile-list-empty-v2">
        <i data-lucide="search-x" aria-hidden="true"></i>
        <span>${profiles.length ? "没有符合条件的游资档案" : "游资名录暂不可用"}</span>
      </div>`;

  const detail = document.querySelector("#hotMoneyProfileDetail");
  if (!selected) {
    detail.innerHTML = `
      <div class="hot-money-profile-empty-v2">
        <i data-lucide="contact" aria-hidden="true"></i>
        <strong>${profiles.length ? "选择一位游资查看档案" : "暂无可展示的游资档案"}</strong>
      </div>`;
  } else {
    const organizations = selected.organizations || [];
    detail.innerHTML = `
      <header class="hot-money-profile-detail-head-v2">
        <span class="hot-money-profile-avatar-v2">${escapeHtml(selected.name.slice(0, 2))}</span>
        <div>
          <small>游资档案</small>
          <h3>${escapeHtml(selected.name)}</h3>
          <span>${organizations.length ? `关联 ${organizations.length} 个公开席位` : "暂无关联席位"}</span>
        </div>
      </header>
      <section class="hot-money-profile-section-v2">
        <h4>人物简介</h4>
        <p class="${selected.description ? "" : "is-empty"}">${escapeHtml(selected.description || "名录暂未收录该游资的公开简介。")}</p>
      </section>
      <section class="hot-money-profile-section-v2 hot-money-profile-org-section-v2">
        <div class="hot-money-profile-section-title-v2">
          <h4>关联营业部</h4>
          <span>${organizations.length} 个</span>
        </div>
        <div class="hot-money-profile-organizations-v2">
          ${organizations.length ? organizations.map((organization) => `
            <span><i data-lucide="building-2" aria-hidden="true"></i>${escapeHtml(organization)}</span>
          `).join("") : '<p class="is-empty">名录暂未收录关联营业部。</p>'}
        </div>
      </section>
      ${payload.meta?.notice ? `<p class="hot-money-profile-notice-v2">${escapeHtml(payload.meta.notice)}</p>` : ""}`;
  }
  refreshIcons();
}

async function loadDragonTiger(force = false) {
  const requestedDate = elements.tradeDate.value;
  if (
    !force
    && ["success", "empty", "partial", "unavailable"].includes(state.dragonTiger?.meta?.status)
    && (state.dragonTiger?.meta?.requested_date || state.dragonTiger?.meta?.trade_date) === requestedDate
  ) {
    renderDragonTiger();
    return;
  }
  setStatus("正在加载龙虎榜");
  try {
    const query = new URLSearchParams({ trade_date: requestedDate });
    if (force) query.set("force", "1");
    const payload = await apiRequest(`/api/dragon-tiger?${query}`);
    state.dragonTiger = payload;
    renderDragonTiger();
    const statusLabel = payload.meta.status === "error"
      ? "龙虎榜数据暂不可用"
      : payload.meta.status === "empty"
        ? "当日暂无公开游资明细"
        : payload.meta.status === "partial"
          ? "当日有龙虎榜，暂无命名游资明细"
        : payload.meta.status === "unavailable" ? "龙虎榜数据暂不可用" : "龙虎榜明细";
    setStatus(`${statusLabel} · 龙虎榜已加载`);
  } catch (error) {
    showToast(error.message || "龙虎榜加载失败");
    setStatus("龙虎榜加载失败");
  }
}

function renderDragonTiger() {
  const payload = state.dragonTiger;
  if (!payload) return;
  const summary = payload.summary || {};
  if (state.dragonViewMode === "daily") setText("dragonDateLabel", `数据日期 ${payload.meta.trade_date}`);
  const status = payload.meta?.status || "empty";
  const hasRecognizedTraders = (payload.traders || []).some((item) => item.identity_type === "trader" && item.recognized !== false);
  const showEmptyState = !hasRecognizedTraders
    && !(payload.unclassified_seats || []).length
    && ["empty", "error", "unavailable"].includes(status);
  const dailyVisible = state.dragonViewMode === "daily";
  document.querySelector("#dragonProfilesContent").hidden = dailyVisible;
  document.querySelector("#dragonEmptyState").hidden = !dailyVisible || !showEmptyState;
  document.querySelector("#dragonDailyContent").hidden = !dailyVisible || showEmptyState;
  if (showEmptyState) {
    const unavailable = ["error", "unavailable"].includes(status);
    setText("dragonEmptyTitle", unavailable ? "龙虎榜数据暂不可用" : `${payload.meta?.trade_date || "该交易日"} 暂无龙虎榜明细`);
    setText("dragonEmptyDescription", unavailable
      ? "当前数据暂未完成更新，可稍后重新检查或查看前一交易日。"
      : "龙虎榜明细通常在交易日盘后陆续披露，可稍后刷新或查看前一交易日。");
  }
  document.querySelector("#dragonSummary").innerHTML = [
    ["上榜游资", `${number(summary.trader_count)} 位`, ""],
    ["操作明细", `${number(summary.operation_count)} 条`, ""],
    ["席位净买入", formatMoneyMillion(summary.seat_net_buy_million), changeClass(summary.seat_net_buy_million)],
    ["活跃股票", `${number(summary.active_stock_count)} 只`, ""],
  ].map(([label, value, className]) => `<div class="dragon-metric"><span>${label}</span><strong class="${className}">${value}</strong></div>`).join("");

  renderDragonTraderList();
  renderUnclassifiedSeats();
}

function renderDragonTraderList() {
  const payload = state.dragonTiger;
  if (!payload) return;
  let traders = [...(payload.traders || [])].filter((item) => item.identity_type === "trader" && item.recognized !== false);
  if (state.dragonFilter === "buy") traders = traders.filter((item) => number(item.net_buy_million) > 0);
  if (state.dragonFilter === "sell") traders = traders.filter((item) => number(item.net_buy_million) < 0);
  if (state.dragonFilter === "unclassified") traders = [];
  if (state.dragonQuery) {
    traders = traders.filter((item) => {
      const searchable = [
        item.name,
        ...(item.operations || []).flatMap((operation) => [operation.code, operation.name, operation.seat_name]),
      ].join(" ").toLowerCase();
      return searchable.includes(state.dragonQuery);
    });
  }

  const container = document.querySelector("#dragonTraderList");
  let emptyMessage = "没有符合当前条件的游资操作";
  if (!Array.isArray(payload.traders)) emptyMessage = "龙虎榜数据格式暂不可用，请稍后重试";
  else if (["error", "unavailable"].includes(payload.meta?.status)) emptyMessage = "龙虎榜数据暂不可用，请稍后重试";
  else if (payload.meta?.status === "empty") emptyMessage = "该交易日暂无游资每日明细";
  else if (payload.meta?.status === "partial") emptyMessage = `当日有 ${number(payload.summary?.official_stock_count)} 只股票上榜，但暂无可识别的游资明细`;
  if (!traders.some((item) => item.id === state.selectedDragonTraderId)) {
    state.selectedDragonTraderId = traders[0]?.id || "";
  }
  const cardMarkup = traders.map((trader, index) => {
    const description = trader.description || `${number(trader.stock_count)} 只股票，${number(trader.operation_count)} 笔操作`;
    return `
      <article class="dragon-trader-card dealing ${trader.id === state.selectedDragonTraderId ? "selected" : ""}" data-dragon-card="${escapeHtml(trader.id)}" aria-hidden="true" style="--deal-delay:${Math.min(index * 38, 650)}ms">
        <span class="dragon-card-rank">${String(index + 1).padStart(2, "0")}</span>
        <span class="dragon-card-monogram">${escapeHtml(trader.name.slice(0, 2))}</span>
        <span class="dragon-card-copy"><strong>${escapeHtml(trader.name)}</strong><q title="${escapeHtml(description)}">${escapeHtml(description)}</q></span>
        <span class="dragon-card-stats"><small>${number(trader.stock_count)} 股 · ${number(trader.operation_count)} 笔</small><b class="${changeClass(trader.net_buy_million)}">${formatMoneyMillion(trader.net_buy_million)}</b></span>
      </article>`;
  }).join("");
  const hitZoneMarkup = traders.map((trader) => `
    <button type="button" class="dragon-card-hit-zone" data-dragon-trader="${escapeHtml(trader.id)}" aria-label="查看 ${escapeHtml(trader.name)} 当日操作" aria-pressed="${trader.id === state.selectedDragonTraderId}"></button>
  `).join("");
  container.innerHTML = traders.length
    ? `${cardMarkup}<div class="dragon-card-hit-layer">${hitZoneMarkup}</div>`
    : emptyStateHtml(state.dragonFilter === "unclassified" ? "待归类席位请在下方管理" : emptyMessage, { className: "dragon-empty" });
  container.querySelectorAll("[data-dragon-card]").forEach((card) => {
    card.addEventListener("animationend", () => card.classList.remove("dealing"), { once: true });
  });
  container.querySelectorAll("[data-dragon-trader]").forEach((hitZone) => {
    const setHovered = (hovered) => {
      container.querySelector(`[data-dragon-card="${CSS.escape(hitZone.dataset.dragonTrader)}"]`)?.classList.toggle("hovered", hovered);
    };
    hitZone.addEventListener("pointerenter", () => setHovered(true));
    hitZone.addEventListener("pointerleave", () => setHovered(false));
    hitZone.addEventListener("focus", () => setHovered(true));
    hitZone.addEventListener("blur", () => setHovered(false));
    hitZone.addEventListener("click", () => {
      state.selectedDragonTraderId = hitZone.dataset.dragonTrader;
      container.querySelectorAll("[data-dragon-card]").forEach((card) => {
        card.classList.toggle("selected", card.dataset.dragonCard === state.selectedDragonTraderId);
      });
      container.querySelectorAll("[data-dragon-trader]").forEach((item) => {
        item.setAttribute("aria-pressed", String(item.dataset.dragonTrader === state.selectedDragonTraderId));
      });
      renderDragonTraderDetail(traders.find((item) => item.id === state.selectedDragonTraderId));
    });
  });
  requestAnimationFrame(() => layoutDragonCards(container));
  renderDragonTraderDetail(traders.find((item) => item.id === state.selectedDragonTraderId));
}

function layoutDragonCards(container = document.querySelector("#dragonTraderList")) {
  if (!container) return;
  const cards = [...container.querySelectorAll(".dragon-trader-card")];
  const hitZones = [...container.querySelectorAll(".dragon-card-hit-zone")];
  if (!cards.length) return;
  const compact = window.innerWidth <= 720;
  const cardWidth = compact ? 148 : 176;
  const available = Math.max(cardWidth, container.clientWidth - (compact ? 30 : 72));
  const spread = Math.min(available - cardWidth, compact ? 310 : 1050);
  const step = cards.length > 1 ? Math.min(cardWidth + 14, spread / (cards.length - 1)) : 0;
  const center = (cards.length - 1) / 2;
  container.style.setProperty("--dragon-card-width", `${cardWidth}px`);
  cards.forEach((card, index) => {
    const x = (index - center) * step;
    card.style.setProperty("--card-x", `${x.toFixed(2)}px`);
    card.style.setProperty("--card-rotation", "0deg");
    card.style.setProperty("--card-y", "0px");
    card.style.zIndex = String(index + 1);
    const hitZone = hitZones[index];
    if (hitZone) {
      const zoneWidth = index === cards.length - 1 ? cardWidth : Math.max(18, step);
      hitZone.style.left = `calc(50% + ${(x - cardWidth / 2).toFixed(2)}px)`;
      hitZone.style.width = `${zoneWidth.toFixed(2)}px`;
    }
  });
}

function renderDragonTraderDetail(trader) {
  const container = document.querySelector("#dragonTraderDetail");
  if (!trader) {
    container.hidden = true;
    renderEmptyState(container, "选择一位游资查看操作明细", { className: "dragon-empty" });
    return;
  }
  container.hidden = false;
  container.innerHTML = `
    <header class="dragon-detail-header">
      <div><span>当日操作明细</span><h3>${escapeHtml(trader.name)}</h3><p>${escapeHtml(trader.description || "按当日公开龙虎榜席位汇总")}</p></div>
      <dl><div><dt>买入</dt><dd class="up">${formatMoneyMillion(trader.buy_million)}</dd></div><div><dt>卖出</dt><dd class="down">${formatMoneyMillion(trader.sell_million)}</dd></div><div><dt>净额</dt><dd class="${changeClass(trader.net_buy_million)}">${formatMoneyMillion(trader.net_buy_million)}</dd></div></dl>
    </header>
    <div class="trader-operations table-frame tbl-wrap">
      <table class="data-table tbl dragon-operation-table">
        <colgroup><col class="dragon-col-index"><col class="dragon-col-stock"><col class="dragon-col-direction"><col class="dragon-col-number"><col class="dragon-col-number"><col class="dragon-col-number"><col class="dragon-col-number"><col class="dragon-col-seat"><col class="dragon-col-reason"></colgroup>
        <thead><tr><th class="row-number num">序号</th><th>股票</th><th>方向</th><th class="number num">涨幅（%）</th><th class="number num">买入（百万）</th><th class="number num">卖出（百万）</th><th class="number num">净额（百万）</th><th>关联席位</th><th class="reason-column">标签 / 上榜原因</th></tr></thead>
        <tbody>${(trader.operations || []).map((operation, index) => `
          <tr data-code="${escapeHtml(operation.code)}">
            <td class="row-number num">${index + 1}</td>
            <td><strong class="sname">${escapeHtml(operation.name)}</strong><span class="scode">${escapeHtml(operation.code)}</span></td>
            <td><span class="direction-label ${changeClass(operation.net_buy_million)}">${escapeHtml(operation.direction)}</span></td>
            <td class="number num ${operation.change == null ? "" : changeClass(operation.change)}">${operation.change == null ? "" : signed(operation.change)}</td>
            <td class="number num">${operation.buy_million == null ? "" : formatNumber(operation.buy_million, 2)}</td>
            <td class="number num">${operation.sell_million == null ? "" : formatNumber(operation.sell_million, 2)}</td>
            <td class="number num ${operation.net_buy_million == null ? "" : changeClass(operation.net_buy_million)}">${operation.net_buy_million == null ? "" : signed(operation.net_buy_million)}</td>
            <td class="seat-cell" title="${escapeHtml(operation.seat_name)}">${escapeHtml(operation.seat_name)}</td>
            <td class="reason-column" title="${escapeHtml([operation.tag, operation.reason].filter((item) => item && item !== "--").join(" · "))}">${escapeHtml(operation.tag && operation.tag !== "--" ? operation.tag : operation.reason && operation.reason !== "--" ? operation.reason : "")}</td>
          </tr>`).join("")}</tbody>
      </table>
    </div>`;
  bindStockRows(container);
  markAutoSortableHeaders(container);
}

function renderUnclassifiedSeats() {
  const seats = state.dragonTiger?.unclassified_seats || [];
  const canManage = state.user?.role === "admin";
  document.querySelector("#dragonUnclassifiedSection").hidden = !canManage || seats.length === 0;
  document.querySelector("#dragonUnclassifiedFilter").hidden = !canManage || seats.length === 0;
  if (!seats.length && state.dragonFilter === "unclassified") {
    state.dragonFilter = "all";
    document.querySelectorAll("[data-dragon-filter]").forEach((button) => {
      button.classList.toggle("active", button.dataset.dragonFilter === "all");
    });
    renderDragonTraderList();
  }
  setText("unclassifiedCount", `${seats.length} 个`);
  const list = document.querySelector("#unclassifiedSeatList");
  list.innerHTML = seats.map((seat, index) => `
    <form class="unclassified-seat-row" data-unclassified-index="${index}">
      <span class="unclassified-seat-name" title="${escapeHtml(seat.seat_name)}">${escapeHtml(seat.seat_name)}</span>
      <span class="unclassified-seat-stats">${number(seat.operation_count)} 笔 · ${number(seat.stock_count)} 股</span>
      <strong class="${changeClass(seat.net_buy_million)}">${formatMoneyMillion(seat.net_buy_million)}</strong>
      <input type="text" maxlength="50" placeholder="输入游资名" aria-label="${escapeHtml(seat.seat_name)}的游资名" required>
      <button class="button" type="submit">归类</button>
    </form>
  `).join("") || emptyStateHtml("当前席位均已归类");
  list.querySelectorAll(".unclassified-seat-row").forEach((form) => {
    form.addEventListener("submit", saveSeatAlias);
  });
}

function dragonIdentityLabel(type) {
  return { trader: "游资", institution: "机构", channel: "通道", unclassified: "待归类" }[type] || "席位";
}

async function saveSeatAlias(event) {
  event.preventDefault();
  const form = event.currentTarget;
  const seat = state.dragonTiger?.unclassified_seats?.[number(form.dataset.unclassifiedIndex)];
  const alias = form.querySelector("input").value.trim();
  if (!seat || !alias) {
    showToast("请输入游资名");
    return;
  }
  const button = form.querySelector("button");
  button.disabled = true;
  try {
    await apiRequest("/api/seat-aliases", "POST", { seat_name: seat.seat_name, alias });
    state.dragonTiger = null;
    await loadDragonTiger();
    showToast(`已将席位归类为 ${alias}`);
  } catch (error) {
    showToast(error.message);
    button.disabled = false;
  }
}

/* PRESERVATION-SOURCE-END app.js:2660-3028 */
