"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import { fetchAPI, postAPI } from "@/lib/api";
import type {
  DayGroup,
  LatestResult,
  OpsStatusResponse,
  PerformanceStats,
  RecommendationData,
  TrackedRecommendation,
} from "@/lib/api";
import StockCard from "@/components/stock-card";
import { useAuth } from "@/hooks/use-auth";

function formatDate(dateStr: string): string {
  const d = new Date(dateStr);
  const today = new Date();
  const yesterday = new Date(today);
  yesterday.setDate(yesterday.getDate() - 1);

  if (dateStr === today.toISOString().slice(0, 10)) return "今日";
  if (dateStr === yesterday.toISOString().slice(0, 10)) return "昨日";

  const weekDays = ["周日", "周一", "周二", "周三", "周四", "周五", "周六"];
  return `${d.getMonth() + 1}月${d.getDate()}日 ${weekDays[d.getDay()]}`;
}

function formatScanTime(value?: string): string {
  if (!value) return "暂无扫描";
  const normalized = value.includes("T") ? value : value.replace(" ", "T");
  const d = new Date(normalized);
  if (Number.isNaN(d.getTime())) return value;
  const today = new Date();
  const isToday = d.toDateString() === today.toDateString();
  const time = d.toLocaleTimeString("zh-CN", { hour: "2-digit", minute: "2-digit" });
  if (isToday) return `今日 ${time}`;
  return d.toLocaleString("zh-CN", { month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" });
}

type RecommendationWithDate = RecommendationData & { groupDate: string };

type FocusTab = "actionable" | "watch" | "observe" | "tracking" | "closed";

const SIGNAL_FILTERS = [
  { key: "all", label: "全部" },
  { key: "breakout", label: "突破" },
  { key: "pullback", label: "回踩" },
  { key: "launch", label: "启动" },
  { key: "buy", label: "买入" },
];

export default function RecommendationsPage() {
  const { user } = useAuth();
  const [dayGroups, setDayGroups] = useState<DayGroup[]>([]);
  const [latest, setLatest] = useState<LatestResult | null>(null);
  const [expandedDays, setExpandedDays] = useState<Set<string>>(new Set());
  const [historyFilter, setHistoryFilter] = useState<string>("all");
  const [focusTab, setFocusTab] = useState<FocusTab>("actionable");
  const [opsStatus, setOpsStatus] = useState<OpsStatusResponse | null>(null);
  const [performance, setPerformance] = useState<PerformanceStats | null>(null);
  const [trackingUpdating, setTrackingUpdating] = useState(false);

  const loadData = useCallback(async () => {
    try {
      const [history, latestResult, ops, perf] = await Promise.all([
        fetchAPI<DayGroup[]>("/api/recommendations/history?days=14"),
        fetchAPI<LatestResult>("/api/recommendations/latest").catch(() => null),
        user?.role === "admin" ? fetchAPI<OpsStatusResponse>("/api/market/ops-status").catch(() => null) : Promise.resolve(null),
        fetchAPI<PerformanceStats>("/api/recommendations/performance").catch(() => null),
      ]);

      setDayGroups(history);
      setLatest(latestResult);
      setOpsStatus(ops);
      setPerformance(perf);

      setExpandedDays((prev) => {
        if (prev.size || history.length === 0) return prev;
        return new Set([history[0].date]);
      });
    } catch (error) {
      console.error("加载推荐失败:", error);
    }
  }, [user?.role]);

  useEffect(() => {
    loadData();
  }, [loadData]);

  const updateTracking = async () => {
    setTrackingUpdating(true);
    try {
      await postAPI("/api/recommendations/update-tracking");
      await loadData();
    } finally {
      setTrackingUpdating(false);
    }
  };

  const toggleDay = (date: string) => {
    setExpandedDays((prev) => {
      const next = new Set(prev);
      if (next.has(date)) next.delete(date);
      else next.add(date);
      return next;
    });
  };

  const applyHistoryFilter = useCallback((recs: RecommendationData[]) => {
    if (historyFilter === "all") return recs;
    if (historyFilter === "buy") return recs.filter((r) => r.signal === "BUY");
    return recs.filter((r) => r.entry_signal_type === historyFilter);
  }, [historyFilter]);

  const allRecommendations: RecommendationWithDate[] = useMemo(
    () => dayGroups.flatMap((group) => group.recommendations.map((rec) => ({ ...rec, groupDate: group.date }))),
    [dayGroups]
  );

  const latestDate = dayGroups[0]?.date ?? "";
  const latestRecommendations = useMemo(() => {
    if (latest?.recommendations?.length) return latest.recommendations.map((rec) => ({ ...rec, groupDate: latestDate || "latest" }));
    return latestDate ? allRecommendations.filter((rec) => rec.groupDate === latestDate) : [];
  }, [allRecommendations, latest, latestDate]);

  const actionable = latestRecommendations.filter((rec) => rec.action_plan === "可操作" || rec.lifecycle_status === "actionable");
  const watch = latestRecommendations.filter((rec) => rec.action_plan === "重点关注");
  const observe = latestRecommendations.filter((rec) => (rec.action_plan ?? "观察") === "观察");
  const tracking = allRecommendations.filter((rec) => rec.lifecycle_status === "tracking");
  const closed = allRecommendations.filter((rec) => ["closed_win", "closed_loss", "expired", "invalidated"].includes(rec.lifecycle_status ?? ""));

  const focusTabs: Array<{ key: FocusTab; label: string; count: number; description: string }> = [
    { key: "actionable", label: "可操作", count: actionable.length, description: "执行名单" },
    { key: "watch", label: "重点关注", count: watch.length, description: "等待确认" },
    { key: "observe", label: "观察池", count: observe.length, description: "不急处理" },
    { key: "tracking", label: "跟踪中", count: tracking.length, description: "兑现进度" },
    { key: "closed", label: "已结束", count: closed.length, description: "复盘样本" },
  ];

  const focusItems = useMemo(() => {
    if (focusTab === "actionable") return actionable;
    if (focusTab === "watch") return watch;
    if (focusTab === "observe") return observe.slice(0, 12);
    if (focusTab === "tracking") return tracking.slice(0, 8);
    return closed.slice(0, 8);
  }, [actionable, closed, focusTab, observe, tracking, watch]);

  const themeFocus = useMemo(() => {
    const source = latestRecommendations.filter((rec) => ["可操作", "重点关注"].includes(rec.action_plan ?? ""));
    const pool = source.length ? source : latestRecommendations;
    const counts = new Map<string, number>();
    pool.forEach((rec) => {
      const key = rec.sector || "未归类";
      counts.set(key, (counts.get(key) ?? 0) + 1);
    });
    return Array.from(counts.entries())
      .sort((a, b) => b[1] - a[1])
      .slice(0, 3);
  }, [latestRecommendations]);

  const todayCount = applyHistoryFilter(dayGroups[0]?.recommendations ?? []).length;
  const totalCount = dayGroups.reduce((sum, group) => sum + applyHistoryFilter(group.recommendations).length, 0);
  const latestScanLabel = latest?.latest_scan?.created_at || dayGroups[0]?.scanned_at;
  const focusSummary = buildFocusSummary({
    strategyProfile: latest?.strategy_profile ?? null,
    actionable,
    watch,
    observe,
    tracking,
    closed,
  });

  return (
    <div className="max-w-7xl mx-auto px-4 md:px-8 pt-6 pb-20 md:pb-10 space-y-5">
      <div className="animate-fade-in-up">
        <h1 className="text-base sm:text-lg font-bold tracking-tight">今日决策池</h1>
      </div>

      <div className="glass-card-static overflow-hidden animate-fade-in-up">
        <div className="grid grid-cols-1 xl:grid-cols-[minmax(0,1fr)_340px]">
          <div className="p-4 md:p-5">
            <div className="text-[10px] uppercase tracking-[0.22em] text-amber-400 font-semibold">今日结论</div>
            <h2 className="mt-2 text-2xl md:text-3xl font-bold tracking-tight text-text-primary">{focusSummary.headline}</h2>
            <p className="mt-2 max-w-3xl text-sm leading-6 text-text-secondary">{focusSummary.detail}</p>

            {latest?.strategy_profile ? (
              <div className="mt-3 flex flex-wrap gap-2">
                <SummaryChip label="打法" value={latest.strategy_profile.name} />
                <SummaryChip label="立场" value={latest.strategy_profile.market_stance || (latest.strategy_profile.allow_trading ? "谨慎进攻" : "防守观察")} />
                <SummaryChip label="仓位边界" value={`${latest.strategy_profile.max_position_pct ?? 0}%`} />
              </div>
            ) : null}

            {themeFocus.length ? (
              <div className="mt-3 flex flex-wrap gap-2">
                {themeFocus.map(([theme, count]) => (
                  <span
                    key={theme}
                    className="inline-flex items-center gap-2 rounded-xl border border-amber-500/15 bg-amber-500/[0.05] px-3 py-1.5 text-xs text-text-secondary"
                  >
                    <span className="font-medium text-text-primary">{theme}</span>
                    <span className="font-mono tabular-nums text-amber-400">{count}只</span>
                  </span>
                ))}
              </div>
            ) : null}

            <div className="mt-4 grid grid-cols-1 md:grid-cols-2 gap-3">
              <KeyList title="执行原则" items={focusSummary.now} />
              <KeyList title="回避原则" items={focusSummary.later} />
            </div>
          </div>

          <div className="border-t border-border-subtle bg-surface-1/50 p-4 md:p-5 xl:border-l xl:border-t-0">
            <div className="grid grid-cols-2 gap-2">
              <SummaryMetric label="今日保留" value={latestRecommendations.length} tone="text-text-primary" />
              <SummaryMetric label="可操作" value={actionable.length} tone="text-red-400" />
              <SummaryMetric label="重点关注" value={watch.length} tone="text-amber-400" />
              <SummaryMetric label="观察池" value={observe.length} tone="text-text-secondary" />
            </div>
            <div className="mt-3 grid grid-cols-2 gap-2">
              <SummaryFact label="历史记录" value={`${totalCount} 只`} />
              <SummaryFact label="已复盘" value={`${closed.length} 只`} />
              <SummaryFact label="最近扫描" value={formatScanTime(latestScanLabel)} />
              <SummaryFact label="扫描状态" value={latest?.latest_scan?.status || dayGroups[0]?.scan_status || "暂无"} />
            </div>
          </div>
        </div>
      </div>

      {user?.role === "admin" && opsStatus ? (
        <div className="glass-card-static p-3.5 animate-fade-in-up">
          <div className="flex flex-col md:flex-row md:items-center justify-between gap-3">
            <div className="text-xs text-text-secondary">
              {opsStatus.data_freshness.message}
            </div>
            <div className="grid grid-cols-2 md:grid-cols-4 gap-2 text-[11px]">
              <FreshnessCell label="市场" value={opsStatus.data_freshness.market_trade_date || "暂无"} />
              <FreshnessCell label="板块" value={opsStatus.data_freshness.sector_trade_date || "暂无"} />
              <FreshnessCell label="跟踪" value={opsStatus.data_freshness.tracking_trade_date || "暂无"} />
              <FreshnessCell label="状态" value={opsStatus.scan_running ? "扫描中" : "空闲"} />
            </div>
          </div>
        </div>
      ) : null}

      <PerformanceReviewCard
        performance={performance}
        canUpdate={user?.role === "admin"}
        updating={trackingUpdating}
        onUpdate={updateTracking}
      />

      <div className="glass-card-static p-4 md:p-5 animate-fade-in-up">
        <div className="flex flex-col gap-4">
          <div className="flex flex-wrap items-center justify-between gap-3">
            <div>
              <h2 className="text-base font-bold tracking-tight text-text-primary">
                {focusTabs.find((tab) => tab.key === focusTab)?.label ?? "焦点标的"}
              </h2>
              <div className="mt-1 text-xs text-text-muted">
                {focusTabs.find((tab) => tab.key === focusTab)?.description ?? "按当前结论处理"}
              </div>
            </div>
            <div className="flex gap-2 overflow-x-auto pb-1">
            {focusTabs.map((tab) => (
              <button
                key={tab.key}
                onClick={() => setFocusTab(tab.key)}
                className={`shrink-0 rounded-xl border px-3 py-2 text-left transition-all ${
                  focusTab === tab.key
                    ? "border-amber-500/20 bg-amber-500/[0.06]"
                    : "border-border-subtle bg-surface-1 hover:bg-surface-2"
                }`}
              >
                <div className="flex items-center gap-2">
                  <span className="text-xs font-semibold text-text-primary">{tab.label}</span>
                  <span className="font-mono text-xs tabular-nums text-text-muted">{tab.count}</span>
                </div>
              </button>
            ))}
            </div>
          </div>

          {focusItems.length ? (
            <div className="mt-4 grid grid-cols-1 md:grid-cols-2 gap-3">
              {focusItems.map((rec) => (
                <StockCard key={`${focusTab}-${rec.groupDate}-${rec.ts_code}`} rec={rec} compact />
              ))}
            </div>
          ) : (
            <div className="mt-4 rounded-2xl border border-border-subtle bg-surface-1/70 p-8 text-center text-sm text-text-muted">
              当前分组暂无标的。
            </div>
          )}
        </div>
      </div>

      <div className="glass-card-static p-4 md:p-5 animate-fade-in-up">
        <div className="flex flex-col md:flex-row md:items-center justify-between gap-3">
          <div>
            <h2 className="text-sm font-semibold text-text-primary">历史记录</h2>
          </div>
          <div className="flex gap-2 overflow-x-auto pb-1">
            {SIGNAL_FILTERS.map((item) => (
              <button
                key={item.key}
                onClick={() => setHistoryFilter(item.key)}
                className={`rounded-xl border px-3 py-1.5 text-xs whitespace-nowrap transition-all ${
                  historyFilter === item.key
                    ? "border-amber-500/20 bg-amber-500/[0.06] text-amber-400"
                    : "border-border-subtle bg-surface-1 text-text-muted hover:text-text-secondary"
                }`}
              >
                {item.label}
              </button>
            ))}
          </div>
        </div>

        {dayGroups.length === 0 ? (
          <div className="mt-4 rounded-2xl border border-border-subtle bg-surface-1/70 p-8 text-center text-sm text-text-muted">
            暂无推荐记录。
          </div>
        ) : (
          <div className="mt-4 space-y-3">
            {dayGroups.map((group, index) => {
              const filtered = applyHistoryFilter(group.recommendations);

              const isExpanded = expandedDays.has(group.date);
              const isToday = index === 0;
              const reasons = group.elimination_reasons ? Object.entries(group.elimination_reasons).slice(0, 3) : [];

              return (
                <div key={group.date} className="rounded-2xl border border-border-subtle bg-surface-1/40">
                  <button
                    onClick={() => toggleDay(group.date)}
                    className="flex w-full items-center justify-between gap-3 px-4 py-3 text-left"
                  >
                    <div className="min-w-0">
                      <div className="flex items-center gap-2">
                        <span className={`text-sm font-semibold ${isToday ? "text-amber-400" : "text-text-primary"}`}>
                          {formatDate(group.date)}
                        </span>
                        <span className="text-[11px] text-text-muted font-mono tabular-nums">{group.date}</span>
                      </div>
                      <div className="mt-1 text-[11px] text-text-muted">
                        扫描 {formatScanTime(group.scanned_at)} · {filtered.length} 只入选
                        {group.scan_input_count ? ` / 候选 ${group.scan_input_count}` : ""}
                      </div>
                      {group.scan_summary ? (
                        <div className="mt-1 line-clamp-1 text-[11px] text-text-secondary">{group.scan_summary}</div>
                      ) : null}
                    </div>
                    <span className="text-xs text-text-muted">{isExpanded ? "收起" : "展开"}</span>
                  </button>

                  {isExpanded ? (
                    <div className="border-t border-border-subtle px-4 py-4">
                      {filtered.length ? (
                        <div className="grid grid-cols-1 md:grid-cols-2 gap-3">
                          {filtered.map((rec) => (
                            <StockCard key={`${group.date}-${rec.ts_code}`} rec={rec} compact />
                          ))}
                        </div>
                      ) : (
                        <div className="rounded-2xl border border-border-subtle bg-surface-1/60 p-5 text-sm text-text-muted">
                          <div className="font-medium text-text-secondary">
                            {historyFilter === "all" ? "本日扫描无入选标的" : "本日扫描存在，但当前筛选条件下无标的"}
                          </div>
                          <div className="mt-2 text-xs leading-5">
                            {group.scan_summary || "系统已完成扫描，但没有标的进入历史推荐池。"}
                          </div>
                          {reasons.length ? (
                            <div className="mt-3 flex flex-wrap gap-1.5">
                              {reasons.map(([reason, count]) => (
                                <span key={reason} className="rounded-lg bg-surface-2/70 px-2 py-1 text-[10px] text-text-muted">
                                  {reason} {count}
                                </span>
                              ))}
                            </div>
                          ) : null}
                        </div>
                      )}
                    </div>
                  ) : null}
                </div>
              );
            })}
          </div>
        )}
      </div>
    </div>
  );
}

function buildFocusSummary({
  strategyProfile,
  actionable,
  watch,
  observe,
  tracking,
  closed,
}: {
  strategyProfile: LatestResult["strategy_profile"];
  actionable: RecommendationData[];
  watch: RecommendationData[];
  observe: RecommendationData[];
  tracking: RecommendationData[];
  closed: RecommendationData[];
}) {
  const allowTrading = strategyProfile?.allow_trading ?? actionable.length > 0;
  const headline =
    !allowTrading
      ? "防守观察"
      : actionable.length > 0
        ? `处理 ${actionable.length} 只可操作标的`
        : watch.length > 0
          ? `关注 ${watch.length} 只确认信号`
          : "暂无优势机会";

  const detail =
    strategyProfile?.decision_note
      ?? (!allowTrading
        ? "防守观察，等待确认。"
        : actionable.length > 0
          ? "执行名单已收敛。"
          : watch.length > 0
            ? "等待确认，不扩池。"
            : "观察为主。");

  const now = [
    !allowTrading
      ? "等待主线扩散和回流。"
      : actionable[0]
      ? `看 ${actionable[0].name}${actionable[0].trigger_condition ? `：${actionable[0].trigger_condition}` : " 的确认信号"}。`
      : watch[0]
        ? `盯住 ${watch[0].name} 是否从观察转成可操作。`
        : "只留主线候选。",
    watch.length > 0
      ? `${watch.length} 只重点关注，等待确认。`
      : allowTrading
        ? "不从观察池强挑。"
        : "确认前不提级。",
    tracking.length > 0
      ? `${tracking.length} 只跟踪兑现。`
      : "关注今日新结论。",
  ];

  const later = [
    observe.length > 0 ? `${observe.length} 只观察池标的。` : "不堆弱标的。",
    closed.length > 0 ? `${closed.length} 只已结束样本。` : "暂无结束样本。",
    "不追无触发标的。",
  ];

  return { headline, detail, now, later };
}

function PerformanceReviewCard({
  performance,
  canUpdate,
  updating,
  onUpdate,
}: {
  performance: PerformanceStats | null;
  canUpdate: boolean;
  updating: boolean;
  onUpdate: () => void;
}) {
  const details = performance?.details ?? [];
  const topRoutes = (performance?.route_breakdown ?? []).slice(0, 4);
  const conclusion = buildPerformanceConclusion(performance);

  return (
    <div className="glass-card-static p-4 md:p-5 animate-fade-in-up">
      <div className="flex flex-col gap-3 md:flex-row md:items-start md:justify-between">
        <div>
          <div className="text-[10px] uppercase tracking-[0.22em] text-amber-400 font-semibold">推荐复盘</div>
          <h2 className="mt-2 text-base font-bold tracking-tight text-text-primary">{conclusion.headline}</h2>
          <p className="mt-1 max-w-3xl text-sm leading-6 text-text-secondary">{conclusion.detail}</p>
        </div>
        {canUpdate ? (
          <button
            onClick={onUpdate}
            disabled={updating}
            className="shrink-0 rounded-xl border border-amber-500/20 bg-amber-500/[0.06] px-3 py-2 text-xs font-semibold text-amber-400 transition-colors hover:bg-amber-500/[0.1] disabled:cursor-not-allowed disabled:opacity-50"
          >
            {updating ? "更新中" : "更新跟踪"}
          </button>
        ) : null}
      </div>

      <div className="mt-4 grid grid-cols-2 lg:grid-cols-5 gap-2">
        <SummaryMetric label="已跟踪" value={performance?.tracked ?? 0} tone="text-text-primary" />
        <SummaryMetric label="胜率" value={performance?.win_rate ?? 0} tone="text-amber-400" suffix="%" />
        <SummaryMetric
          label="平均收益"
          value={performance?.avg_return ?? 0}
          tone={(performance?.avg_return ?? 0) >= 0 ? "text-red-400" : "text-emerald-400"}
          suffix="%"
          signed
        />
        <SummaryMetric label="平均浮盈" value={performance?.avg_max_return ?? 0} tone="text-red-400" suffix="%" signed />
        <SummaryMetric label="平均回撤" value={performance?.avg_max_drawdown ?? 0} tone="text-amber-400" suffix="%" />
      </div>

      <div className="mt-4 grid grid-cols-1 xl:grid-cols-[320px_minmax(0,1fr)] gap-3">
        <div className="rounded-2xl border border-border-subtle bg-surface-1/60 p-3">
          <div className="text-[11px] font-semibold text-text-secondary">有效路线</div>
          <div className="mt-3 space-y-2">
            {topRoutes.length ? topRoutes.map((route) => (
              <div key={route.route} className="flex items-center justify-between gap-3 rounded-xl bg-surface-2/70 px-3 py-2">
                <div className="min-w-0">
                  <div className="truncate text-xs font-medium text-text-primary">{formatRouteLabel(route.route)}</div>
                  <div className="mt-0.5 text-[11px] text-text-muted">{route.count} 个样本</div>
                </div>
                <div className="text-right font-mono text-xs tabular-nums">
                  <div className="text-amber-400">{route.win_rate}%</div>
                  <div className={route.avg_return >= 0 ? "text-red-400" : "text-emerald-400"}>
                    {route.avg_return > 0 ? "+" : ""}{route.avg_return}%
                  </div>
                </div>
              </div>
            )) : (
              <div className="rounded-xl bg-surface-2/70 px-3 py-6 text-center text-xs text-text-muted">暂无路线样本。</div>
            )}
          </div>
        </div>

        <div className="rounded-2xl border border-border-subtle bg-surface-1/60 p-3">
          <div className="flex items-center justify-between gap-3">
            <div className="text-[11px] font-semibold text-text-secondary">最近复盘样本</div>
            <div className="text-[11px] text-text-muted">按推荐时间倒序</div>
          </div>
          <div className="mt-3 overflow-x-auto">
            {details.length ? (
              <table className="w-full min-w-[620px] border-separate border-spacing-y-2 text-left text-xs">
                <thead className="text-[10px] uppercase tracking-wider text-text-muted">
                  <tr>
                    <th className="px-3 py-2 font-medium">标的</th>
                    <th className="px-3 py-2 font-medium">推荐日</th>
                    <th className="px-3 py-2 font-medium">现价/入场</th>
                    <th className="px-3 py-2 font-medium">涨跌</th>
                    <th className="px-3 py-2 font-medium">过程</th>
                    <th className="px-3 py-2 font-medium">结论</th>
                  </tr>
                </thead>
                <tbody>
                  {details.slice(0, 8).map((item) => (
                    <ReviewRow key={`${item.ts_code}-${item.created_at}-${item.track_date}`} item={item} />
                  ))}
                </tbody>
              </table>
            ) : (
              <div className="rounded-xl bg-surface-2/70 px-3 py-8 text-center text-sm text-text-muted">
                暂无跟踪记录。先执行一次跟踪更新后再看复盘。
              </div>
            )}
          </div>
        </div>
      </div>
    </div>
  );
}

function ReviewRow({ item }: { item: TrackedRecommendation }) {
  const pct = item.pct_from_entry ?? 0;
  const pctTone = pct >= 0 ? "text-red-400" : "text-emerald-400";
  const cellClass = "bg-surface-2/30 px-3 py-3 transition-colors group-hover:bg-surface-2/55";
  return (
    <tr className="group">
      <td className={`${cellClass} rounded-l-xl`}>
        <div className="font-medium text-text-primary">{item.name}</div>
        <div className="mt-0.5 font-mono text-[11px] text-text-muted">{item.ts_code}</div>
      </td>
      <td className={`${cellClass} font-mono text-text-muted`}>{item.created_at || "-"}</td>
      <td className={`${cellClass} font-mono tabular-nums text-text-secondary`}>
        {formatNumber(item.current_price)} / {formatNumber(item.entry_price)}
      </td>
      <td className={`${cellClass} font-mono tabular-nums ${pctTone}`}>{pct > 0 ? "+" : ""}{pct}%</td>
      <td className={`${cellClass} font-mono tabular-nums text-text-secondary`}>
        <span className="text-red-400">{formatSigned(item.max_return_pct)}</span>
        <span className="mx-1 text-text-muted">/</span>
        <span className="text-amber-400">{formatSigned(item.max_drawdown_pct)}</span>
      </td>
      <td className={`${cellClass} rounded-r-xl text-text-secondary`}>{item.review_note || formatCloseReason(item.close_reason)}</td>
    </tr>
  );
}

function buildPerformanceConclusion(performance: PerformanceStats | null) {
  if (!performance || performance.tracked === 0) {
    return {
      headline: "等待形成有效复盘样本",
      detail: "当前还没有可统计的推荐跟踪记录。更新跟踪后，会按推荐后的价格表现判断是否兑现预期。",
    };
  }

  const avg = performance.avg_return ?? 0;
  const direction = avg > 0 ? "整体兑现为正" : avg < 0 ? "整体仍在回撤" : "整体接近持平";
  return {
    headline: `${performance.tracked} 个样本，胜率 ${performance.win_rate}%`,
    detail: `${direction}，平均收益 ${avg > 0 ? "+" : ""}${avg.toFixed(2)}%，平均最大浮盈 ${performance.avg_max_return.toFixed(2)}%，平均最大回撤 ${performance.avg_max_drawdown.toFixed(2)}%。`,
  };
}

function formatRouteLabel(route: string) {
  const labels: Record<string, string> = {
    hot_theme_core: "主线核心",
    theme_leader: "板块龙头",
    top_theme_member: "强主题成员",
    sector_recall: "板块召回",
  };
  return labels[route] ?? route;
}

function formatCloseReason(reason?: string) {
  const labels: Record<string, string> = {
    hit_target: "命中目标",
    hit_stop_loss: "触发止损",
    review_expired_profit: "到期盈利",
    review_expired_loss: "到期亏损",
    review_expired_flat: "到期震荡",
  };
  return labels[reason ?? ""] ?? "跟踪中";
}

function formatNumber(value: number | null | undefined) {
  return value == null ? "-" : Number(value).toFixed(2);
}

function formatSigned(value: number | null | undefined) {
  if (value == null) return "-";
  return `${value > 0 ? "+" : ""}${Number(value).toFixed(2)}%`;
}

function KeyList({ title, items }: { title: string; items: string[] }) {
  return (
    <div className="rounded-2xl border border-border-subtle bg-surface-1/70 p-3">
      <div className="text-[11px] font-semibold text-text-secondary">{title}</div>
      <div className="mt-2 space-y-2">
        {items.map((item, index) => (
          <div key={`${title}-${index}`} className="flex items-start gap-2 text-sm leading-6 text-text-secondary">
            <span className="mt-2 h-1.5 w-1.5 shrink-0 rounded-full bg-amber-400" />
            <span>{item}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

function SummaryMetric({
  label,
  value,
  tone,
  suffix,
  signed,
}: {
  label: string;
  value: number;
  tone: string;
  suffix?: string;
  signed?: boolean;
}) {
  return (
    <div className="rounded-2xl border border-border-subtle bg-surface-1/70 px-3 py-3">
      <div className="text-[10px] uppercase tracking-wider text-text-muted">{label}</div>
      <div className={`mt-1 text-lg font-bold font-mono tabular-nums ${tone}`}>
        {signed && value > 0 ? "+" : ""}
        {value}
        {suffix ?? ""}
      </div>
    </div>
  );
}

function SummaryFact({ label, value }: { label: string; value: string }) {
  return (
    <div className="rounded-2xl border border-border-subtle bg-surface-1/70 px-3 py-3">
      <div className="text-[10px] uppercase tracking-wider text-text-muted">{label}</div>
      <div className="mt-1 text-xs font-semibold leading-5 text-text-secondary">{value}</div>
    </div>
  );
}

function FreshnessCell({ label, value }: { label: string; value: string }) {
  return (
    <div className="rounded-xl bg-surface-1/70 px-3 py-2">
      <div className="text-[10px] text-text-muted">{label}</div>
      <div className="mt-1 text-xs font-mono tabular-nums text-text-secondary">{value}</div>
    </div>
  );
}

function SummaryChip({ label, value }: { label: string; value: string }) {
  return (
    <span className="inline-flex items-center gap-2 rounded-xl border border-border-subtle bg-surface-1/70 px-3 py-1.5 text-xs text-text-secondary">
      <span className="text-text-muted">{label}</span>
      <span className="font-medium text-text-primary">{value}</span>
    </span>
  );
}
