function meaningfulNumber(value) {
  return value !== null && value !== undefined && value !== "" && Number.isFinite(Number(value));
}
async function openStock(code, fallback = null) {
  closeStockPreview();
  const pools = [state.dashboard?.limits || [], state.dashboard?.broken || [], state.dashboard?.down_limits || []];
  const row = pools.flat().find((item) => String(item.code) === String(code)) || fallback || { code, name: "--", sector: "其他" };
  state.activeStock = row;
  state.stockDetail = null;
  state.stockDetailIntraday = null;
  state.stockDetailChartMode = "daily";
  const requestSequence = ++state.stockDetailRequestSequence;
  syncDetailChartButtons("stock", "daily");
  setText("detailCode", row.code);
  setText("detailName", row.name);
  setText("detailPrice", formatNumber(row.price, 2));
  setText("detailChange", `${signed(row.change)}%`);
  const changeElement = document.querySelector("#detailChange");
  changeElement.className = changeClass(row.change);
  setText("detailStreak", row.status === "涨停" ? streakLabel(row.streak) : row.status || "--");
  setText("detailReason", row.reason || "--");
  setText("detailSector", row.sector || "其他");
  setText("detailFirst", row.first_time || "--");
  setText("detailLast", row.last_time || "--");
  setText("detailOpen", `${number(row.open_times)} 次`);
  setText("detailTurnover", `${formatNumber(row.turnover_rate, 2)}%`);
  setText("detailAmount", `${formatNumber(row.amount_billion, 2)} 亿`);
  setText("detailSeal", `${formatNumber(row.seal_amount_million, 0)} 万`);
  setText("chartSource", "正在加载行情");
  setText("flowNet", "--");
  setText("flowLarge", "--");
  setText("flowMedium", "--");
  setText("flowSmall", "--");
  document.querySelector("#reasonInput").value = row.reason || "";
  document.querySelector("#stockNoteContent").value = "";
  document.querySelector("#stockNotePlan").value = "";
  renderEmptyState("stockNotes", "正在加载笔记");
  updateWatchButton();
  openModalDialog(elements.stockDialog);
  clearPriceChart("正在加载日 K 数据");
  try {
    const query = new URLSearchParams({ trade_date: elements.tradeDate.value });
    const payload = await apiRequest(`/api/stock/${encodeURIComponent(code)}?${query}`);
    if (requestSequence !== state.stockDetailRequestSequence) return;
    state.stockDetail = payload;
    const stock = payload.stock || {};
    state.activeStock = { ...row, name: stock.name || row.name, sector: stock.industry || row.sector };
    setText("detailName", stock.name || row.name);
    setText("detailPrice", formatNumber(stock.price || row.price, 2));
    setText("detailChange", `${signed(stock.change ?? row.change)}%`);
    renderMoneyflow(payload.moneyflow || {});
    renderStockNotes(payload.notes || []);
    updateWatchButton();
    if (state.stockDetailChartMode === "daily") {
      setText("chartSource", `日 K 行情 · ${payload.prices.length} 个交易日`);
      requestAnimationFrame(() => drawPriceChart(payload.prices || []));
    }
  } catch (error) {
    if (requestSequence !== state.stockDetailRequestSequence) return;
    setText("chartSource", "行情加载失败");
    if (state.stockDetailChartMode === "daily") clearPriceChart(error.message || "行情加载失败");
    showToast(error.message || "个股详情加载失败");
  }
}

async function selectStockDetailChart(mode) {
  const selected = mode === "intraday" ? "intraday" : "daily";
  state.stockDetailChartMode = selected;
  syncDetailChartButtons("stock", selected);
  if (selected === "daily") {
    const prices = state.stockDetail?.prices || [];
    setText("chartSource", prices.length ? `日 K 行情 · ${prices.length} 个交易日` : "正在加载行情");
    if (prices.length) requestAnimationFrame(() => drawPriceChart(prices));
    else clearPriceChart("正在加载日 K 数据");
    return;
  }

  if (state.stockDetailIntraday) {
    renderStockDetailIntraday(state.stockDetailIntraday);
    return;
  }
  const code = String(state.activeStock?.code || "");
  if (!/^\d{6}$/.test(code)) return;
  const requestSequence = state.stockDetailRequestSequence;
  setText("chartSource", "正在加载分时");
  clearPriceChart("正在加载分时数据");
  try {
    const params = new URLSearchParams({ type: "stock", id: code });
    const payload = await apiRequest(`/api/chart/intraday?${params}`);
    if (requestSequence !== state.stockDetailRequestSequence) return;
    state.stockDetailIntraday = payload;
    if (state.stockDetailChartMode === "intraday") renderStockDetailIntraday(payload);
  } catch (error) {
    if (requestSequence !== state.stockDetailRequestSequence || state.stockDetailChartMode !== "intraday") return;
    setText("chartSource", "分时暂不可用");
    clearPriceChart(error.message || "分时行情暂不可用");
  }
}

function renderStockDetailIntraday(payload) {
  const points = payload.points || [];
  if (!points.length) {
    setText("chartSource", "分时暂不可用");
    clearPriceChart("分时行情暂不可用");
    return;
  }
  setText("chartSource", `分时 · ${payload.meta?.trade_date || "--"}`);
  requestAnimationFrame(() => {
    if (state.stockDetailChartMode !== "intraday") return;
    drawIntradayCanvas(elements.priceChart, points, [], payload.meta?.previous_close);
  });
}

function openActiveStockInHeaven() {
  const code = state.activeStock?.code;
  if (!/^\d{6}$/.test(String(code || ""))) return;
  elements.stockDialog.close();
  state.heavenPanel = "trend";
  state.heavenManualData = null;
  const input = document.querySelector("#heavenStockInput");
  input.value = code;
  openView("heavenView");
  selectHeavenPanel("trend", true);
}
