/* eslint-disable */
/**
 * Desktop UI shell — Pro Trading Dark.
 * Заменяет старый app.jsx App-компонент на широких экранах (>640px).
 * Mobile продолжает работать через MobileApp.
 *
 * Архитектура:
 *   DesktopApp
 *   ├─ DesktopSidebar  (навигация + аккаунт)
 *   ├─ DesktopHeader   (заголовок + биржевой свитчер + уведомления)
 *   └─ <Screen>        (один из DashboardScreen, BotsScreen, ...)
 *
 * Использует существующие window.MobileAPI методы (без переписывания backend
 * слоя). Тосты, modals, theme — самостоятельные.
 *
 * Весь файл обёрнут в IIFE — Babel-standalone компилирует все JSX в одном
 * scope, и наши const могли бы пересечься с mobile-app.jsx.
 */
(function () {
const { useState, useEffect, useCallback, useMemo, useRef } = React;

// ───────────────────────── Icons (минимальный inline set) ─────────────────────────
const DIcon = ({ name, size = 18, ...p }) => {
  const s = size;
  const stroke = "currentColor";
  const sw = 1.6;
  const paths = {
    dashboard: <><rect x="3" y="3" width="7" height="9" rx="1.5" stroke={stroke} strokeWidth={sw} fill="none"/><rect x="14" y="3" width="7" height="5" rx="1.5" stroke={stroke} strokeWidth={sw} fill="none"/><rect x="14" y="12" width="7" height="9" rx="1.5" stroke={stroke} strokeWidth={sw} fill="none"/><rect x="3" y="16" width="7" height="5" rx="1.5" stroke={stroke} strokeWidth={sw} fill="none"/></>,
    bot: <><rect x="4" y="7" width="16" height="12" rx="3" stroke={stroke} strokeWidth={sw} fill="none"/><circle cx="9" cy="13" r="1.5" fill={stroke}/><circle cx="15" cy="13" r="1.5" fill={stroke}/><path d="M12 3v4M8 19v2M16 19v2" stroke={stroke} strokeWidth={sw}/></>,
    chart: <><path d="M4 19h16M7 16V9m4 7V5m4 11v-9" stroke={stroke} strokeWidth={sw} strokeLinecap="round"/></>,
    signal: <><path d="M3 14a9 9 0 0 1 9-9M3 14a9 9 0 0 0 9 9M21 14a9 9 0 0 0-9-9M21 14a9 9 0 0 1-9 9" stroke={stroke} strokeWidth={sw} fill="none"/><circle cx="12" cy="14" r="2" fill={stroke}/></>,
    journal: <><rect x="4" y="3" width="16" height="18" rx="2" stroke={stroke} strokeWidth={sw} fill="none"/><path d="M8 8h8M8 12h8M8 16h5" stroke={stroke} strokeWidth={sw} strokeLinecap="round"/></>,
    settings: <><circle cx="12" cy="12" r="3" stroke={stroke} strokeWidth={sw} fill="none"/><path d="M19 12a7 7 0 0 0-.2-1.7l2-1.5-2-3.4-2.4.9a7 7 0 0 0-3-1.7L13 2h-2l-.4 2.6a7 7 0 0 0-3 1.7l-2.4-.9-2 3.4 2 1.5A7 7 0 0 0 5 12c0 .6.1 1.1.2 1.7l-2 1.5 2 3.4 2.4-.9a7 7 0 0 0 3 1.7L11 22h2l.4-2.6a7 7 0 0 0 3-1.7l2.4.9 2-3.4-2-1.5c.1-.6.2-1.1.2-1.7Z" stroke={stroke} strokeWidth={sw} fill="none"/></>,
    bell: <><path d="M12 3a6 6 0 0 0-6 6v3l-2 3h16l-2-3V9a6 6 0 0 0-6-6Z" stroke={stroke} strokeWidth={sw} fill="none"/><path d="M10 18a2 2 0 0 0 4 0" stroke={stroke} strokeWidth={sw}/></>,
    moon: <><path d="M20 14.5A8 8 0 0 1 9.5 4a8 8 0 1 0 10.5 10.5Z" stroke={stroke} strokeWidth={sw} fill="none"/></>,
    sun: <><circle cx="12" cy="12" r="4" stroke={stroke} strokeWidth={sw} fill="none"/><path d="M12 3v2M12 19v2M3 12h2M19 12h2M5.6 5.6l1.4 1.4M17 17l1.4 1.4M5.6 18.4 7 17M17 7l1.4-1.4" stroke={stroke} strokeWidth={sw} strokeLinecap="round"/></>,
    logout: <><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4M16 17l5-5-5-5M21 12H9" stroke={stroke} strokeWidth={sw} fill="none" strokeLinecap="round" strokeLinejoin="round"/></>,
    plus: <><path d="M12 5v14M5 12h14" stroke={stroke} strokeWidth={sw} strokeLinecap="round"/></>,
    x: <><path d="M6 6l12 12M18 6L6 18" stroke={stroke} strokeWidth={sw} strokeLinecap="round"/></>,
    play: <><path d="M6 4l14 8-14 8V4Z" fill={stroke}/></>,
    pause: <><rect x="6" y="4" width="4" height="16" fill={stroke}/><rect x="14" y="4" width="4" height="16" fill={stroke}/></>,
    refresh: <><path d="M3 12a9 9 0 0 1 15.5-6.5L21 8M21 4v4h-4M21 12a9 9 0 0 1-15.5 6.5L3 16M3 20v-4h4" stroke={stroke} strokeWidth={sw} fill="none" strokeLinecap="round"/></>,
    chevron: <><path d="M6 9l6 6 6-6" stroke={stroke} strokeWidth={sw} fill="none" strokeLinecap="round"/></>,
    wallet: <><rect x="3" y="6" width="18" height="14" rx="2" stroke={stroke} strokeWidth={sw} fill="none"/><path d="M3 10h18M16 15h2" stroke={stroke} strokeWidth={sw} strokeLinecap="round"/></>,
    storm: <><path d="M13 2L4 14h7l-2 8 10-13h-7l1-7Z" stroke={stroke} strokeWidth={sw} fill="none" strokeLinejoin="round"/></>,
    search: <><circle cx="11" cy="11" r="7" stroke={stroke} strokeWidth={sw} fill="none"/><path d="M21 21l-5-5" stroke={stroke} strokeWidth={sw} strokeLinecap="round"/></>,
    futures: <><path d="M4 18l5-7 4 5 7-9" stroke={stroke} strokeWidth={sw} fill="none" strokeLinecap="round" strokeLinejoin="round"/><circle cx="9" cy="11" r="1.5" fill={stroke}/><circle cx="13" cy="16" r="1.5" fill={stroke}/><circle cx="20" cy="7" r="1.5" fill={stroke}/></>,
    spot: <><circle cx="12" cy="12" r="9" stroke={stroke} strokeWidth={sw} fill="none"/><text x="12" y="16" textAnchor="middle" fontSize="11" fontWeight="700" fill={stroke}>$</text></>,
    robot: <><rect x="5" y="8" width="14" height="11" rx="3" stroke={stroke} strokeWidth={sw} fill="none"/><circle cx="9.5" cy="13" r="1.6" fill={stroke}/><circle cx="14.5" cy="13" r="1.6" fill={stroke}/><path d="M12 4v4M9 17h6" stroke={stroke} strokeWidth={sw} strokeLinecap="round"/><path d="M3 12h2M19 12h2" stroke={stroke} strokeWidth={sw} strokeLinecap="round"/></>,
    fire: <><path d="M12 2c2 3 4 5 4 9a4 4 0 1 1-8 0c0-2 1-3 2-5-3 2-5 5-5 9a7 7 0 0 0 14 0c0-6-3-9-7-13Z" stroke={stroke} strokeWidth={sw} fill="none" strokeLinejoin="round"/></>,
    shield: <><path d="M12 2l8 4v6c0 5-3.5 9-8 10-4.5-1-8-5-8-10V6l8-4Z" stroke={stroke} strokeWidth={sw} fill="none" strokeLinejoin="round"/></>,
    warning: <><path d="M12 3L2 21h20L12 3Z" stroke={stroke} strokeWidth={sw} fill="none" strokeLinejoin="round"/><path d="M12 10v5M12 17.5v0.5" stroke={stroke} strokeWidth={sw} strokeLinecap="round"/></>,
    target: <><circle cx="12" cy="12" r="9" stroke={stroke} strokeWidth={sw} fill="none"/><circle cx="12" cy="12" r="5" stroke={stroke} strokeWidth={sw} fill="none"/><circle cx="12" cy="12" r="1.5" fill={stroke}/></>,
    download: <><path d="M12 3v12m0 0l-5-5m5 5l5-5M4 21h16" stroke={stroke} strokeWidth={sw} fill="none" strokeLinecap="round" strokeLinejoin="round"/></>,
    forward: <><path d="M7 7l5 5-5 5M13 7l5 5-5 5" stroke={stroke} strokeWidth={sw} fill="none" strokeLinecap="round" strokeLinejoin="round"/></>,
    crown: <><path d="M3 18l2-10 5 4 2-7 2 7 5-4 2 10z" stroke={stroke} strokeWidth={sw} fill="none" strokeLinejoin="round"/><path d="M3 21h18" stroke={stroke} strokeWidth={sw} strokeLinecap="round"/></>,
    moonStar: <><path d="M20 14.5A8 8 0 0 1 9.5 4a8 8 0 1 0 10.5 10.5Z" stroke={stroke} strokeWidth={sw} fill="none"/><path d="M16 5l0.7 1.5L18 7l-1.3 0.5L16 9l-0.7-1.5L14 7l1.3-0.5z" stroke={stroke} strokeWidth={sw} fill={stroke}/></>,
    mail: <><rect x="3" y="5" width="18" height="14" rx="2" stroke={stroke} strokeWidth={sw} fill="none"/><path d="M3 7l9 7 9-7" stroke={stroke} strokeWidth={sw} fill="none"/></>,
    trash: <><path d="M4 7h16M9 7V4h6v3M6 7l1 13a2 2 0 0 0 2 2h6a2 2 0 0 0 2-2l1-13M10 11v6M14 11v6" stroke={stroke} strokeWidth={sw} fill="none" strokeLinecap="round" strokeLinejoin="round"/></>,
    edit: <><path d="M4 20h4l11-11-4-4L4 16v4z" stroke={stroke} strokeWidth={sw} fill="none" strokeLinejoin="round"/></>,
    check: <><path d="M4 12l5 5L20 6" stroke={stroke} strokeWidth={sw + 0.4} fill="none" strokeLinecap="round" strokeLinejoin="round"/></>,
    money: <><rect x="2" y="6" width="20" height="12" rx="2" stroke={stroke} strokeWidth={sw} fill="none"/><circle cx="12" cy="12" r="3" stroke={stroke} strokeWidth={sw} fill="none"/><path d="M5 12h0.01M19 12h0.01" stroke={stroke} strokeWidth={sw + 0.3} strokeLinecap="round"/></>,
  };
  return (
    <svg width={s} height={s} viewBox="0 0 24 24" fill="none" {...p}>
      {paths[name] || null}
    </svg>
  );
};

// ───────────────────────── Toast manager ─────────────────────────
const useToasts = () => {
  const [toasts, setToasts] = useState([]);
  const push = useCallback((t) => {
    const id = Math.random().toString(36).slice(2);
    const kind = t.err ? "error" : t.ok ? "success" : t.warn ? "warn" : "info";
    const msg = typeof t === "string" ? t : t.msg || "";
    setToasts(prev => [...prev, { id, msg, kind }]);
    setTimeout(() => setToasts(prev => prev.filter(x => x.id !== id)), 4000);
  }, []);
  const ToastStack = () => (
    <div className="d-toast-stack">
      {toasts.map(t => (
        <div key={t.id} className={`d-toast ${t.kind}`}>{t.msg}</div>
      ))}
    </div>
  );
  return { push, ToastStack };
};

// ───────────────────────── Sidebar ─────────────────────────
const DesktopSidebar = ({ active, onNavigate, user, onLogout, collapsed, onToggle, counts }) => {
  const items = [
    { id: "dashboard", label: "Главная", icon: "dashboard" },
    { id: "bots",      label: "Боты",    icon: "bot",     badge: counts.runningBots, badgeKind: counts.runningBots > 0 ? "live" : null },
    { id: "spot",      label: "Спот",    icon: "wallet" },
    { id: "signals",   label: "Сигналы", icon: "signal",  badge: counts.signals24h, badgeKind: counts.signals24h > 0 ? "live" : null },
    { id: "journal",   label: "Журнал",  icon: "journal" },
    { id: "stats",     label: "Статистика", icon: "chart" },
  ];
  const bottom = [
    ...(user?.role === "admin" ? [{ id: "admin", label: "🛡 Админка", icon: "settings" }] : []),
    { id: "settings",  label: "Настройки", icon: "settings" },
  ];
  const initials = (user?.email || "?").slice(0, 1).toUpperCase();
  return (
    <aside className="d-sidebar">
      <div className="d-logo" onClick={onToggle} style={{ cursor: "pointer" }} title="Свернуть боковую панель">
        <div className="d-logo-dot">A4</div>
        <div className="d-logo-text">API4ATKA</div>
      </div>
      <nav className="d-nav">
        <div className="d-nav-section">Торговля</div>
        {items.map(it => (
          <div key={it.id}
               className={"d-nav-item" + (active === it.id ? " active" : "")}
               onClick={() => onNavigate(it.id)}>
            <span className="d-nav-icon"><DIcon name={it.icon} size={18}/></span>
            <span className="d-nav-label">{it.label}</span>
            {it.badge != null && it.badge > 0 && (
              <span className={"d-nav-badge" + (it.badgeKind ? " " + it.badgeKind : "")}>{it.badge}</span>
            )}
          </div>
        ))}
        <div className="d-nav-section">Система</div>
        {bottom.map(it => (
          <div key={it.id}
               className={"d-nav-item" + (active === it.id ? " active" : "")}
               onClick={() => onNavigate(it.id)}>
            <span className="d-nav-icon"><DIcon name={it.icon} size={18}/></span>
            <span className="d-nav-label">{it.label}</span>
          </div>
        ))}
      </nav>
      <ProfileFoot user={user} initials={initials} onLogout={onLogout} onNavigate={onNavigate}/>
    </aside>
  );
};

// ── Profile dropdown в sidebar bottom ──
const ProfileFoot = ({ user, initials, onLogout, onNavigate }) => {
  const [open, setOpen] = useState(false);
  const ref = useRef(null);
  useEffect(() => {
    const onClick = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    if (open) document.addEventListener("mousedown", onClick);
    return () => document.removeEventListener("mousedown", onClick);
  }, [open]);
  const setTheme = (t) => {
    document.documentElement.setAttribute("data-theme", t);
    try { localStorage.setItem("alpha_theme", t); } catch {}
    setOpen(false);
  };
  const setLang = (l) => {
    try { localStorage.setItem("alpha_lang", l); } catch {}
    if (window.setUiLang) window.setUiLang(l);
    setOpen(false);
  };
  const curTheme = document.documentElement.getAttribute("data-theme") || "dark";
  const curLang = (() => { try { return localStorage.getItem("alpha_lang") || "ru"; } catch { return "ru"; } })();
  return (
    <div ref={ref} style={{ position: "relative" }}>
      {open && (
        <div style={{
          position: "absolute", bottom: "100%", left: 8, right: 8, marginBottom: 8,
          background: "var(--d-bg-2)", border: "1px solid var(--d-line-2)", borderRadius: 10,
          boxShadow: "0 12px 32px rgba(0,0,0,0.5)", padding: 8, zIndex: 100,
        }}>
          <div style={{ padding: "8px 10px", borderBottom: "1px solid var(--d-line)", marginBottom: 6 }}>
            <div style={{ fontWeight: 600, fontSize: 12.5 }}>{user?.email}</div>
            <div className="muted" style={{ fontSize: 10, marginTop: 2 }}>{user?.plan_tier || "free"} plan · {user?.role || "user"}</div>
          </div>

          <div style={{ padding: "6px 8px", fontSize: 11, color: "var(--d-text-3)", textTransform: "uppercase", letterSpacing: "0.05em" }}>Тема</div>
          <div className="d-seg" style={{ width: "100%", marginBottom: 6 }}>
            <button className={"d-seg-btn" + (curTheme === "dark" ? " active" : "")} style={{ flex: 1 }} onClick={() => setTheme("dark")}>🌙 Тёмная</button>
            <button className={"d-seg-btn" + (curTheme === "light" ? " active" : "")} style={{ flex: 1 }} onClick={() => setTheme("light")}>☀ Светлая</button>
          </div>

          <div style={{ padding: "6px 8px", fontSize: 11, color: "var(--d-text-3)", textTransform: "uppercase", letterSpacing: "0.05em" }}>Язык</div>
          <div className="d-seg" style={{ width: "100%", marginBottom: 8 }}>
            <button className={"d-seg-btn" + (curLang === "ru" ? " active" : "")} style={{ flex: 1 }} onClick={() => setLang("ru")}>RU</button>
            <button className={"d-seg-btn" + (curLang === "en" ? " active" : "")} style={{ flex: 1 }} onClick={() => setLang("en")}>EN</button>
          </div>

          <button className="d-btn d-btn-ghost" style={{ width: "100%", justifyContent: "flex-start" }}
                  onClick={() => { setOpen(false); onNavigate("settings"); }}>
            ⚙ Настройки аккаунта
          </button>
          <button className="d-btn d-btn-danger" style={{ width: "100%", marginTop: 6, justifyContent: "center" }} onClick={onLogout}>
            <DIcon name="logout" size={12}/> Выйти
          </button>
        </div>
      )}
      <div className="d-sidebar-foot" onClick={() => setOpen(o => !o)}>
        <div className="d-avatar">{initials}</div>
        <div className="d-sidebar-foot-meta">
          <div className="d-sidebar-foot-name">{user?.email || "Гость"}</div>
          <div className="d-sidebar-foot-mail">{user?.plan_tier || "free"} · ⌃ открыть</div>
        </div>
      </div>
    </div>
  );
};

// ───────────────────────── Header ─────────────────────────
const SUPPORTED_EX = ["weex", "okx", "binance", "bybit"];

const RefreshRing = ({ seconds, total = 60 }) => {
  const r = 7;
  const c = 2 * Math.PI * r;
  const offset = c * (1 - Math.max(0, seconds) / total);
  return (
    <svg width="20" height="20" viewBox="0 0 20 20" style={{ flexShrink: 0 }}>
      <circle cx="10" cy="10" r={r} fill="none" stroke="var(--d-bg-4)" strokeWidth="1.6"/>
      <circle cx="10" cy="10" r={r} fill="none" stroke="var(--d-accent)" strokeWidth="1.6"
              strokeDasharray={c} strokeDashoffset={offset}
              strokeLinecap="round"
              transform="rotate(-90 10 10)"
              style={{ transition: "stroke-dashoffset 0.5s linear" }}/>
    </svg>
  );
};

const DesktopHeader = ({ title, exchange, onExchangeChange, exReady, theme, onToggleTheme, onOpenStorm, stormActive, onRefresh, refreshing, nextRefreshIn }) => {
  return (
    <header className="d-header">
      <div className="d-header-title">{title}</div>
      <div className="d-header-tools">
        <div className="d-ex-switch">
          {SUPPORTED_EX.map(ex => (
            <button key={ex}
                    className={"d-ex-chip" + (exchange === ex ? " active" : "")}
                    onClick={() => onExchangeChange(ex)}
                    title={exReady[ex] ? "Подключён" : "Нет API-ключа"}>
              <span className="d-ex-chip-dot" style={{ background: exReady[ex] ? "var(--d-success)" : "var(--d-text-3)" }}/>
              {ex}
            </button>
          ))}
        </div>
        <div style={{ display: "flex", alignItems: "center", gap: 6,
                      padding: "4px 10px", borderRadius: 8,
                      background: "var(--d-bg-2)", border: "1px solid var(--d-line)",
                      fontSize: 11, color: "var(--d-text-2)", fontFamily: "var(--d-font-mono)" }}
             title="Авто-обновление каждые 60с">
          <RefreshRing seconds={nextRefreshIn}/>
          <span className="mono">{nextRefreshIn}s</span>
        </div>
        <button className="d-icon-btn" onClick={onRefresh} title="Обновить сейчас" disabled={refreshing}>
          {refreshing ? <span className="d-spinner"/> : <DIcon name="refresh" size={16}/>}
        </button>
        {window.DesktopExtras?.NotificationsBell && <window.DesktopExtras.NotificationsBell/>}
        <button className={"d-icon-btn" + (stormActive ? " active" : "")}
                onClick={onOpenStorm} title="Storm mode — паник-кнопка"
                style={stormActive ? { borderColor: "var(--d-danger)", color: "var(--d-danger)" } : {}}>
          <DIcon name="storm" size={16}/>
          {stormActive && <span className="d-icon-btn-dot"/>}
        </button>
        <button className="d-icon-btn" onClick={onToggleTheme} title={theme === "dark" ? "Светлая тема" : "Тёмная тема"}>
          <DIcon name={theme === "dark" ? "sun" : "moon"} size={16}/>
        </button>
      </div>
    </header>
  );
};

// ───────────────────────── Storm modal ─────────────────────────
const StormModal = ({ open, onClose, onConfirm, stormActive, untilMs }) => {
  if (!open) return null;
  const minsLeft = stormActive && untilMs ? Math.max(0, Math.round((untilMs - Date.now()) / 60000)) : 0;
  return (
    <div className="d-modal-backdrop" onClick={onClose}>
      <div className="d-modal" onClick={e => e.stopPropagation()}>
        <div className="d-modal-head">
          <div className="d-modal-title">⚡ Storm mode</div>
          <button className="d-icon-btn" onClick={onClose}><DIcon name="x" size={14}/></button>
        </div>
        <div className="d-modal-body">
          {stormActive ? (
            <>
              <p>Storm mode <b style={{ color: "var(--d-danger)" }}>активен</b>. Все боты остановлены, новые ордера блокируются.</p>
              <p className="muted">До автоматического отключения: <b>{minsLeft} мин</b></p>
            </>
          ) : (
            <>
              <p>Включить Storm mode на <b>60 минут</b>:</p>
              <ul style={{ paddingLeft: 18, margin: "10px 0", lineHeight: 1.8, fontSize: 12, color: "var(--d-text-1)" }}>
                <li>Остановит ВСЕ активные локальные боты</li>
                <li>Заблокирует автоматическое исполнение сигналов</li>
                <li>Не закрывает уже открытые позиции (нужно вручную)</li>
              </ul>
              <p className="muted" style={{ fontSize: 11 }}>Storm можно отменить досрочно повторным нажатием.</p>
            </>
          )}
        </div>
        <div className="d-modal-foot">
          <button className="d-btn d-btn-ghost" onClick={onClose}>Отмена</button>
          <button className={"d-btn " + (stormActive ? "" : "d-btn-danger")}
                  onClick={() => { onConfirm(); onClose(); }}>
            {stormActive ? "Отключить Storm" : "⚡ Включить Storm"}
          </button>
        </div>
      </div>
    </div>
  );
};

// ───────────────────────── Root DesktopApp ─────────────────────────
const DesktopApp = ({ user, setUser, onLogout }) => {
  // Биржа
  const [exchange, setExchange] = useState(() => window.creds.active());
  const [exReady, setExReady] = useState(() => window.creds.readyMap());
  useEffect(() => {
    const onUpd = () => setExReady(window.creds.readyMap());
    window.addEventListener("creds-updated", onUpd);
    return () => window.removeEventListener("creds-updated", onUpd);
  }, []);

  // Тема
  const [theme, setTheme] = useState(() => {
    try { return localStorage.getItem("alpha_theme") || "dark"; } catch { return "dark"; }
  });
  useEffect(() => {
    const eff = theme === "auto"
      ? (window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light")
      : theme;
    document.documentElement.setAttribute("data-theme", eff);
    try { localStorage.setItem("alpha_theme", theme); } catch {}
  }, [theme]);

  // Sidebar collapse
  const [collapsed, setCollapsed] = useState(() => {
    try { return localStorage.getItem("dapp_sidebar_collapsed") === "1"; } catch { return false; }
  });
  useEffect(() => {
    try { localStorage.setItem("dapp_sidebar_collapsed", collapsed ? "1" : "0"); } catch {}
  }, [collapsed]);

  // Активный экран
  const [screen, setScreen] = useState("dashboard");

  // Тосты
  const { push: pushToast, ToastStack } = useToasts();

  // Storm mode
  const [stormOpen, setStormOpen] = useState(false);
  const [stormUntil, setStormUntil] = useState(0);
  const loadStorm = useCallback(async () => {
    try {
      const r = await window.MobileAPI.loadStormStatus();
      setStormUntil(Number(r?.storm_until_ms || 0));
    } catch {}
  }, []);
  useEffect(() => { loadStorm(); const t = setInterval(loadStorm, 30000); return () => clearInterval(t); }, [loadStorm]);
  const stormActive = stormUntil > Date.now();
  const toggleStorm = async () => {
    try {
      await window.MobileAPI.setStormMode(stormActive ? 0 : 60);
      await loadStorm();
      pushToast({ msg: stormActive ? "Storm отключён" : "⚡ Storm включён на 60 мин", warn: !stormActive, ok: stormActive });
    } catch (e) {
      pushToast({ msg: "Не удалось переключить Storm: " + (e.message || e), err: true });
    }
  };

  // Refresh всех экранов — broadcast event + auto каждые 60с
  const [refreshTick, setRefreshTick] = useState(0);
  const [refreshing, setRefreshing] = useState(false);
  const [nextRefreshIn, setNextRefreshIn] = useState(60);
  const handleRefresh = async () => {
    setRefreshing(true);
    setRefreshTick(t => t + 1);
    setNextRefreshIn(60);
    setTimeout(() => setRefreshing(false), 600);
  };
  useEffect(() => {
    const id = setInterval(() => {
      setNextRefreshIn(prev => {
        if (prev <= 1) {
          setRefreshing(true);
          setRefreshTick(t => t + 1);
          setTimeout(() => setRefreshing(false), 500);
          return 60;
        }
        return prev - 1;
      });
    }, 1000);
    return () => clearInterval(id);
  }, []);

  // Счётчики для бейджей в sidebar
  const [counts, setCounts] = useState({ runningBots: 0, signals24h: 0 });
  const refreshCounts = useCallback(async () => {
    try {
      const bots = await window.MobileAPI.listLocalBots();
      const running = (bots || []).filter(b => ["running", "paused", "starting"].includes(b.state)).length;
      setCounts(c => ({ ...c, runningBots: running }));
    } catch {}
  }, []);
  useEffect(() => { refreshCounts(); }, [refreshCounts, refreshTick]);

  // Заголовок страницы
  const screenTitles = {
    dashboard: "Главная",
    bots: "Торговые боты",
    spot: "Спот",
    signals: "Сигналы и каналы",
    journal: "Журнал сделок",
    stats: "Статистика",
    settings: "Настройки",
    admin: "Админ-панель",
  };

  // Контекст для экранов
  const screenProps = {
    exchange, exReady,
    pushToast, refreshTick,
    user,
    nextRefreshIn,
  };

  const Screen = (window.DesktopScreens && window.DesktopScreens[screen]) || (() => (
    <div className="d-empty">
      <div className="d-empty-icon"><DIcon name="settings" size={28}/></div>
      <div className="d-empty-title">Экран в разработке</div>
      <div className="d-empty-msg">Этот раздел ещё переносится с мобильной версии.</div>
    </div>
  ));

  return (
    <>
      <div className={"d-shell" + (collapsed ? " collapsed" : "")}>
        <DesktopSidebar
          active={screen}
          onNavigate={setScreen}
          user={user}
          onLogout={onLogout}
          collapsed={collapsed}
          onToggle={() => setCollapsed(c => !c)}
          counts={counts}
        />
        <DesktopHeader
          title={screenTitles[screen] || ""}
          exchange={exchange}
          onExchangeChange={(ex) => { setExchange(ex); window.creds.setActive(ex); }}
          exReady={exReady}
          theme={theme}
          onToggleTheme={() => setTheme(t => (t === "dark" ? "light" : "dark"))}
          onOpenStorm={() => setStormOpen(true)}
          stormActive={stormActive}
          onRefresh={handleRefresh}
          refreshing={refreshing}
          nextRefreshIn={nextRefreshIn}
        />
        <main className="d-main">
          <Screen {...screenProps}/>
        </main>
      </div>

      <StormModal
        open={stormOpen}
        onClose={() => setStormOpen(false)}
        onConfirm={toggleStorm}
        stormActive={stormActive}
        untilMs={stormUntil}
      />
      <ToastStack/>
    </>
  );
};

// Экспорт для использования в app.jsx
window.DesktopApp = DesktopApp;
window.DesktopIcons = { DIcon };
window.DesktopShellHelpers = { useToasts };

})();  // конец IIFE-обёртки
