window.XiaobaiPageModules.register("auction", ["auctionView"], {
  enter: ["loadAuction"],
  leave: ["clearAuction"],
});

/* PRESERVATION-SOURCE-BEGIN app.js:2217-2481 */
async function loadAuctionCenter(force = false) {
  if (state.auctionLoading) return;
  state.auctionLoading = true;
  const button = document.querySelector("#auctionRefreshButton");
  button.disabled = true;
  setText("auctionDateLabel", "正在读取竞价数据");
  try {
    const query = new URLSearchParams({ trade_date: elements.tradeDate.value });
    if (force) query.set("force", "1");
    state.auctionData = await apiRequest(`/api/auction?${query}`);
    renderAuctionCenter();
    scheduleAuctionTransition(state.auctionData.meta || {});
  } catch (error) {
    document.querySelector("#auctionSummary").innerHTML = "";
    document.querySelector("#auctionThemeCarry").innerHTML = "";
    document.querySelector("#auctionNewThemes").innerHTML = "";
    document.querySelector("#auctionAmountTrend").innerHTML = "";
    document.querySelector("#auctionAmountCompare").innerHTML = "";
    document.querySelector("#auctionTableBody").innerHTML = "";
    document.querySelector("#auctionEmpty").hidden = false;
    setText("auctionDateLabel", error.message || "竞价数据暂不可用");
    showToast(error.message || "竞价数据加载失败");
  } finally {
    state.auctionLoading = false;
    button.disabled = false;
  }
}

function renderAuctionCenter() {
  const payload = state.auctionData;
  if (!payload) return;
  const summary = payload.summary || {};
  renderAuctionPhase(payload.meta || {});
  setText(
    "auctionDateLabel",
    `${payload.meta?.carried_forward ? "最近有效竞价" : "竞价日期"} ${payload.meta?.trade_date || "--"}`,
  );
  document.querySelector("#auctionSummary").innerHTML = [
    ["竞价覆盖", `${formatNumber(summary.stock_count, 0)} 只`, ""],
    ["重点异动", `${formatNumber(summary.focus_count, 0)} 只`, "up"],
    ["竞价一字", `${formatNumber(summary.one_price_count, 0)} 只`, ""],
    ["竞价成交额", `${formatNumber(summary.amount_billion, 2)} 亿`, ""],
  ].map(([label, value, tone]) => `<div><span>${label}</span><strong class="${tone}">${value}</strong></div>`).join("");
  setText("auctionFocusCount", number(summary.focus_count));
  setText("auctionAllCount", number(summary.candidate_count));
  setText("auctionOnePriceCount", number(summary.one_price_count));
  setText("auctionWatchlistCount", number(payload.watchlist_rows?.length));
  renderAuctionInsights(payload);
  renderAuctionTable();
}

function renderAuctionInsights(payload) {
  const themes = payload.themes || {};
  const carry = themes.carry || [];
  const tone = { "强承接": "strong", "有承接": "steady", "分歧": "mixed", "承接弱": "weak" };
  setText("auctionThemeBaseline", `基于 ${payload.candidate_meta?.baseline_date || "--"}`);
  document.querySelector("#auctionThemeCarry").innerHTML = carry.length
    ? carry.map((item) => `
      <div class="auction-theme-row">
        <strong class="auction-theme-name">${escapeHtml(item.name)}</strong>
        <span class="auction-theme-info">${escapeHtml(item.leader || "--")} · 昨日 ${number(item.prior_limit_count)} 只涨停</span>
        <span class="auction-theme-status ${tone[item.status] || "mixed"}">${escapeHtml(item.status)}</span>
        <span class="auction-theme-median ${item.median_change == null ? "" : changeClass(item.median_change)}">${item.median_change == null ? "暂无有效候选" : `${signed(item.median_change)}%`}<small>中位</small></span>
      </div>`).join("")
    : '<div class="auction-inline-empty">暂无昨日强势题材基线</div>';

  const newThemes = themes.new_themes || [];
  document.querySelector("#auctionNewThemes").innerHTML = newThemes.length
    ? newThemes.map((item) => `<span title="${escapeHtml((item.leaders || []).join("、"))}">${escapeHtml(item.name)} <strong>${number(item.stock_count)}</strong></span>`).join("")
    : '<small>尚未形成多股共振的新线索</small>';

  const history = payload.amount_history || [];
  const maximum = Math.max(...history.map((item) => number(item.amount_billion)), 1);
  const priorFive = history.slice(Math.max(0, history.length - 6), Math.max(0, history.length - 1));
  const fiveDayAverage = priorFive.length
    ? priorFive.reduce((sum, item) => sum + number(item.amount_billion), 0) / priorFive.length
    : null;
  document.querySelector("#auctionAmountTrend").innerHTML = history.length
    ? history.map((item, index) => {
      const height = Math.max(8, number(item.amount_billion) / maximum * 100);
      const current = index === history.length - 1 ? " current" : "";
      return `<div class="auction-amount-day${current}" title="${escapeHtml(item.trade_date)} · ${formatNumber(item.amount_billion, 2)} 亿 · ${number(item.stock_count)} 只">
        <span style="height:${height.toFixed(1)}%"></span><small>${escapeHtml(String(item.trade_date || "").slice(5))}</small>
      </div>`;
    }).join("") + (fiveDayAverage === null ? "" : `<div class="auction-amount-average" style="bottom:${(20 + Math.min(fiveDayAverage / maximum, 1) * 82).toFixed(1)}px"><small>5日均 ${formatNumber(fiveDayAverage, 1)}</small></div>`)
    : '<div class="auction-inline-empty">历史竞价量能尚未形成</div>';
  setText("auctionAmountValue", `${formatNumber(payload.summary?.amount_billion, 2)} 亿`);
  const comparison = [
    ["较昨日", payload.summary?.amount_change_previous],
    ["较5日均值", payload.summary?.amount_change_5d],
  ];
  document.querySelector("#auctionAmountCompare").innerHTML = comparison.map(([label, value]) => `
    <span>${label}<strong class="${value == null ? "" : changeClass(value)}">${value == null ? "--" : `${signed(value)}%`}</strong></span>
  `).join("");
}

function renderAuctionPhase(meta) {
  const phase = meta.phase || "archive";
  const available = Boolean(meta.available);
  const copy = {
    pending: ["竞价尚未开始", "9:15 进入观察期，9:25 读取最终竞价结果。", "下一阶段 09:15"],
    observing: ["竞价观察期", "此阶段先观察盘前变化，系统将在 9:25 自动读取最终结果。", "09:25 定格"],
    selection: available
      ? ["竞价筛选窗口", "最终竞价结果已经定格，请在 9:30 前完成筛选。", "有效至 09:30"]
      : ["等待最终竞价", "9:25 数据尚未到达，系统正在自动重试。", "即将更新"],
    finalized: ["今日竞价已定格", "9:30 后停止更新，仅保留用于复盘、回测与智能选股。", "已冻结"],
    archive: ["历史竞价归档", "当前展示所选交易日的最终竞价结果。", "归档数据"],
  }[phase] || ["竞价状态", "当前竞价状态待确认。", "--"];
  const notice = document.querySelector("#auctionPhaseNotice");
  notice.dataset.phase = phase;
  setText("auctionPhaseTitle", copy[0]);
  setText("auctionPhaseDetail", copy[1]);
  setText("auctionPhaseTime", copy[2]);
  const refresh = document.querySelector("#auctionRefreshButton");
  refresh.hidden = phase !== "selection";
  refresh.disabled = state.auctionLoading;
}

function clearAuctionTimer() {
  if (state.auctionTimer) clearTimeout(state.auctionTimer);
  state.auctionTimer = null;
}

function scheduleAuctionTransition(meta) {
  clearAuctionTimer();
  if (state.activeView !== "auctionView") return;
  let delay = 0;
  if (["selection", "finalized"].includes(meta.phase) && !meta.available) {
    delay = 10_000;
  } else if (meta.next_transition_at) {
    const transitionAt = new Date(meta.next_transition_at).getTime();
    if (Number.isFinite(transitionAt)) delay = Math.max(800, transitionAt - Date.now() + 500);
  }
  if (!delay) return;
  state.auctionTimer = setTimeout(() => {
    state.auctionTimer = null;
    if (state.activeView === "auctionView") loadAuctionCenter(true);
  }, Math.min(delay, 2_147_000_000));
}

function renderAuctionTable() {
  const rows = currentAuctionRows();
  const columns = auctionColumns();
  const head = document.querySelector("#auctionTableHead");
  head.innerHTML = columns.map((column) => {
    const sorted = column.sortKey === state.auctionSortKey;
    const arrow = !column.sortKey ? "" : `<span class="arr">${sorted ? (state.auctionSortDirection === "desc" ? "▼" : "▲") : "↕"}</span>`;
    return `<th class="${column.numeric ? "number num " : ""}${column.sortKey ? "sortable " : ""}${sorted ? "sorted" : ""}"${column.sortKey ? ` data-auction-sort="${column.sortKey}"` : ""}>${column.label}${arrow}</th>`;
  }).join("");
  const body = document.querySelector("#auctionTableBody");
  body.innerHTML = rows.map((row) => `<tr data-code="${escapeHtml(row.code)}">${columns.map((column) => renderAuctionCell(row, column.key)).join("")}</tr>`).join("");
  bindStockRows(body);
  const datasetCopy = {
    focus: ["重点异动", "优先查看市场核心与显著预期差"],
    onePrice: ["竞价一字", "竞价封于当日真实涨停价，不参与普通异动评分"],
    watchlist: ["我的自选", "仅展示当前账号关注标的的竞价反馈"],
    all: ["全部候选", "昨日涨停、炸板与热榜前20候选"],
  }[state.auctionDataset] || ["竞价异动", ""];
  setText("auctionWorkspaceTitle", datasetCopy[0]);
  setText("auctionWorkspaceSubtitle", datasetCopy[1]);
  document.querySelector("#auctionExpectationControls").hidden = state.auctionDataset === "onePrice";
  const empty = document.querySelector("#auctionEmpty");
  const phase = state.auctionData?.meta?.phase || "archive";
  empty.textContent = phase === "selection" && !state.auctionData?.meta?.available
    ? "正在等待 9:25 最终竞价数据"
    : state.auctionDataset === "watchlist"
      ? "当前账号还没有可观察的自选股"
      : state.auctionDataset === "onePrice"
        ? "当前没有竞价封于涨停价的股票"
        : "没有符合条件的竞价候选";
  empty.hidden = rows.length > 0;
}

function currentAuctionRows() {
  const datasets = {
    focus: state.auctionData?.focus_rows || [],
    onePrice: state.auctionData?.one_price_rows || [],
    watchlist: state.auctionData?.watchlist_rows || [],
    all: state.auctionData?.rows || [],
  };
  let rows = [...(datasets[state.auctionDataset] || [])];
  const filter = state.auctionFilter;
  const labels = { above: "超预期", matched: "符合预期", below: "低于预期" };
  if (labels[filter]) rows = rows.filter((item) => item.expectation === labels[filter]);
  if (state.auctionQuery) {
    rows = rows.filter((item) => `${item.code} ${item.name} ${item.sector}`.toLocaleLowerCase("zh-CN").includes(state.auctionQuery));
  }
  const key = state.auctionSortKey;
  const direction = state.auctionSortDirection === "asc" ? 1 : -1;
  if (key) {
    rows.sort((left, right) => {
      const leftValue = left[key];
      const rightValue = right[key];
      if (leftValue == null && rightValue == null) return 0;
      if (leftValue == null) return 1;
      if (rightValue == null) return -1;
      const result = typeof leftValue === "number" || typeof rightValue === "number"
        ? number(leftValue) - number(rightValue)
        : String(leftValue).localeCompare(String(rightValue), "zh-CN", { numeric: true });
      return result * direction;
    });
  }
  return rows.slice(0, 300);
}

function auctionColumns() {
  const base = [
    { key: "stock", label: "股票" },
    { key: "context", label: "方向与来源" },
    { key: "identity", label: "市场身份" },
  ];
  const metrics = [
    { key: "score", label: "关注分", numeric: true, sortKey: "attention_score" },
    { key: "expectation", label: "预期判断" },
    { key: "change", label: "竞价涨幅（%）", numeric: true, sortKey: "change" },
    { key: "amount", label: "竞价额（百万）", numeric: true, sortKey: "amount_million" },
    { key: "volume", label: "量比", numeric: true, sortKey: "volume_ratio" },
  ];
  return state.auctionDataset === "onePrice" ? [...base, ...metrics.slice(2)] : [...base, ...metrics];
}

function renderAuctionCell(row, key) {
  const unavailable = row.available === false;
  const onePrice = Boolean(row.is_one_price);
  const expectationTone = { "超预期": "above", "符合预期": "matched", "低于预期": "below" };
  if (key === "stock") return `<td><span class="auction-stock-cell-v2"><strong class="sname">${escapeHtml(row.name)}</strong><small class="stock-code scode">${escapeHtml(row.code)}</small></span></td>`;
  if (key === "context") return `<td><span class="auction-context-cell-v2"><strong>${escapeHtml(row.sector || "其他")}</strong>${renderAuctionSources(row.source_label || (state.auctionDataset === "watchlist" ? "我的自选" : "全市场"))}</span></td>`;
  if (key === "identity") return `<td>${renderAuctionCoreTags(row.core_tags)}</td>`;
  if (unavailable) return key === "expectation"
    ? '<td><span class="table-muted">暂无竞价</span></td>'
    : `<td class="${["score", "change", "amount", "volume"].includes(key) ? "number num" : ""}"></td>`;
  if (key === "score") return `<td class="number num auction-score">${onePrice ? "" : formatNumber(row.attention_score, 1)}</td>`;
  if (key === "expectation") {
    const tag = onePrice
      ? '<span class="auction-one-price-tag">竞价一字</span>'
      : `<span class="auction-expectation ${expectationTone[row.expectation] || "matched"}">${escapeHtml(row.expectation || "符合预期")}</span>`;
    return `<td>${tag}</td>`;
  }
  if (key === "change") return `<td class="number num ${changeClass(row.change)}">${signed(row.change)}</td>`;
  if (key === "amount") return `<td class="number num">${formatNumber(row.amount_million, 2)}</td>`;
  if (key === "volume") return `<td class="number num auction-volume-ratio">${formatNumber(row.volume_ratio, 2)}</td>`;
  return "<td></td>";
}

function renderAuctionSources(value) {
  const sources = String(value || "").split(/[·、/]/).map((item) => item.trim()).filter(Boolean).slice(0, 3);
  return `<small class="auction-source-tags-v2">${sources.map((source) => `<b>${escapeHtml(source)}</b>`).join("")}</small>`;
}

function renderAuctionCoreTags(tags) {
  const values = Array.isArray(tags) ? tags : [];
  return values.length
    ? `<span class="auction-core-tags">${values.slice(0, 2).map((tag) => `<b>${escapeHtml(tag)}</b>`).join("")}</span>`
    : '<span class="auction-identity-empty" aria-label="无市场身份"></span>';
}

function exportAuctionRows() {
  const rows = currentAuctionRows();
  exportRows("集合竞价", rows, [
    ["股票代码", "code"], ["股票名称", "name"], ["行业", "sector"], ["来源", "source_label"],
    ["市场身份", "core_tags"], ["关注分", "attention_score"], ["预期判断", "expectation"],
    ["竞价涨幅%", "change"], ["竞价额百万", "amount_million"], ["量比", "volume_ratio"],
  ]);
}

/* PRESERVATION-SOURCE-END app.js:2217-2481 */
