/* Page 5 — Settings / Data Sources */
const { Icon } = window.UI;

const SettingsPage = () => {
  const [fmToken, setFmToken] = React.useState(() => (window.FinMind ? window.FinMind.getToken() : ""));
  const saveFmToken = () => {
    if (window.FinMind) window.FinMind.setToken(fmToken);
    if (window.FinMind) window.FinMind.clearCache();
    alert("FinMind token 已儲存，快取已清空。請重新載入 K 線頁面。");
  };

  const [workerUrl, setWorkerUrl] = React.useState(() => (window.Intraday ? window.Intraday.getWorkerUrl() : ""));
  const [workerAuth, setWorkerAuth] = React.useState(() => (window.Intraday ? window.Intraday.getAuth() : ""));
  const [pollSec, setPollSec] = React.useState(() => (window.Intraday ? window.Intraday.getPollSeconds() : 10));
  const [intradayStatus, setIntradayStatus] = React.useState(null);
  const saveIntraday = () => {
    if (!window.Intraday) return;
    window.Intraday.setWorkerUrl(workerUrl);
    window.Intraday.setAuth(workerAuth);
    window.Intraday.setPollSeconds(pollSec);
    alert("即時報價設定已儲存。");
  };
  const testIntraday = async () => {
    if (!window.Intraday) return;
    window.Intraday.setWorkerUrl(workerUrl);
    window.Intraday.setAuth(workerAuth);
    setIntradayStatus({ kind: "loading", msg: "測試中…" });
    try {
      const q = await window.Intraday.getQuote("2330.TW");
      setIntradayStatus({ kind: "ok", msg: `OK · ${q.source} · ${q.sym} 最新 ${q.price}（${new Date(q.ts).toLocaleTimeString()}）` });
    } catch (e) {
      setIntradayStatus({ kind: "err", msg: `失敗：${e.message}` });
    }
  };

  /* Telegram */
  const [tgChatId, setTgChatId] = React.useState(() => (window.Telegram ? window.Telegram.getChatId() : ""));
  const [tgBot, setTgBot] = React.useState(null);
  const [tgRecent, setTgRecent] = React.useState([]);
  const [tgStatus, setTgStatus] = React.useState(null);

  React.useEffect(() => {
    if (!window.Telegram) return;
    window.Telegram.getMe().then(setTgBot).catch(() => setTgBot(null));
  }, []);

  const saveTg = () => {
    if (!window.Telegram) return;
    window.Telegram.setChatId(tgChatId);
    alert("Telegram Chat ID 已儲存。");
  };
  const detectChatId = async () => {
    if (!window.Telegram) return;
    setTgStatus({ kind: "loading", msg: "讀取最近聊過的對話…" });
    try {
      const chats = await window.Telegram.listRecentChats();
      setTgRecent(chats);
      if (chats.length === 0) {
        setTgStatus({ kind: "warn", msg: "沒抓到任何對話。請先到 Telegram 開啟與 bot 的對話、傳一則訊息（如 /start）後再試。" });
      } else {
        setTgStatus({ kind: "ok", msg: `找到 ${chats.length} 個最近的對話，請點選下方 chat 套用 ID。` });
      }
    } catch (e) {
      setTgStatus({ kind: "err", msg: `失敗：${e.message}` });
    }
  };
  const testTg = async () => {
    if (!window.Telegram) return;
    window.Telegram.setChatId(tgChatId);
    setTgStatus({ kind: "loading", msg: "送出測試訊息…" });
    try {
      const now = new Date().toLocaleString("zh-TW", { hour12: false });
      await window.Telegram.sendMessage(`<b>TWStock Workbench 測試訊息</b>\n時間：${now}\n如果你看到這則訊息，代表 bot 連線成功 ✅`);
      setTgStatus({ kind: "ok", msg: `OK，已送到 chat ${tgChatId}。` });
    } catch (e) {
      setTgStatus({ kind: "err", msg: `失敗：${e.message}` });
    }
  };

  /* 今日觸發 (從首頁搬過來) — alert engine 尚未實作，先空陣列；rules 數從 localStorage 讀 */
  const triggered = (window.MOCK && window.MOCK.TRIGGERED_ALERTS) || [];
  const [alertRules] = window.usePersistedState("alert.rules", window.MOCK.DEFAULT_ALERT_RULES);
  const armed = (alertRules || []).filter(a => a.on).length;

  /* ===== 資料備份：匯出 / 匯入所有 twstock.* localStorage ===== */
  const fileInputRef = React.useRef(null);
  const [backupStatus, setBackupStatus] = React.useState(null);

  const countLocalKeys = () => {
    let n = 0;
    for (let i = 0; i < localStorage.length; i++) {
      const k = localStorage.key(i);
      if (k && k.startsWith("twstock.")) n++;
    }
    return n;
  };
  const exportAllData = () => {
    const data = {};
    for (let i = 0; i < localStorage.length; i++) {
      const key = localStorage.key(i);
      if (!key || !key.startsWith("twstock.")) continue;
      try { data[key] = JSON.parse(localStorage.getItem(key)); }
      catch (e) { data[key] = localStorage.getItem(key); }
    }
    const blob = new Blob([JSON.stringify(data, null, 2)], { type: "application/json" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = `twstock-backup-${new Date().toISOString().slice(0, 10)}.json`;
    a.click();
    setTimeout(() => URL.revokeObjectURL(url), 500);
    setBackupStatus({ kind: "ok", msg: `已匯出 ${Object.keys(data).length} 筆設定` });
  };
  const importAllData = (file) => {
    const reader = new FileReader();
    reader.onload = (e) => {
      try {
        const data = JSON.parse(e.target.result);
        let n = 0;
        Object.keys(data).forEach((key) => {
          if (!key.startsWith("twstock.")) return;
          localStorage.setItem(key, JSON.stringify(data[key]));
          n++;
        });
        setBackupStatus({ kind: "ok", msg: `已匯入 ${n} 筆設定` });
        if (confirm(`匯入完成（${n} 筆）。重新整理頁面以套用？`)) {
          location.reload();
        }
      } catch (err) {
        setBackupStatus({ kind: "err", msg: `匯入失敗：${err.message}` });
      }
    };
    reader.readAsText(file);
  };
  const onImportFile = (e) => {
    const f = e.target.files && e.target.files[0];
    if (f) importAllData(f);
    e.target.value = "";
  };

  /* ===== Alert engine sync to worker（每日訊號排程）===== */
  const [alertStatus, setAlertStatus] = React.useState(null);
  const [alertBusy, setAlertBusy] = React.useState(null); // null | "sync" | "tw" | "us" | "refresh"

  const alertApi = async (path, opts = {}) => {
    if (!workerUrl) throw new Error("尚未設定 Worker URL");
    const headers = { "Content-Type": "application/json", ...opts.headers };
    if (workerAuth) headers["X-Auth"] = workerAuth;
    const url = workerUrl.replace(/\/$/, "") + path;
    const res = await fetch(url, { ...opts, headers });
    const json = await res.json();
    if (!res.ok) throw new Error(json.error || `HTTP ${res.status}`);
    return json;
  };

  const syncAlertConfig = async () => {
    setAlertBusy("sync");
    try {
      /* 與「清單變更自動同步」共用 src/services/intraday.jsx 的 pushAlertConfig，避免兩份組 payload 邏輯漂移 */
      const result = await window.Intraday.pushAlertConfig();
      if (result.skipped === "no-worker-url") throw new Error("尚未設定 Worker URL");
      if (result.skipped === "no-chat-id") throw new Error("尚未設定 Telegram Chat ID（請先在 Telegram 區塊偵測並儲存）");
      setAlertStatus({ kind: "ok", msg: `已同步 · 台股 ${result.watchTW.length} 檔 · 美股 ${result.watchUS.length} 檔`, at: Date.now() });
      await refreshAlertStatus();
    } catch (err) {
      setAlertStatus({ kind: "err", msg: err.message });
    } finally {
      setAlertBusy(null);
    }
  };

  const runScanNow = async (market) => {
    setAlertBusy(market.toLowerCase());
    try {
      const result = await alertApi(`/alert/run?market=${market}`, { method: "POST" });
      setAlertStatus({
        kind: result.sent ? "ok" : "warn",
        msg: result.sent
          ? `${market} 已送出（掃 ${result.scanned} 檔 · 觸發 ${result.triggered} 檔）`
          : (result.error || `${market} 完成但未送出`),
        at: Date.now(),
      });
      await refreshAlertStatus();
    } catch (err) {
      setAlertStatus({ kind: "err", msg: err.message });
    } finally {
      setAlertBusy(null);
    }
  };

  const refreshAlertStatus = async () => {
    if (!workerUrl) return;
    setAlertBusy((b) => b || "refresh");
    try {
      const data = await alertApi("/alert/status");
      setAlertStatus((s) => ({
        ...(s || {}),
        worker: data,
      }));
    } catch (err) {
      /* 靜默 */
    } finally {
      setAlertBusy((b) => (b === "refresh" ? null : b));
    }
  };

  React.useEffect(() => { if (workerUrl) refreshAlertStatus(); /* eslint-disable-next-line */ }, [workerUrl]);

  /* TDCC 大戶持股 — 手動觸發 + 狀態查詢 */
  const [tdccStatus, setTdccStatus] = React.useState(null);
  const [tdccBusy, setTdccBusy] = React.useState(null); // null | "refresh" | "status"
  const refreshTdccStatus = async () => {
    if (!workerUrl || !window.TDCC) return;
    setTdccBusy((b) => b || "status");
    try {
      const data = await window.TDCC.getStatus();
      setTdccStatus({ kind: "ok", weeks: data.weeks || [], meta: data.meta });
    } catch (err) {
      setTdccStatus({ kind: "err", msg: err.message });
    } finally {
      setTdccBusy((b) => (b === "status" ? null : b));
    }
  };
  const runTdccRefresh = async () => {
    if (!workerUrl || !window.TDCC) return;
    setTdccBusy("refresh");
    try {
      const result = await window.TDCC.refresh();
      setTdccStatus({ kind: "ok", msg: `下載完成：${result.lastDate} · 全市場 ${result.stocks} 檔` });
      await refreshTdccStatus();
    } catch (err) {
      setTdccStatus({ kind: "err", msg: err.message });
    } finally {
      setTdccBusy(null);
    }
  };
  React.useEffect(() => { if (workerUrl) refreshTdccStatus(); /* eslint-disable-next-line */ }, [workerUrl]);

  return (
    <div className="page settings-page">
      {/* 監控雙列：今日觸發 + 資料健康 */}
      <div className="settings-monitor">
        <section className="surface set-card monitor-card">
          <header className="section-head">
            <h2 className="section-title">今日觸發</h2>
            <div className="section-head-r">
              <span className="dim mono" style={{fontSize:"var(--fs-xs)"}}>{armed} 條規則待命</span>
              <span className={"pill " + (triggered.length > 0 ? "accent dot" : "")}>{triggered.length}</span>
            </div>
          </header>
          {triggered.length === 0 ? (
            <div className="monitor-empty dim">
              <Icon name="bell" size={20}/>
              <span>今天還沒有規則被觸發</span>
            </div>
          ) : (
            <ul className="trigger-strip">
              {triggered.map((a, i) => (
                <li key={i} className="trigger-strip-item">
                  <span className={"alert-dot " + a.level}/>
                  <div className="trigger-strip-body">
                    <div className="trigger-strip-row">
                      <span className="mono" style={{fontWeight:600}}>{a.sym}</span>
                      <span className="dim mono" style={{fontSize:"var(--fs-xs)"}}>{a.time}</span>
                    </div>
                    <div className="dim" style={{fontSize:"var(--fs-sm)"}}>{a.rule}</div>
                  </div>
                </li>
              ))}
            </ul>
          )}
        </section>
      </div>

      <div className="settings-grid">
        {/* Deployment Mode */}
        <section className="surface set-card">
          <header className="section-head">
            <h2 className="section-title">部署模式</h2>
            <span className="pill accent dot">免費 MVP</span>
          </header>
          <div className="deploy-options">
            <label className="deploy-opt selected">
              <input type="radio" name="dep" defaultChecked/>
              <div>
                <div className="deploy-title">免費 MVP</div>
                <div className="dim" style={{fontSize:"var(--fs-sm)"}}>Cloudflare Pages · Workers · D1 · GitHub Actions</div>
              </div>
              <span className="pill success dot">使用中</span>
            </label>
            <label className="deploy-opt">
              <input type="radio" name="dep"/>
              <div>
                <div className="deploy-title">正式環境</div>
                <div className="dim" style={{fontSize:"var(--fs-sm)"}}>Cloud Run · managed PostgreSQL · TimescaleDB</div>
              </div>
              <span className="pill">可選</span>
            </label>
            <label className="deploy-opt">
              <input type="radio" name="dep"/>
              <div>
                <div className="deploy-title">Firebase（選配）</div>
                <div className="dim" style={{fontSize:"var(--fs-sm)"}}>Hosting / Auth / 設定存放—不作為 K 線主資料庫</div>
              </div>
              <span className="pill">選配</span>
            </label>
          </div>
        </section>

        {/* Data Providers */}
        <section className="surface set-card">
          <header className="section-head"><h2 className="section-title">資料來源</h2></header>
          <div className="provider-list">
            <div className="provider-row">
              <div className="provider-l">
                <div className="provider-name">FinMind</div>
                <div className="dim mono" style={{fontSize:"var(--fs-xs)"}}>
                  {fmToken ? `Token：${fmToken.slice(0, 6)}••••${fmToken.slice(-4)}` : "未設定 token（免費 300 req/hr）"}
                </div>
              </div>
              <div className="provider-bar" style={{display:"flex", gap:6, alignItems:"center"}}>
                <input className="input mono" type="password" placeholder="貼上 FinMind token"
                  value={fmToken} onChange={(e) => setFmToken(e.target.value)}
                  style={{flex:1, fontSize:"var(--fs-xs)"}}/>
                <button className="btn" onClick={saveFmToken}>儲存</button>
              </div>
              <div className="provider-r">
                <span className="dim mono" style={{fontSize:"var(--fs-xs)"}}>{fmToken ? "600 req/hr" : "300 req/hr"}</span>
              </div>
            </div>
            <div className="provider-row">
              <div className="provider-l">
                <div className="provider-name">twstock</div>
                <div className="dim mono" style={{fontSize:"var(--fs-xs)"}}>僅作備援 · 無需 token</div>
              </div>
              <div className="provider-bar">
                <span className="pill">備援</span>
              </div>
              <div className="provider-r">
                <span className="dim mono" style={{fontSize:"var(--fs-xs)"}}>最近備援 04-29</span>
              </div>
            </div>
            <div className="provider-row">
              <div className="provider-l">
                <div className="provider-name">美股資料源</div>
                <div className="dim mono" style={{fontSize:"var(--fs-xs)"}}>
                  日 K 走 FinMind USStockPrice · 即時報價走 Yahoo Finance（透過 Cloudflare Worker）
                </div>
              </div>
              <div className="provider-bar">
                <span className="pill success dot">已就緒</span>
              </div>
              <div className="provider-r">
                <span className={"pill " + (workerUrl ? "success dot" : "warn")} style={{fontSize:"var(--fs-xs)"}}>
                  {workerUrl ? "Yahoo 即時報價已啟用" : "即時報價未啟用"}
                </span>
              </div>
            </div>
          </div>
        </section>

        {/* Intraday — Cloudflare Worker proxy 抓 TWSE MIS / Yahoo Finance 即時報價 */}
        <section className="surface set-card">
          <header className="section-head">
            <h2 className="section-title">即時報價</h2>
            <span className={"pill " + (workerUrl ? "success dot" : "warn")}>{workerUrl ? "已啟用" : "未啟用"}</span>
          </header>
          <div className="form-grid two">
            <div className="form-row col" style={{gridColumn:"1 / -1"}}>
              <label className="form-label">Cloudflare Worker URL</label>
              <input className="input mono" placeholder="https://twstock-intraday.<account>.workers.dev"
                value={workerUrl} onChange={(e) => setWorkerUrl(e.target.value)}/>
              <span className="dim mono" style={{fontSize:"var(--fs-xs)", marginTop:4}}>
                部署 worker/ 目錄到 Cloudflare（見 worker/README.md）
              </span>
            </div>
            <div className="form-row col">
              <label className="form-label">Shared Secret</label>
              <input className="input mono" type="password" placeholder="與 wrangler secret put SHARED_SECRET 同字串"
                value={workerAuth} onChange={(e) => setWorkerAuth(e.target.value)}/>
            </div>
            <div className="form-row col">
              <label className="form-label">輪詢秒數</label>
              <input className="input mono" type="number" min="3" max="120"
                value={pollSec} onChange={(e) => setPollSec(parseInt(e.target.value, 10) || 10)}/>
              <span className="dim mono" style={{fontSize:"var(--fs-xs)", marginTop:4}}>
                盤中每 N 秒抓一次；盤外只抓一次
              </span>
            </div>
            <div className="form-row col" style={{gridColumn:"1 / -1", display:"flex", gap:8, alignItems:"center", flexWrap:"wrap"}}>
              <button className="btn primary" onClick={saveIntraday}>儲存</button>
              <button className="btn" onClick={testIntraday} disabled={!workerUrl}>
                <Icon name="refresh" size={13}/> 測試（2330.TW）
              </button>
              {intradayStatus && (
                <span className={"pill " + (
                  intradayStatus.kind === "ok" ? "success dot"
                  : intradayStatus.kind === "err" ? "danger dot"
                  : ""
                )} style={{fontSize:"var(--fs-xs)"}}>
                  {intradayStatus.msg}
                </span>
              )}
            </div>
          </div>
        </section>

        {/* Telegram */}
        <section className="surface set-card">
          <header className="section-head">
            <h2 className="section-title">Telegram</h2>
            <span className={"pill " + (tgBot ? "success dot" : "warn")}>
              {tgBot ? `@${tgBot.username}` : "Bot 未就緒"}
            </span>
          </header>
          <div className="form-grid two">
            <div className="form-row col"><label className="form-label">Bot 狀態</label>
              <div className="readonly-row">
                {tgBot
                  ? <><span className="mono">@{tgBot.username}</span> <span className="dim">{tgBot.first_name}</span></>
                  : <span className="dim">需先部署 Worker 並設 TELEGRAM_BOT_TOKEN secret</span>}
              </div>
            </div>
            <div className="form-row col"><label className="form-label">Chat ID</label>
              <input className="input mono" placeholder="例：123456789（個人）或 -1001234567890（群組）"
                value={tgChatId} onChange={(e) => setTgChatId(e.target.value)}/>
              <span className="dim mono" style={{fontSize:"var(--fs-xs)", marginTop:4}}>
                先在 Telegram 跟 bot 傳訊息，再按下方「自動偵測」
              </span>
            </div>
            <div className="form-row col" style={{gridColumn:"1 / -1", display:"flex", gap:8, flexWrap:"wrap"}}>
              <button className="btn primary" onClick={saveTg}>儲存 Chat ID</button>
              <button className="btn" onClick={detectChatId} disabled={!tgBot}>
                <Icon name="search" size={13}/> 自動偵測 Chat ID
              </button>
              <button className="btn" onClick={testTg} disabled={!tgChatId || !tgBot}>
                <Icon name="send" size={13}/> 送出測試訊息
              </button>
              {tgStatus && (
                <span className={"pill " + (
                  tgStatus.kind === "ok" ? "success dot"
                  : tgStatus.kind === "err" ? "danger dot"
                  : tgStatus.kind === "warn" ? "warn"
                  : ""
                )} style={{fontSize:"var(--fs-xs)", maxWidth:"100%", whiteSpace:"normal", textAlign:"left"}}>
                  {tgStatus.msg}
                </span>
              )}
            </div>
            {tgRecent.length > 0 && (
              <div className="form-row col" style={{gridColumn:"1 / -1"}}>
                <label className="form-label">最近與 bot 互動的對話</label>
                <div style={{display:"flex", flexDirection:"column", gap:4}}>
                  {tgRecent.map((c) => (
                    <button key={c.chat_id} className="btn ghost"
                      style={{justifyContent:"flex-start", textAlign:"left", padding:"6px 10px"}}
                      onClick={() => setTgChatId(String(c.chat_id))}>
                      <span className="mono" style={{fontWeight:600, minWidth:140}}>{c.chat_id}</span>
                      <span style={{flex:1, marginLeft:10}}>{c.title}{c.username ? ` (@${c.username})` : ""}</span>
                      <span className="pill" style={{fontSize:9}}>{c.type}</span>
                    </button>
                  ))}
                </div>
              </div>
            )}
          </div>
        </section>

        {/* Market Preferences */}
        <section className="surface set-card">
          <header className="section-head"><h2 className="section-title">市場偏好</h2></header>
          <div className="form-grid two">
            <div className="form-row col"><label className="form-label">時區</label>
              <select className="select"><option>Asia/Taipei (UTC+8)</option><option>America/New_York</option></select>
            </div>
            <div className="form-row col"><label className="form-label">預設觀察清單</label>
              <select className="select"><option>台股核心</option><option>美股科技</option><option>全部</option></select>
            </div>
            <div className="form-row col"><label className="form-label">預設 K 線週期</label>
              <div className="seg" style={{height:32}}><button className="active">日 K</button><button>週 K</button><button>月 K</button></div>
            </div>
            <div className="form-row col"><label className="form-label">更新頻率</label>
              <div className="seg" style={{height:32}}><button>5 分鐘</button><button className="active">15 分鐘</button><button>收盤後</button></div>
            </div>
          </div>
        </section>

        {/* 自動通知排程 — Cron + KC scan + Telegram */}
        <section className="surface set-card span-2">
          <header className="section-head">
            <div className="section-head-l">
              <h2 className="section-title">自動通知排程</h2>
              <span className="dim mono" style={{fontSize:"var(--fs-xs)"}}>
                每天台股 13:00、美股 03:30 / 04:30 Taipei 各推一次
              </span>
            </div>
            <button className="btn ghost" onClick={refreshAlertStatus}
                    title="重新整理 Worker 狀態"
                    style={{padding:"2px 8px", fontSize:"var(--fs-xs)"}}>
              <Icon name="refresh" size={12}/> 更新
            </button>
          </header>
          <div style={{padding:"10px 14px 14px"}}>
            <p className="dim" style={{fontSize:"var(--fs-sm)", marginTop:0, marginBottom:12, lineHeight:1.5}}>
              Worker 端 Cron 自動掃描觀察清單，遇到「盤整突破」或「回後買上漲」訊號即透過 Telegram 推一則訊號總結。
              先按 <strong>同步到 Worker</strong> 把觀察清單與 Chat ID 推上去，之後 Worker 會在收盤前 30 分鐘自動跑。
            </p>
            <div style={{display:"flex", gap:8, flexWrap:"wrap", marginBottom:12}}>
              <button className="btn primary" onClick={syncAlertConfig} disabled={alertBusy === "sync" || !workerUrl}>
                <Icon name="send" size={13}/> {alertBusy === "sync" ? "同步中…" : "同步到 Worker"}
              </button>
              <button className="btn" onClick={() => runScanNow("TW")} disabled={alertBusy === "tw" || !workerUrl}>
                <Icon name="play" size={13}/> {alertBusy === "tw" ? "掃描中…" : "立即觸發 台股"}
              </button>
              <button className="btn" onClick={() => runScanNow("US")} disabled={alertBusy === "us" || !workerUrl}>
                <Icon name="play" size={13}/> {alertBusy === "us" ? "掃描中…" : "立即觸發 美股"}
              </button>
              {!workerUrl && (
                <span className="pill warn" style={{alignSelf:"center"}}>需先設定 Worker URL</span>
              )}
              {alertStatus && alertStatus.msg && (
                <span className={"pill " + (alertStatus.kind === "ok" ? "success dot" : alertStatus.kind === "warn" ? "warn" : "danger dot")}
                      style={{alignSelf:"center"}}>{alertStatus.msg}</span>
              )}
            </div>
            {alertStatus && alertStatus.worker && (
              <div className="health-board" style={{gridTemplateColumns:"repeat(3, 1fr)"}}>
                <div className="hb-tile">
                  <div className="dim sec-title">Worker 上同步</div>
                  <div className="mono hb-val" style={{fontSize:"var(--fs-sm)"}}>
                    {alertStatus.worker.config
                      ? new Date(alertStatus.worker.config.updatedAt).toLocaleString("zh-TW", {hour12: false})
                      : "尚未同步"}
                  </div>
                </div>
                <div className="hb-tile">
                  <div className="dim sec-title">已同步觀察數</div>
                  <div className="mono hb-val">
                    {alertStatus.worker.config
                      ? `${(alertStatus.worker.config.watchTW || []).length} TW · ${(alertStatus.worker.config.watchUS || []).length} US`
                      : "—"}
                  </div>
                </div>
                <div className="hb-tile">
                  <div className="dim sec-title">上次掃描</div>
                  <div className="mono hb-val" style={{fontSize:"var(--fs-sm)"}}>
                    {alertStatus.worker.lastScan
                      ? `${alertStatus.worker.lastScan.market} · ${new Date(alertStatus.worker.lastScan.ts).toLocaleString("zh-TW", {hour12: false})} · 觸發 ${alertStatus.worker.lastScan.triggered || 0}`
                      : "尚無紀錄"}
                  </div>
                </div>
              </div>
            )}
          </div>
        </section>

        {/* TDCC 大戶持股 — 每週六自動下載 + 手動觸發 */}
        <section className="surface set-card span-2">
          <header className="section-head">
            <h2 className="section-title">TDCC 大戶持股</h2>
            <span className={"pill " + (workerUrl ? "success dot" : "warn")}>{workerUrl ? "已啟用" : "未啟用"}</span>
          </header>
          <div style={{padding:"10px 14px 14px"}}>
            <p className="dim" style={{fontSize:"var(--fs-sm)", marginTop:0, marginBottom:10, lineHeight:1.5}}>
              Worker cron 每週六台北 18:00 自動下載 TDCC 集保戶股權分散表全市場快照（~7MB）並累積到 KV。
              冷啟動或想立即補抓最新一週，按下方「立即下載」。
            </p>
            <div style={{display:"flex", gap:8, marginBottom:10, flexWrap:"wrap"}}>
              <button className="btn primary" onClick={runTdccRefresh} disabled={tdccBusy === "refresh" || !workerUrl}>
                <Icon name="refresh" size={13}/> {tdccBusy === "refresh" ? "下載中…" : "立即下載最新一週"}
              </button>
              <button className="btn" onClick={refreshTdccStatus} disabled={tdccBusy === "status" || !workerUrl}>
                <Icon name="refresh" size={13}/> 重新整理狀態
              </button>
              {!workerUrl && (
                <span className="pill warn" style={{alignSelf:"center"}}>需先設定 Worker URL</span>
              )}
              {tdccStatus && tdccStatus.kind === "err" && (
                <span className="pill danger dot" style={{alignSelf:"center"}}>{tdccStatus.msg}</span>
              )}
              {tdccStatus && tdccStatus.msg && tdccStatus.kind === "ok" && (
                <span className="pill success dot" style={{alignSelf:"center"}}>{tdccStatus.msg}</span>
              )}
            </div>
            {tdccStatus && tdccStatus.weeks && (
              <div className="health-board" style={{gridTemplateColumns:"repeat(3, 1fr)"}}>
                <div className="hb-tile">
                  <div className="dim sec-title">已累積週數</div>
                  <div className="mono hb-val">{tdccStatus.weeks.length} 週</div>
                </div>
                <div className="hb-tile">
                  <div className="dim sec-title">最新一週</div>
                  <div className="mono hb-val" style={{fontSize:"var(--fs-sm)"}}>
                    {tdccStatus.weeks[0]
                      ? `${tdccStatus.weeks[0].slice(0,4)}/${tdccStatus.weeks[0].slice(4,6)}/${tdccStatus.weeks[0].slice(6,8)}`
                      : "—"}
                  </div>
                </div>
                <div className="hb-tile">
                  <div className="dim sec-title">最近抓取</div>
                  <div className="mono hb-val" style={{fontSize:"var(--fs-sm)"}}>
                    {tdccStatus.meta && tdccStatus.meta.lastFetchAt
                      ? new Date(tdccStatus.meta.lastFetchAt).toLocaleString("zh-TW", {hour12: false})
                      : "—"}
                  </div>
                </div>
              </div>
            )}
          </div>
        </section>

        {/* 資料備份 — 匯出 / 匯入 localStorage（搬移到正式版用） */}
        <section className="surface set-card span-2">
          <header className="section-head">
            <h2 className="section-title">資料備份</h2>
            <span className="dim mono" style={{fontSize:"var(--fs-xs)"}}>
              {countLocalKeys()} 筆 twstock.* 設定
            </span>
          </header>
          <div style={{padding:"10px 14px 14px"}}>
            <p className="dim" style={{fontSize:"var(--fs-sm)", marginTop:0, marginBottom:12, lineHeight:1.5}}>
              匯出本機 localStorage 內所有 <code className="mono">twstock.*</code> 設定為 JSON 檔（包含觀察清單、
              FinMind token、Worker URL、Telegram chat ID、繪圖、Rail toggle…）。
              到另一個 origin（例如正式網域）匯入即可整批還原。
            </p>
            <div style={{display:"flex", gap:8, flexWrap:"wrap"}}>
              <button className="btn primary" onClick={exportAllData}>
                <Icon name="external" size={13}/> 匯出全部設定
              </button>
              <button className="btn" onClick={() => fileInputRef.current && fileInputRef.current.click()}>
                <Icon name="plus" size={13}/> 匯入 JSON…
              </button>
              <input ref={fileInputRef} type="file" accept="application/json,.json"
                     style={{display:"none"}} onChange={onImportFile}/>
              {backupStatus && (
                <span className={"pill " + (backupStatus.kind === "ok" ? "success dot" : "danger dot")}
                      style={{alignSelf:"center"}}>
                  {backupStatus.msg}
                </span>
              )}
            </div>
            <p className="dim" style={{fontSize:"var(--fs-xs)", marginTop:10, marginBottom:0}}>
              提示：匯入會覆蓋同 key 的現有設定。建議先匯出當前 origin 做為備份。
            </p>
          </div>
        </section>

        {/* Data Health */}
        <section className="surface set-card span-2">
          <header className="section-head">
            <h2 className="section-title">資料健康</h2>
            <span className="pill success dot">正常</span>
          </header>
          <div className="health-board">
            <div className="hb-tile"><div className="dim sec-title">最後報價同步</div><div className="mono hb-val">10:31:02</div></div>
            <div className="hb-tile"><div className="dim sec-title">最後 K 線同步</div><div className="mono hb-val">10:30:00</div></div>
            <div className="hb-tile"><div className="dim sec-title">更新頻率</div><div className="mono hb-val">15 分鐘</div></div>
            <div className="hb-tile"><div className="dim sec-title">預覽資料年齡</div><div className="mono hb-val">2 分鐘</div></div>
            <div className="hb-tile"><div className="dim sec-title">確認資料年齡</div><div className="mono hb-val">1 天</div></div>
            <div className="hb-tile"><div className="dim sec-title">失敗任務</div><div className="mono hb-val warn">2</div></div>
            <div className="hb-tile"><div className="dim sec-title">遺漏資料</div><div className="mono hb-val">0 棒</div></div>
            <div className="hb-tile"><div className="dim sec-title">GH Actions</div><div className="mono hb-val">10:00 ✓</div></div>
            <div className="hb-tile"><div className="dim sec-title">CF D1</div><div className="mono hb-val"><span className="pill success dot">上線</span></div></div>
          </div>
        </section>
      </div>
    </div>
  );
};

window.SettingsPage = SettingsPage;
