import { useEffect, useMemo, useState } from "react";
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
import { api, type TradeAccount, type TradeRecord, type TradeStatsPayload } from "../lib/api";
import { syncPlayerProgress } from "../lib/learningSync";
import { Card, Loading, ErrorState, Tag } from "../components/ui";
import { AppIcon } from "../components/PixelIcons";
import { PrinciplePicker, principleLabel } from "../components/journal/PrinciplePicker";
import { JournalDashboard } from "../components/journal/JournalDashboard";
import {
  AccountSettingsModal,
  EMPTY_ACCOUNT_FORM,
  accountFormFromRecord,
  accountPayloadFromForm,
  type AccountForm,
} from "../components/journal/AccountSettingsModal";
import { aiApi } from "../lib/ai";

const ACCOUNT_STORAGE_KEY = "journal-account-id";

type TradeForm = {
  symbol: string;
  name: string;
  direction: "long" | "short";
  kind: string;
  entry_date: string;
  entry_price: string;
  shares: string;
  exit_date: string;
  exit_price: string;
  entry_reason: string;
  exit_reason: string;
  principle: string;
  mistake: boolean;
  mistake_note: string;
  note: string;
};

const EMPTY_FORM: TradeForm = {
  symbol: "",
  name: "",
  direction: "long",
  kind: "交易",
  entry_date: new Date().toISOString().slice(0, 10),
  entry_price: "",
  shares: "",
  exit_date: "",
  exit_price: "",
  entry_reason: "",
  exit_reason: "",
  principle: "",
  mistake: false,
  mistake_note: "",
  note: "",
};

function fmtPct(v: number | null | undefined) {
  if (v == null || Number.isNaN(v)) return "—";
  return `${v > 0 ? "+" : ""}${v.toFixed(1)}%`;
}

function fmtMoney(v: number | null | undefined) {
  if (v == null || Number.isNaN(v)) return "—";
  const sign = v > 0 ? "+" : v < 0 ? "-" : "";
  return `${sign}$${Math.abs(v).toLocaleString(undefined, { maximumFractionDigits: 0 })}`;
}

function tradeActionLabel(t: TradeRecord) {
  if (!t.closed) return t.direction === "short" ? "放空" : "建倉";
  return t.direction === "short" ? "回補" : "平倉";
}

function actionTone(t: TradeRecord): "up" | "down" | "cool" {
  if (!t.closed) return "cool";
  if (t.direction === "short") return "down";
  return "up";
}

function formFromTrade(t: TradeRecord): TradeForm {
  return {
    symbol: t.symbol || "",
    name: t.name || "",
    direction: t.direction === "short" ? "short" : "long",
    kind: t.kind || "交易",
    entry_date: t.entry_date || "",
    entry_price: t.entry_price != null ? String(t.entry_price) : "",
    shares: t.shares != null ? String(t.shares) : "",
    exit_date: t.exit_date || "",
    exit_price: t.exit_price != null ? String(t.exit_price) : "",
    entry_reason: t.entry_reason || "",
    exit_reason: t.exit_reason || "",
    principle: t.principle || "",
    mistake: !!t.mistake,
    mistake_note: t.mistake_note || "",
    note: t.note || "",
  };
}

function payloadFromForm(form: TradeForm) {
  const num = (s: string) => (s.trim() === "" ? null : Number(s));
  return {
    symbol: form.symbol.trim().toUpperCase(),
    name: form.name.trim() || null,
    direction: form.direction,
    kind: form.kind.trim() || null,
    entry_date: form.entry_date || null,
    entry_price: num(form.entry_price),
    shares: num(form.shares),
    exit_date: form.exit_date || null,
    exit_price: num(form.exit_price),
    entry_reason: form.entry_reason.trim() || null,
    exit_reason: form.exit_reason.trim() || null,
    principle: form.principle.trim() || null,
    mistake: form.mistake,
    mistake_note: form.mistake_note.trim() || null,
    note: form.note.trim() || null,
  };
}

function avgReturnPct(trades: TradeRecord[]) {
  const closed = trades.filter((t) => t.closed && t.pnl_pct != null);
  if (!closed.length) return null;
  return closed.reduce((a, t) => a + (t.pnl_pct || 0), 0) / closed.length;
}

function disciplineScore(stats: TradeStatsPayload | undefined) {
  if (!stats?.closed) return null;
  const clean = stats.byMistake.find((x) => x.key === "無犯錯")?.count ?? 0;
  return (clean / stats.closed) * 10;
}

function buildReviewNote(stats: TradeStatsPayload | undefined, trades: TradeRecord[]) {
  if (!stats?.closed) {
    return "還沒有已平倉的戰鬥紀錄。先記下一筆交易，寫清楚進場理由與對應心法，平倉後再回來復盤。";
  }
  const top = stats.byPrinciple[0];
  const mistake = stats.byMistake.find((x) => x.key === "有犯錯");
  const avg = avgReturnPct(trades);
  const parts: string[] = [];
  if (stats.winRate != null) {
    parts.push(`已平倉 ${stats.closed} 筆，勝率 ${stats.winRate.toFixed(0)}%`);
  }
  if (avg != null) parts.push(`平均報酬 ${fmtPct(avg)}`);
  if (top) parts.push(`最常用依據是「${top.key}」（${top.count} 次）`);
  if (mistake?.count) parts.push(`其中 ${mistake.count} 筆標記為犯錯，值得逐筆檢討`);
  else parts.push("目前沒有標記犯錯的紀錄，紀律表現不錯");
  return parts.join("。") + "。";
}

function TradeFormModal({
  open,
  editing,
  form,
  saving,
  onChange,
  onClose,
  onSave,
  onDelete,
}: {
  open: boolean;
  editing: TradeRecord | null;
  form: TradeForm;
  saving: boolean;
  onChange: (patch: Partial<TradeForm>) => void;
  onClose: () => void;
  onSave: () => void;
  onDelete?: () => void;
}) {
  useEffect(() => {
    document.body.classList.toggle("skill-modal-open", open);
    return () => document.body.classList.remove("skill-modal-open");
  }, [open]);

  if (!open) return null;

  return (
    <div className="skill-modal" role="dialog" aria-modal="true" aria-labelledby="trade-form-title">
      <button type="button" className="skill-modal-backdrop" aria-label="關閉" onClick={onClose} />
      <div className="skill-modal-panel journal-form-panel">
        <div className="skill-modal-head">
          <AppIcon name="sword" size={26} framed variant="hero" />
          <strong id="trade-form-title">{editing ? "編輯戰鬥紀錄" : "新增戰鬥紀錄"}</strong>
          <button type="button" className="guide-close" onClick={onClose} aria-label="關閉">
            ×
          </button>
        </div>
        <div className="journal-form-body">
          <div className="grid g2">
            <div className="settings-field">
              <label>標的代號 *</label>
              <input
                value={form.symbol}
                onChange={(e) => onChange({ symbol: e.target.value })}
                placeholder="NVDA / 2330.TW"
              />
            </div>
            <div className="settings-field">
              <label>名稱</label>
              <input value={form.name} onChange={(e) => onChange({ name: e.target.value })} placeholder="輝達" />
            </div>
          </div>
          <div className="grid g3">
            <div className="settings-field">
              <label>方向</label>
              <select value={form.direction} onChange={(e) => onChange({ direction: e.target.value as "long" | "short" })}>
                <option value="long">做多</option>
                <option value="short">放空</option>
              </select>
            </div>
            <div className="settings-field">
              <label>類型</label>
              <select value={form.kind} onChange={(e) => onChange({ kind: e.target.value })}>
                <option value="交易">交易</option>
                <option value="投資">投資</option>
                <option value="減倉">減倉</option>
              </select>
            </div>
            <div className="settings-field">
              <label>進場日</label>
              <input type="date" value={form.entry_date} onChange={(e) => onChange({ entry_date: e.target.value })} />
            </div>
          </div>
          <div className="grid g3">
            <div className="settings-field">
              <label>進場價</label>
              <input
                inputMode="decimal"
                value={form.entry_price}
                onChange={(e) => onChange({ entry_price: e.target.value })}
              />
            </div>
            <div className="settings-field">
              <label>股數</label>
              <input inputMode="decimal" value={form.shares} onChange={(e) => onChange({ shares: e.target.value })} />
            </div>
            <div className="settings-field">
              <label>出場日</label>
              <input type="date" value={form.exit_date} onChange={(e) => onChange({ exit_date: e.target.value })} />
            </div>
          </div>
          <div className="settings-field">
            <label>出場價（留空＝持倉中）</label>
            <input
              inputMode="decimal"
              value={form.exit_price}
              onChange={(e) => onChange({ exit_price: e.target.value })}
            />
          </div>
          <PrinciplePicker value={form.principle} onChange={(principle) => onChange({ principle })} />
          <div className="settings-field">
            <label>進場理由</label>
            <textarea
              className="skill-notes-textarea"
              rows={2}
              value={form.entry_reason}
              onChange={(e) => onChange({ entry_reason: e.target.value })}
            />
          </div>
          <div className="settings-field">
            <label>出場理由</label>
            <textarea
              className="skill-notes-textarea"
              rows={2}
              value={form.exit_reason}
              onChange={(e) => onChange({ exit_reason: e.target.value })}
            />
          </div>
          <label className="journal-mistake-check">
            <input type="checkbox" checked={form.mistake} onChange={(e) => onChange({ mistake: e.target.checked })} />
            這筆有犯錯（紀律、停損、違反心法等）
          </label>
          {form.mistake ? (
            <div className="settings-field">
              <label>犯錯說明</label>
              <textarea
                className="skill-notes-textarea"
                rows={2}
                value={form.mistake_note}
                onChange={(e) => onChange({ mistake_note: e.target.value })}
              />
            </div>
          ) : null}
          <div className="settings-field">
            <label>復盤筆記</label>
            <textarea
              className="skill-notes-textarea"
              rows={3}
              value={form.note}
              onChange={(e) => onChange({ note: e.target.value })}
            />
          </div>
          <div className="settings-actions mt-s">
            {editing && onDelete ? (
              <button type="button" className="btn-ghost danger" disabled={saving} onClick={onDelete}>
                刪除
              </button>
            ) : (
              <span />
            )}
            <div className="journal-form-actions">
              <button type="button" className="btn-ghost" disabled={saving} onClick={onClose}>
                取消
              </button>
              <button type="button" className="btn-primary" disabled={saving || !form.symbol.trim()} onClick={onSave}>
                {saving ? "儲存中…" : "儲存"}
              </button>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

export default function Journal() {
  const qc = useQueryClient();
  const accountsQ = useQuery({ queryKey: ["trade-accounts"], queryFn: async () => (await api.tradeAccounts()).accounts });

  const [accountId, setAccountId] = useState<number | null>(() => {
    const raw = localStorage.getItem(ACCOUNT_STORAGE_KEY);
    const n = raw ? Number(raw) : NaN;
    return Number.isFinite(n) ? n : null;
  });
  const [tab, setTab] = useState<"dashboard" | "trades">("dashboard");
  const [formOpen, setFormOpen] = useState(false);
  const [accountModalOpen, setAccountModalOpen] = useState(false);
  const [accountEditing, setAccountEditing] = useState<TradeAccount | null>(null);
  const [accountForm, setAccountForm] = useState<AccountForm>(EMPTY_ACCOUNT_FORM);
  const [editing, setEditing] = useState<TradeRecord | null>(null);
  const [form, setForm] = useState<TradeForm>(EMPTY_FORM);
  const [aiReviewByAccount, setAiReviewByAccount] = useState<Record<number, string>>({});
  const [simulationResultByAccount, setSimulationResultByAccount] = useState<
    Record<number, { summary?: string; report?: string; review?: string }>
  >({});

  const accounts = accountsQ.data || [];
  const activeAccountId = accountId ?? accounts[0]?.id ?? null;
  const activeAccount = accounts.find((a) => a.id === activeAccountId);

  useEffect(() => {
    if (activeAccountId != null) localStorage.setItem(ACCOUNT_STORAGE_KEY, String(activeAccountId));
  }, [activeAccountId]);

  useEffect(() => {
    if (accountId == null && accounts[0]?.id) setAccountId(accounts[0].id);
  }, [accountId, accounts]);

  const tradesQ = useQuery({
    queryKey: ["trades", activeAccountId],
    queryFn: async () => (await api.trades(activeAccountId ?? undefined)).trades,
    enabled: activeAccountId != null,
  });
  const statsQ = useQuery({
    queryKey: ["trade-stats", activeAccountId],
    queryFn: () => api.tradeStats(activeAccountId ?? undefined),
    enabled: activeAccountId != null,
  });
  const dashQ = useQuery({
    queryKey: ["trade-dashboard", activeAccountId],
    queryFn: () => api.tradeDashboard(activeAccountId ?? undefined),
    enabled: activeAccountId != null,
    refetchInterval: activeAccount?.simulationEnabled || activeAccount?.kind === "ai" ? 60_000 : false,
  });

  const invalidate = () => {
    qc.invalidateQueries({ queryKey: ["trades"] });
    qc.invalidateQueries({ queryKey: ["trade-stats"] });
    qc.invalidateQueries({ queryKey: ["trade-dashboard"] });
    qc.invalidateQueries({ queryKey: ["trade-accounts"] });
    qc.invalidateQueries({ queryKey: ["portfolio-total"] });
    syncPlayerProgress(qc);
  };

  const saveMut = useMutation({
    mutationFn: async () => {
      const payload = { ...payloadFromForm(form), accountId: activeAccountId ?? undefined };
      if (editing) return api.updateTrade(editing.id, payload);
      return api.createTrade(payload);
    },
    onSuccess: () => {
      invalidate();
      setFormOpen(false);
      setEditing(null);
      setForm(EMPTY_FORM);
    },
  });

  const deleteMut = useMutation({
    mutationFn: (id: number) => api.deleteTrade(id),
    onSuccess: () => {
      invalidate();
      setFormOpen(false);
      setEditing(null);
      setForm(EMPTY_FORM);
    },
  });

  const saveAccountMut = useMutation({
    mutationFn: async () => {
      const payload = accountPayloadFromForm(accountForm);
      if (accountEditing) return api.updateTradeAccount(accountEditing.id, payload);
      return api.createTradeAccount(payload);
    },
    onSuccess: (acc) => {
      invalidate();
      setAccountId(acc.id);
      setAccountModalOpen(false);
      setAccountEditing(null);
      setAccountForm(EMPTY_ACCOUNT_FORM);
    },
  });

  const deleteAccountMut = useMutation({
    mutationFn: ({ id, force }: { id: number; force?: boolean }) => api.deleteTradeAccount(id, { force }),
    onSuccess: () => {
      invalidate();
      const remaining = accounts.filter((a) => a.id !== accountEditing?.id);
      setAccountId(remaining[0]?.id ?? null);
      setAccountModalOpen(false);
      setAccountEditing(null);
    },
  });

  const simMut = useMutation({
    mutationFn: ({ accountId, phase }: { accountId: number; phase: string }) =>
      api.runSimulation(accountId, { force: true, phase }),
    onSuccess: (result, { accountId }) => {
      invalidate();
      qc.invalidateQueries({ queryKey: ["simulation-runs", accountId] });
      qc.invalidateQueries({ queryKey: ["trader-brief", accountId] });
      setSimulationResultByAccount((current) => ({ ...current, [accountId]: result }));
    },
  });

  const aiReviewMut = useMutation({
    mutationFn: async (accountId: number) => {
      const status = await aiApi.status();
      if (!status.ready || !status.active) throw new Error("請先在設定頁完成 AI 設定");
      const ctx = await aiApi.context("journal", { view: "journal", cardTitle: "交易復盤" }, { accountId });
      const res = await aiApi.chat({
        provider: status.active,
        question:
          "請依今日市場資料與此帳號的持倉、現金比例、年度損益與交易紀錄，給出：1) 今日盤後復盤 2) 持倉風險與配置建議 3) 紀律與心法執行檢討。條列、具體、繁體中文。",
        context: ctx,
      });
      return res.text;
    },
    onSuccess: (text, accountId) => setAiReviewByAccount((current) => ({ ...current, [accountId]: text })),
  });

  const trades = tradesQ.data || [];
  const stats = statsQ.data;
  const avgPct = useMemo(() => avgReturnPct(trades), [trades]);
  const discipline = useMemo(() => disciplineScore(stats), [stats]);
  const reviewNote = useMemo(() => buildReviewNote(stats, trades), [stats, trades]);
  const activeAiReview = activeAccountId != null ? aiReviewByAccount[activeAccountId] : null;
  const activeSimulationResult = activeAccountId != null ? simulationResultByAccount[activeAccountId] : null;
  const activeSimulationPending = simMut.isPending && simMut.variables?.accountId === activeAccountId;
  const activeAiReviewPending = aiReviewMut.isPending && aiReviewMut.variables === activeAccountId;
  const activeSimulationError = simMut.variables?.accountId === activeAccountId ? simMut.error : null;
  const activeAiReviewError = aiReviewMut.variables === activeAccountId ? aiReviewMut.error : null;

  const openCreate = () => {
    setEditing(null);
    setForm({ ...EMPTY_FORM, entry_date: new Date().toISOString().slice(0, 10) });
    setFormOpen(true);
  };

  const openEdit = (t: TradeRecord) => {
    setEditing(t);
    setForm(formFromTrade(t));
    setFormOpen(true);
  };

  if (accountsQ.isLoading || (activeAccountId != null && tradesQ.isLoading)) return <Loading label="讀取戰績…" />;
  if (accountsQ.error || tradesQ.error || statsQ.error || dashQ.error) {
    return (
      <ErrorState
        detail={String(
          (accountsQ.error || tradesQ.error || statsQ.error || dashQ.error as Error)?.message || "讀取失敗",
        )}
      />
    );
  }

  const dash = dashQ.data;

  const openAccountEdit = () => {
    if (!activeAccount) return;
    setAccountEditing(activeAccount);
    setAccountForm(accountFormFromRecord(activeAccount));
    setAccountModalOpen(true);
  };

  const openAccountCreate = () => {
    setAccountEditing(null);
    setAccountForm({ ...EMPTY_ACCOUNT_FORM, kind: "human" });
    setAccountModalOpen(true);
  };

  return (
    <>
      <div className="page-head">
        <div className="eyebrow">個人 · 復盤</div>
        <h1 className="page-title-row">
          <AppIcon name="folder" size={38} framed glow variant="hero" />
          任務日誌與戰績
        </h1>
        <p>可分帳號記錄（自己操作或未來 AI 策略），儀表板看持股比例、年度損益與總賺賠；心法從知識庫選取。</p>
      </div>

      <div className="journal-page-tabs">
        <button type="button" className={`journal-page-tab${tab === "dashboard" ? " active" : ""}`} onClick={() => setTab("dashboard")}>
          戰績儀表板
        </button>
        <button type="button" className={`journal-page-tab${tab === "trades" ? " active" : ""}`} onClick={() => setTab("trades")}>
          戰鬥紀錄
        </button>
      </div>

      {tab === "dashboard" && dash && activeAccountId != null ? (
        <JournalDashboard
          dash={dash}
          accounts={accounts}
          accountId={activeAccountId}
          onAccountChange={setAccountId}
          onEditAccount={openAccountEdit}
          onAddAccount={openAccountCreate}
          onAiReview={activeAccount?.aiEnabled ? () => aiReviewMut.mutate(activeAccountId) : undefined}
          aiLoading={activeAiReviewPending}
          onSimulatePhase={activeAccount?.kind === "ai" ? (phase) => simMut.mutate({ accountId: activeAccountId, phase }) : undefined}
          simLoading={activeSimulationPending}
        />
      ) : null}

      {activeAiReview ? (
        <Card title="AI 復盤" ico={<AppIcon name="wizard" size={22} framed variant="nav" />} className="mt" ai aiFocus={{ view: "journal", cardTitle: "AI 復盤" }}>
          <div className="editorial" style={{ marginTop: 0, whiteSpace: "pre-wrap" }}>
            {activeAiReview}
          </div>
          <button
            type="button"
            className="btn-ghost sm mt-s"
            onClick={() => setAiReviewByAccount((current) => {
              const next = { ...current };
              if (activeAccountId != null) delete next[activeAccountId];
              return next;
            })}
          >
            關閉
          </button>
        </Card>
      ) : null}

      {tab === "trades" ? (
        <>
      <div className="journal-account-bar compact">
        <div className="journal-account-tabs">
          {accounts.map((a) => (
            <button
              key={a.id}
              type="button"
              className={`journal-account-tab${a.id === activeAccountId ? " active" : ""}`}
              style={{ "--acc-color": a.color || "var(--gold)" } as React.CSSProperties}
              onClick={() => setAccountId(a.id)}
            >
              <span className="journal-account-dot" />
              {a.name}
            </button>
          ))}
        </div>
      </div>

      <div className="grid g4">
        <div className="card kpi">
          <div className="k-v" style={{ color: "var(--emerald)" }}>
            {stats?.winRate != null ? `${stats.winRate.toFixed(0)}%` : "—"}
          </div>
          <div className="k-l">勝率</div>
          <div className="k-d small muted">{stats?.closed ?? 0} 筆已平倉</div>
        </div>
        <div className="card kpi">
          <div className="k-v">{trades.length}</div>
          <div className="k-l">總戰鬥數</div>
          <div className="k-d small muted">{stats?.open ?? 0} 筆持倉中</div>
        </div>
        <div className="card kpi">
          <div
            className="k-v"
            style={{ color: avgPct != null && avgPct >= 0 ? "var(--emerald)" : avgPct != null ? "var(--crimson)" : undefined }}
          >
            {avgPct != null ? fmtPct(avgPct) : "—"}
          </div>
          <div className="k-l">平均報酬</div>
          <div className="k-d small muted">已平倉加權</div>
        </div>
        <div className="card kpi">
          <div className="k-v">{discipline != null ? `⭐ ${discipline.toFixed(1)}` : "—"}</div>
          <div className="k-l">紀律評分</div>
          <div className="k-d small muted">滿分 10</div>
        </div>
      </div>

      <Card
        title="戰鬥紀錄"
        ico={<AppIcon name="sword" size={22} framed variant="nav" />}
        ai
        aiFocus={{ view: "journal", cardTitle: "我的交易復盤" }}
        className="mt"
      >
        <div className="journal-toolbar">
          <button type="button" className="btn-primary sm" onClick={openCreate}>
            ＋ 新增紀錄
          </button>
          {stats?.totalPnl != null && stats.closed > 0 ? (
            <span className="small muted">
              累計損益 {fmtMoney(stats.totalPnl)}
              {stats.payoff != null ? ` · 賺賠比 ${stats.payoff.toFixed(2)}` : ""}
            </span>
          ) : null}
        </div>
        {trades.length === 0 ? (
          <div className="state-box mt-s">
            <p className="muted">還沒有戰鬥紀錄。從個股背包研究完後，把進場理由記下來吧。</p>
            <button type="button" className="btn-primary sm mt-s" onClick={openCreate}>
              記第一筆
            </button>
          </div>
        ) : (
          <div className="journal-table-wrap">
            <table className="tbl">
              <thead>
                <tr>
                  <th>日期</th>
                  <th>標的</th>
                  <th>動作</th>
                  <th>價格</th>
                  <th>進出場理由（心法）</th>
                  <th>結果</th>
                </tr>
              </thead>
              <tbody>
                {trades.map((t) => {
                  const reason = [principleLabel(t.principle || ""), t.entry_reason].filter(Boolean).join(" · ") || "—";
                  const date = t.exit_date || t.entry_date || "—";
                  const price = t.exit_price ?? t.entry_price;
                  const win = t.closed && (t.pnl || 0) > 0;
                  const loss = t.closed && (t.pnl || 0) < 0;
                  return (
                    <tr key={t.id} className="journal-row" onClick={() => openEdit(t)}>
                      <td className="muted small">{date}</td>
                      <td>
                        <strong>{t.symbol}</strong>
                        {t.name ? <span className="small muted"> {t.name}</span> : null}
                      </td>
                      <td>
                        <Tag tone={actionTone(t)}>{tradeActionLabel(t)}</Tag>
                        {t.mistake ? <span className="journal-mistake-flag">⚠</span> : null}
                      </td>
                      <td>{price != null ? price.toLocaleString() : "—"}</td>
                      <td>{reason}</td>
                      <td
                        style={{
                          fontWeight: 700,
                          color: win ? "var(--emerald)" : loss ? "var(--crimson)" : "var(--ink-soft)",
                        }}
                      >
                        {!t.closed ? "持倉中" : fmtPct(t.pnl_pct)}
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        )}
      </Card>

      <div className="grid g2 mt">
        <Card title="最常用的心法" ico={<AppIcon name="scroll" size={22} framed variant="nav" />}>
          {(stats?.byPrinciple || []).length === 0 ? (
            <p className="muted small">平倉後並填寫「依據心法」，這裡會統計你最常依賴的判斷框架。</p>
          ) : (
            <div className="dl">
              {stats!.byPrinciple.slice(0, 5).map((row) => (
                <div className="row" key={row.key}>
                  <span className="k">{row.key}</span>
                  <span className="v">
                    {row.count} 次
                    {row.winRate != null ? ` · 勝率 ${row.winRate.toFixed(0)}%` : ""}
                  </span>
                </div>
              ))}
            </div>
          )}
        </Card>
        <Card title="復盤心得" ico={<AppIcon name="compass" size={22} framed variant="nav" />}>
          <div className="editorial" style={{ marginTop: 0 }}>
            {reviewNote}
          </div>
        </Card>
      </div>
        </>
      ) : null}

      <TradeFormModal
        open={formOpen}
        editing={editing}
        form={form}
        saving={saveMut.isPending || deleteMut.isPending}
        onChange={(patch) => setForm((f) => ({ ...f, ...patch }))}
        onClose={() => {
          setFormOpen(false);
          setEditing(null);
        }}
        onSave={() => saveMut.mutate()}
        onDelete={
          editing
            ? () => {
                if (confirm(`刪除 ${editing.symbol} 這筆紀錄？`)) deleteMut.mutate(editing.id);
              }
            : undefined
        }
      />

      <AccountSettingsModal
        open={accountModalOpen}
        editing={accountEditing}
        form={accountForm}
        saving={saveAccountMut.isPending || deleteAccountMut.isPending}
        onChange={(patch) => setAccountForm((f) => ({ ...f, ...patch }))}
        onClose={() => {
          setAccountModalOpen(false);
          setAccountEditing(null);
        }}
        onSave={() => saveAccountMut.mutate()}
        deleteError={deleteAccountMut.error?.message || null}
        onDelete={
          accountEditing
            ? ({ force }) => {
                const extra = force ? "\n\n將一併刪除所有交易、模擬與復盤記憶，無法復原。" : "";
                if (confirm(`確定刪除帳號「${accountEditing.name}」？${extra}`)) {
                  deleteAccountMut.mutate({ id: accountEditing.id, force });
                }
              }
            : undefined
        }
      />

      {activeAccount?.kind === "ai" && activeSimulationResult
        && (activeSimulationResult.summary || activeSimulationResult.report || activeSimulationResult.review) ? (
        <Card title="本輪 AI 交易員結果" ico={<AppIcon name="wizard" size={22} framed variant="nav" />} className="mt">
          <p className="editorial" style={{ marginTop: 0, whiteSpace: "pre-wrap" }}>
            {activeSimulationResult.report || activeSimulationResult.review || activeSimulationResult.summary}
          </p>
        </Card>
      ) : null}

      {(saveMut.error || deleteMut.error || saveAccountMut.error || deleteAccountMut.error || activeAiReviewError || activeSimulationError) && (
        <p className="small" style={{ color: "var(--crimson)", marginTop: 12 }}>
          {(
            saveMut.error ||
            deleteMut.error ||
            saveAccountMut.error ||
            deleteAccountMut.error ||
            activeAiReviewError ||
            activeSimulationError
          )?.message || "操作失敗"}
        </p>
      )}
    </>
  );
}
