/* Sidebar + Top Bar + Market Summary Bar */
const { Icon, Sparkline, fmt, fmtVol, sign, PctBadge } = window.UI;

const Sidebar = ({ page, setPage, sidebarW, collapsed: extCollapsed, onToggle }) => {
  const items = [
    { id: "overview", label: "總覽", icon: "dashboard" },
    { id: "watchlists", label: "觀察清單", icon: "list" },
    { id: "alerts", label: "通知規則", icon: "bell" },
    { id: "backtests", label: "回測", icon: "beaker" },
    { id: "news", label: "新聞", icon: "news" },
    { id: "settings", label: "設定", icon: "settings" },
  ];
  const collapsed = extCollapsed !== undefined ? extCollapsed : sidebarW < 90;
  const effectiveW = collapsed ? 64 : sidebarW;
  return (
    <aside className="sidebar" style={{ width: effectiveW }}>
      <div className="brand">
        <button className="btn ghost icon-btn sidebar-toggle"
          onClick={onToggle}
          title={collapsed ? "展開選單" : "收合選單"}>
          <Icon name="menu" size={16}/>
        </button>
        {!collapsed && (
          <div className="brand-text">
            <div className="brand-name">台美股</div>
            <div className="brand-sub">觀察工作台</div>
          </div>
        )}
      </div>
      <nav className="nav">
        {items.map(it => (
          <button key={it.id}
            className={"nav-item" + (page === it.id ? " active" : "")}
            onClick={() => setPage(it.id)}
            title={collapsed ? it.label : ""}>
            <Icon name={it.icon} size={16}/>
            {!collapsed && <span>{it.label}</span>}
          </button>
        ))}
      </nav>
      <div className="sidebar-footer">
        <div className={"deploy-mode " + (collapsed ? "collapsed" : "")}>
          {!collapsed && <span className="dim" style={{fontSize:"var(--fs-xs)"}}>部署模式</span>}
          <span className="pill accent dot">{collapsed ? "MVP" : "免費 MVP · CF"}</span>
        </div>
      </div>
    </aside>
  );
};

const TopBar = ({ theme, setTheme, user, onSignOut, goChart }) => {
  const [menuOpen, setMenuOpen] = React.useState(false);
  React.useEffect(() => {
    if (!menuOpen) return;
    const close = () => setMenuOpen(false);
    document.addEventListener("click", close);
    return () => document.removeEventListener("click", close);
  }, [menuOpen]);
  const [now, setNow] = React.useState(() => new Date());
  React.useEffect(() => {
    const id = setInterval(() => setNow(new Date()), 1000);
    return () => clearInterval(id);
  }, []);

  /* 搜尋 */
  const [q, setQ] = React.useState("");
  const [searchOpen, setSearchOpen] = React.useState(false);
  const [activeIdx, setActiveIdx] = React.useState(0);
  const [twUniverse, setTwUniverse] = React.useState([]);
  const searchRef = React.useRef(null);
  const inputRef = React.useRef(null);

  /* 非阻塞載入全台股 universe（首次有 token 才會成功，24h 快取）*/
  React.useEffect(() => {
    if (!window.FinMind || !window.FinMind.getTaiwanUniverse) return;
    window.FinMind.getTaiwanUniverse()
      .then((list) => setTwUniverse(list || []))
      .catch(() => {});
  }, []);

  const universe = React.useMemo(() => {
    const map = new Map();
    (window.MOCK?.WATCHLIST || []).forEach((s) => map.set(s.sym, s));
    twUniverse.forEach((s) => { if (!map.has(s.sym)) map.set(s.sym, s); });
    return Array.from(map.values());
  }, [twUniverse]);

  const candidates = React.useMemo(() => {
    const qq = q.trim().toLowerCase();
    if (!qq) return [];
    const matched = universe
      .filter((s) => s.sym.toLowerCase().includes(qq) || (s.name || "").toLowerCase().includes(qq))
      .slice(0, 8);
    const raw = q.trim();
    const isUsTicker = /^[A-Za-z]{1,5}$/.test(raw);
    const isTwTicker = /^\d{4,6}$/.test(raw);
    if (matched.length === 0 && (isUsTicker || isTwTicker)) {
      const sym = isUsTicker ? raw.toUpperCase() : raw + ".TW";
      return [{ sym, name: "未在清單，直接開圖", market: isUsTicker ? "US" : "TW", synthetic: true }];
    }
    return matched;
  }, [q, universe]);

  const resolveSym = (raw) => {
    const s = (raw || "").trim();
    if (!s) return null;
    if (s.includes(".")) return s.toUpperCase();
    if (/^\d+$/.test(s)) return s + ".TW";
    return s.toUpperCase();
  };

  const submitSearch = (override) => {
    if (!goChart) return;
    if (override) { goChart(override); }
    else if (candidates[activeIdx]) { goChart(candidates[activeIdx].sym); }
    else {
      const sym = resolveSym(q);
      if (sym) goChart(sym);
    }
    setQ("");
    setSearchOpen(false);
    setActiveIdx(0);
    inputRef.current && inputRef.current.blur();
  };

  React.useEffect(() => { setActiveIdx(0); }, [q]);

  React.useEffect(() => {
    if (!searchOpen) return;
    const close = (e) => {
      if (!searchRef.current) return;
      if (!searchRef.current.contains(e.target)) setSearchOpen(false);
    };
    document.addEventListener("mousedown", close);
    return () => document.removeEventListener("mousedown", close);
  }, [searchOpen]);

  /* ⌘K / Ctrl+K 聚焦搜尋 */
  React.useEffect(() => {
    const handler = (e) => {
      if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === "k") {
        e.preventDefault();
        inputRef.current && inputRef.current.focus();
        setSearchOpen(true);
      }
    };
    document.addEventListener("keydown", handler);
    return () => document.removeEventListener("keydown", handler);
  }, []);

  const fmtHm = (tz) => now.toLocaleTimeString("zh-TW", { hour12: false, hour: "2-digit", minute: "2-digit", timeZone: tz });
  const fmtHms = (tz) => now.toLocaleTimeString("zh-TW", { hour12: false, hour: "2-digit", minute: "2-digit", second: "2-digit", timeZone: tz });

  const twTrading = window.Intraday?.isTradingHoursTW?.() ?? false;
  const usTrading = window.Intraday?.isTradingHoursUS?.() ?? false;

  return (
    <header className="topbar">
      <div className="search-wrap" ref={searchRef} style={{ position: "relative" }}>
        <div className="search">
          <Icon name="search" size={14}/>
          <input ref={inputRef}
            className="search-input"
            placeholder="搜尋代號或名稱 — 2330 / NVDA / 台積電"
            value={q}
            onChange={(e) => { setQ(e.target.value); setSearchOpen(true); }}
            onFocus={() => setSearchOpen(true)}
            onKeyDown={(e) => {
              if (e.key === "Enter") { e.preventDefault(); submitSearch(); }
              else if (e.key === "Escape") { setSearchOpen(false); inputRef.current.blur(); }
              else if (e.key === "ArrowDown") { e.preventDefault(); setActiveIdx((i) => Math.min(candidates.length - 1, i + 1)); }
              else if (e.key === "ArrowUp") { e.preventDefault(); setActiveIdx((i) => Math.max(0, i - 1)); }
            }}/>
          <kbd>⌘K</kbd>
        </div>
        {searchOpen && q.trim() && (
          <div className="search-dropdown surface" style={{
            position: "absolute", top: "calc(100% + 6px)", left: 0, right: 0,
            zIndex: 50, padding: 4,
            border: "1px solid var(--border)", borderRadius: "var(--radius)",
            background: "var(--bg-elevated)", boxShadow: "0 10px 28px rgba(0,0,0,0.4)",
          }}>
            {candidates.length > 0 ? candidates.map((s, i) => (
              <button key={s.sym}
                onMouseDown={(e) => { e.preventDefault(); submitSearch(s.sym); }}
                onMouseEnter={() => setActiveIdx(i)}
                data-color-mode={s.market === "US" ? "us" : "tw"}
                style={{
                  display: "flex", alignItems: "center", gap: 10, width: "100%",
                  padding: "8px 10px", border: 0, borderRadius: 4,
                  background: i === activeIdx ? "var(--bg-app)" : "transparent",
                  color: "var(--text-1)", cursor: "pointer", textAlign: "left",
                  fontFamily: "inherit", fontSize: "var(--fs-sm)",
                }}>
                <span className="mono" style={{ fontWeight: 600, minWidth: 72 }}>{s.sym}</span>
                <span style={{ flex: 1 }}>{s.name}</span>
                <span className="pill" style={{ fontSize: 9 }}>{s.market === "TW" ? "TWSE" : "NASDAQ"}</span>
                {typeof s.pct === "number" && (
                  <span className={"num mono " + (s.pct >= 0 ? "up" : "down")} style={{ minWidth: 56, textAlign: "right" }}>
                    {s.pct >= 0 ? "+" : ""}{s.pct.toFixed(2)}%
                  </span>
                )}
              </button>
            )) : (
              <button onMouseDown={(e) => { e.preventDefault(); submitSearch(); }}
                style={{
                  display: "flex", alignItems: "center", gap: 10, width: "100%",
                  padding: "8px 10px", border: 0, borderRadius: 4,
                  background: "var(--bg-app)", color: "var(--text-1)", cursor: "pointer",
                  textAlign: "left", fontFamily: "inherit", fontSize: "var(--fs-sm)",
                }}>
                <Icon name="external" size={12}/>
                <span style={{ flex: 1 }}>直接查 <strong className="mono">{resolveSym(q)}</strong></span>
                <kbd style={{ fontSize: 9 }}>Enter</kbd>
              </button>
            )}
          </div>
        )}
      </div>
      <div className="topbar-spacer"/>
      <div className="topbar-status">
        <span className="status-item">
          <span className={"dot " + (twTrading ? "ok" : "off")}/>
          {twTrading ? `台股盤中 · ${fmtHm("Asia/Taipei")}` : "台股休市"}
        </span>
        <span className="status-item">
          <span className={"dot " + (usTrading ? "ok" : "off")}/>
          {usTrading ? `美股盤中 · ${fmtHm("America/New_York")} ET` : "美股休市"}
        </span>
        <span className="status-item dim">現在 {fmtHms("Asia/Taipei")}</span>
      </div>
      <div className="topbar-actions">
        <button className="btn ghost icon-btn" onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
          title="Toggle theme">
          <Icon name={theme === "dark" ? "sun" : "moon"} size={15}/>
        </button>
        <button className="btn ghost icon-btn" title="Refresh"><Icon name="refresh" size={15}/></button>
        {user && (
          <div className="user-menu" onClick={(e) => e.stopPropagation()}>
            <button className="user-avatar-btn" title={user.email || user.displayName || ""}
              onClick={() => setMenuOpen((o) => !o)}>
              {user.photoURL
                ? <img src={user.photoURL} alt="" className="user-avatar"/>
                : <div className="user-avatar fallback">{(user.displayName || user.email || "?")[0].toUpperCase()}</div>}
            </button>
            {menuOpen && (
              <div className="user-menu-pop surface">
                <div className="user-menu-head">
                  <div className="user-menu-name">{user.displayName || "(無名)"}</div>
                  <div className="user-menu-email dim mono">{user.email}</div>
                </div>
                <button className="user-menu-item" onClick={() => { setMenuOpen(false); onSignOut(); }}>
                  <Icon name="external" size={12}/> 登出
                </button>
              </div>
            )}
          </div>
        )}
      </div>
    </header>
  );
};

const MarketSummaryBar = ({ data }) => (
  <div className="market-bar">
    {data.map((m, i) => {
      const mode = m.region === "TW" ? "tw" : (m.region === "US" ? "us" : "tw");
      const cls = m.pct >= 0 ? "up" : "down";
      return (
        <div className="market-tile" key={i} data-color-mode={mode}>
          <div className="market-tile-head">
            <span className="market-tile-name">{m.name}</span>
            <span className="market-tile-region dim">{m.region}</span>
          </div>
          <div className="market-tile-row">
            <span className="num market-tile-price">{fmt(m.price, m.price > 1000 ? 2 : 2)}</span>
            <Sparkline data={m.spark} width={56} height={20}/>
          </div>
          <div className="market-tile-row sub">
            <span className={"num " + cls}>{m.chg >= 0 ? "+" : ""}{fmt(m.chg, 2)}</span>
            <span className={"num " + cls}>{m.pct >= 0 ? "+" : ""}{fmt(m.pct, 2)}%</span>
          </div>
        </div>
      );
    })}
  </div>
);

window.Shell = { Sidebar, TopBar, MarketSummaryBar };
