/* eslint-disable */
/**
 * Desktop Pro Trading Dark — Extra modals & utility components.
 *
 * Регистрирует на window.DesktopExtras:
 *   - LocalBotDetailsModal — детали локального бота (state.fills, levels, pos, manual safety)
 *   - BasketCreateForm — Recurring Basket bot form
 *   - TelegramConnectWizard — полный SMS-флоу (api_id/hash → код → 2FA)
 *   - MultiAccountManager — ключи бирж с label (default / sub1 / sub2)
 *   - NotificationsBell — dropdown в Header
 *
 * IIFE-wrap по причине Babel-standalone глобал scope.
 */
(function () {
const { useState, useEffect, useCallback, useMemo, useRef } = React;
const DIcon = (window.DesktopIcons && window.DesktopIcons.DIcon) || (() => null);

const fmt = (n, d = 2) => {
  const v = Number(n);
  if (!isFinite(v)) return "—";
  return v.toLocaleString("ru-RU", { minimumFractionDigits: d, maximumFractionDigits: d });
};
const fmtPx = (n) => {
  const v = Number(n);
  if (!isFinite(v) || v === 0) return "—";
  if (v > 100) return v.toLocaleString("ru-RU", { maximumFractionDigits: 2 });
  if (v > 1) return v.toLocaleString("ru-RU", { maximumFractionDigits: 4 });
  return v.toPrecision(5);
};
const pctClass = (v) => (Number(v) >= 0 ? "pos" : "neg");
const ago = (ms) => {
  if (!ms) return "—";
  const s = Math.round((Date.now() - ms) / 1000);
  if (s < 60) return s + "с";
  if (s < 3600) return Math.round(s / 60) + "м";
  if (s < 86400) return Math.round(s / 3600) + "ч";
  return Math.round(s / 86400) + "д";
};

// ─────────────────────  LocalBotDetailsModal  ─────────────────────
const LocalBotDetailsModal = ({ botId, onClose, onReload, pushToast }) => {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [tab, setTab] = useState("overview");
  const [manualBusy, setManualBusy] = useState(false);

  const load = useCallback(async () => {
    setLoading(true);
    try {
      const r = await window.MobileAPI.loadLocalBotDetails(botId);
      setData(r);
    } catch (e) {
      pushToast({ msg: "Не удалось загрузить детали: " + (e.message || e), err: true });
    }
    setLoading(false);
  }, [botId, pushToast]);
  useEffect(() => { load(); }, [load]);

  const manualSafety = async () => {
    setManualBusy(true);
    try {
      const r = await window.MobileAPI.dcaManualSafety(botId);
      pushToast({ msg: r?.detail || "Страховочный ордер добавлен", ok: true });
      await load();
      if (onReload) onReload();
    } catch (e) {
      pushToast({ msg: "Ошибка: " + (e.message || e).slice(0, 120), err: true });
    }
    setManualBusy(false);
  };

  if (loading || !data) {
    return (
      <div className="d-modal-backdrop" onClick={onClose}>
        <div className="d-modal wide" onClick={e => e.stopPropagation()}>
          <div className="d-modal-head">
            <div className="d-modal-title">Загрузка…</div>
            <button className="d-icon-btn" onClick={onClose}><DIcon name="x" size={14}/></button>
          </div>
          <div className="d-modal-body" style={{ minHeight: 200 }}>
            <div style={{ display: "grid", placeItems: "center", height: 200 }}>
              <span className="d-spinner"/>
            </div>
          </div>
        </div>
      </div>
    );
  }

  const bot = data.bot || {};
  const cfg = data.config || {};
  const state = data.state || {};
  const fills = data.fills || state.fills || [];
  const mark = Number(data.mark_px || state.last_mark || 0);
  const avg = Number(state.avg_entry || 0);
  const totalQty = Number(state.total_qty || 0);
  const investment = Number(bot.investment_usdt || 0);
  const lev = Number(bot.leverage || 1);
  const isLong = String(bot.direction || "long").toLowerCase() === "long";

  // Маржа: position margin (то что реально используется) и резерв
  // Position margin = notional / leverage (минимум что нужно для позиции)
  const notional = avg > 0 && totalQty > 0 ? avg * totalQty : 0;
  const positionMargin = lev > 0 ? notional / lev : 0;
  const reservedMargin = Math.max(0, investment - positionMargin);

  const upnl = avg > 0 && mark > 0 && totalQty > 0
    ? (mark - avg) * totalQty * (isLong ? 1 : -1) : 0;
  const upnlPct = investment > 0 ? (upnl / investment * 100) : 0;

  // Корректная цена ликвидации с учётом ВСЕЙ investment как буфер маржи.
  // При cross/auto-reserve margin OKX-style: max loss = inv, liq когда uPnL = -inv.
  // liq_price = entry ± inv/qty (с учётом maint margin 0.5%)
  const maintRate = 0.005;
  let liqPrice = 0;
  if (avg > 0 && totalQty > 0 && investment > 0) {
    const maxLossPerCoin = (investment * (1 - maintRate)) / totalQty;
    liqPrice = isLong
      ? Math.max(0, avg - maxLossPerCoin)
      : avg + maxLossPerCoin;
  }

  // Время работы
  const startMs = Number(bot.started_at || bot.created_at || 0);
  const uptimeMs = startMs > 0 ? Date.now() - startMs : 0;
  const uptimeStr = (() => {
    if (!uptimeMs) return "—";
    const days = Math.floor(uptimeMs / 86400000);
    const hours = Math.floor((uptimeMs % 86400000) / 3600000);
    const mins = Math.floor((uptimeMs % 3600000) / 60000);
    if (days > 0) return `${days}д ${hours}ч`;
    if (hours > 0) return `${hours}ч ${mins}м`;
    return `${mins}м`;
  })();

  const levels = state.levels || [];

  // Grid profits = realized PnL от FILLED уровней
  const gridCycles = Number(state.cycles_done || 0);
  const gridProfits = Number(state.grid_realized_pnl || bot.total_pnl || 0);
  // Реализованные пары buy/sell для Grid = trades_count (каждая пара = 1 cycle)
  const filledLevels = levels.filter(l => l.state === "FILLED" || l.state === "FINISHED").length;

  const reachedMaxSafety = bot.bot_type === "dca" &&
    (fills.filter(f => f.type === "safety").length >= (cfg.max_safety_orders || 0));

  return (
    <div className="d-modal-backdrop" onClick={onClose}>
      <div className="d-modal wide" onClick={e => e.stopPropagation()} style={{ maxWidth: 880 }}>
        <div className="d-modal-head">
          <div className="d-modal-title" style={{ display: "flex", alignItems: "center", gap: 10 }}>
            <div style={{ width: 32, height: 32, borderRadius: 8, background: "var(--d-bg-3)",
                          display: "grid", placeItems: "center", color: "var(--d-accent)" }}>
              <DIcon name="bot" size={16}/>
            </div>
            <div>
              <div>{bot.symbol} <span className="d-badge" style={{ marginLeft: 6 }}>{(bot.bot_type || "").toUpperCase()}</span></div>
              <div className="muted mono" style={{ fontSize: 10, fontWeight: 400 }}>
                #{bot.id} · {(bot.exchange || "").toUpperCase()} · {bot.direction} · {bot.leverage}x
              </div>
            </div>
          </div>
          <button className="d-icon-btn" onClick={onClose}><DIcon name="x" size={14}/></button>
        </div>
        <div className="d-modal-body" style={{ padding: 0 }}>
          {/* Tabs */}
          <div className="d-tabs" style={{ padding: "0 18px", marginBottom: 0 }}>
            <button className={"d-tab" + (tab === "overview" ? " active" : "")} onClick={() => setTab("overview")}>Обзор</button>
            <button className={"d-tab" + (tab === "fills" ? " active" : "")} onClick={() => setTab("fills")}>
              Ордера <span className="d-tab-count">{fills.length}</span>
            </button>
            {bot.bot_type === "grid" && (
              <button className={"d-tab" + (tab === "levels" ? " active" : "")} onClick={() => setTab("levels")}>
                Уровни <span className="d-tab-count">{levels.length}</span>
              </button>
            )}
            <button className={"d-tab" + (tab === "params" ? " active" : "")} onClick={() => setTab("params")}>Параметры</button>
          </div>

          <div style={{ padding: "16px 18px" }}>
            {tab === "overview" && (
              <>
                {/* Топ-стрип: PnL + время работы (OKX-style) */}
                <div style={{ display: "grid", gridTemplateColumns: "2fr 1fr 1fr", gap: 10, marginBottom: 14 }}>
                  <div className="d-card" style={{ padding: 14 }}>
                    <div className="d-kpi-label">Общий PnL ({(bot.exchange || "").toUpperCase()})</div>
                    <div className={"d-kpi-value mono " + pctClass(upnl + gridProfits)}>
                      {(upnl + gridProfits) >= 0 ? "+" : ""}{fmt(upnl + gridProfits)} USDT
                    </div>
                    <div className={"d-kpi-sub mono " + pctClass(upnlPct)} style={{ fontSize: 11.5 }}>
                      {(upnlPct >= 0 ? "+" : "") + upnlPct.toFixed(2)}% от инвестиций
                    </div>
                  </div>
                  <div className="d-card" style={{ padding: 14 }}>
                    <div className="d-kpi-label">Время работы</div>
                    <div className="d-kpi-value mono" style={{ fontSize: 18 }}>{uptimeStr}</div>
                    <div className="d-kpi-sub" style={{ fontSize: 11 }}>
                      {bot.bot_type === "grid" ? `${gridCycles} циклов` :
                       bot.bot_type === "dca" ? `${gridCycles} циклов` :
                       `${gridCycles} закупок`}
                    </div>
                  </div>
                  <div className="d-card" style={{ padding: 14 }}>
                    <div className="d-kpi-label">Прибыль с сетки</div>
                    <div className={"d-kpi-value mono " + pctClass(gridProfits)} style={{ fontSize: 18 }}>
                      {gridProfits >= 0 ? "+" : ""}{fmt(gridProfits)}
                    </div>
                    <div className="d-kpi-sub" style={{ fontSize: 11 }}>{bot.trades_count || 0} сделок</div>
                  </div>
                </div>

                <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14, marginBottom: 14 }}>
                  <div className="d-card" style={{ padding: 14 }}>
                    <div className="d-label">Текущая позиция</div>
                    <div className="d-stat"><span className="d-stat-label">Mark цена</span><span className="d-stat-val mono">{fmtPx(mark)}</span></div>
                    <div className="d-stat"><span className="d-stat-label">Средняя вход</span><span className="d-stat-val mono">{fmtPx(avg)}</span></div>
                    <div className="d-stat"><span className="d-stat-label">Размер</span><span className="d-stat-val mono">{fmt(totalQty, 4)}</span></div>
                    <div className="d-stat"><span className="d-stat-label">Нотионал</span><span className="d-stat-val mono">{fmt(notional)} USDT</span></div>
                    <div className="d-stat">
                      <span className="d-stat-label">Нереализ. PnL</span>
                      <span className={"d-stat-val mono " + pctClass(upnl)}>
                        {upnl >= 0 ? "+" : ""}{fmt(upnl)} ({(upnlPct >= 0 ? "+" : "") + upnlPct.toFixed(2)}%)
                      </span>
                    </div>
                    {liqPrice > 0 && (
                      <div className="d-stat">
                        <span className="d-stat-label">Цена ликвидации (~)</span>
                        <span className="d-stat-val mono neg">{fmtPx(liqPrice)}</span>
                      </div>
                    )}
                  </div>

                  <div className="d-card" style={{ padding: 14 }}>
                    <div className="d-label">Маржа</div>
                    <div className="d-stat">
                      <span className="d-stat-label">Инвестиция (вся)</span>
                      <span className="d-stat-val mono">{fmt(investment)} USDT</span>
                    </div>
                    <div className="d-stat">
                      <span className="d-stat-label">Используется на позиции</span>
                      <span className="d-stat-val mono">{fmt(positionMargin)} USDT</span>
                    </div>
                    <div className="d-stat">
                      <span className="d-stat-label">Зарезервировано (буфер)</span>
                      <span className="d-stat-val mono pos">{fmt(reservedMargin)} USDT</span>
                    </div>
                    <div className="d-stat">
                      <span className="d-stat-label">Загрузка</span>
                      <span className="d-stat-val mono">{investment > 0 ? ((positionMargin / investment) * 100).toFixed(1) : 0}%</span>
                    </div>
                    <div className="d-stat">
                      <span className="d-stat-label">Плечо (заявленное)</span>
                      <span className="d-stat-val mono">{lev}x</span>
                    </div>
                    <div className="d-stat">
                      <span className="d-stat-label">Эфф. плечо</span>
                      <span className="d-stat-val mono">{investment > 0 ? (notional / investment).toFixed(2) : "0.00"}x</span>
                    </div>
                  </div>
                </div>

                {/* DCA / Grid прогресс */}
                <div className="d-card" style={{ padding: 14, marginBottom: 14 }}>
                  <div className="d-label">Прогресс {bot.bot_type === "grid" ? "сетки" : "цикла"}</div>
                  <div style={{ display: "grid", gridTemplateColumns: "repeat(4, 1fr)", gap: 12 }}>
                    {bot.bot_type === "grid" && (
                      <>
                        <KpiMini label="Всего уровней" val={levels.length}/>
                        <KpiMini label="В работе (OPEN)" val={levels.filter(l => l.state === "OPEN").length} color="var(--d-accent-2)"/>
                        <KpiMini label="Сработало" val={filledLevels} color="var(--d-success)"/>
                        <KpiMini label="Ошибок" val={levels.filter(l => String(l.state || "").includes("ERROR")).length} color={levels.filter(l => String(l.state || "").includes("ERROR")).length > 0 ? "var(--d-danger)" : undefined}/>
                      </>
                    )}
                    {bot.bot_type === "dca" && (
                      <>
                        <KpiMini label="Страховочных" val={`${fills.filter(f => f.type === "safety").length} / ${cfg.max_safety_orders || 0}`}/>
                        <KpiMini label="Циклов TP" val={gridCycles} color="var(--d-success)"/>
                        {cfg.tp_per_cycle_pct > 0 && avg > 0 && (
                          <KpiMini label="TP цена"
                                   val={fmtPx(isLong ? avg * (1 + cfg.tp_per_cycle_pct / 100) : avg * (1 - cfg.tp_per_cycle_pct / 100))}
                                   color="var(--d-success)"/>
                        )}
                        <KpiMini label="Сделок" val={bot.trades_count || 0}/>
                      </>
                    )}
                    {bot.bot_type === "recurring" && (
                      <>
                        <KpiMini label="Закупок" val={gridCycles}/>
                        <KpiMini label="Символов в корзине" val={(cfg.basket || []).length}/>
                        <KpiMini label="Интервал" val={`${cfg.interval_hours || 168}ч`}/>
                        <KpiMini label="За цикл" val={`${fmt(cfg.amount_per_purchase || 0, 0)} USDT`}/>
                      </>
                    )}
                  </div>
                  {state.last_skip_reason && (
                    <div style={{ marginTop: 12, padding: 10, background: "var(--d-warn-dim)",
                                  borderRadius: 6, fontSize: 11.5, color: "var(--d-warn)" }}>
                      ⚠ Последний skip: <span className="mono">{state.last_skip_reason}</span>
                    </div>
                  )}
                </div>

                {/* Manual safety button — только DCA */}
                {bot.bot_type === "dca" && (
                  <div style={{ padding: 12, background: "var(--d-bg-2)", borderRadius: 8, border: "1px solid var(--d-line)" }}>
                    <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
                      <div style={{ flex: 1 }}>
                        <div style={{ fontWeight: 600, fontSize: 12.5 }}>Ручная докупка</div>
                        <div className="muted" style={{ fontSize: 11, marginTop: 2 }}>
                          {reachedMaxSafety
                            ? "Достигнут max_safety_orders. Можешь добавить ещё страховочный вручную."
                            : "Триггерит следующий страховочный ордер немедленно (без ожидания нужного движения цены)."}
                        </div>
                      </div>
                      <button className="d-btn d-btn-primary" onClick={manualSafety} disabled={manualBusy}>
                        {manualBusy ? <span className="d-spinner"/> : "+ Докупить"}
                      </button>
                    </div>
                  </div>
                )}
              </>
            )}

            {tab === "fills" && (
              <div className="d-card" style={{ padding: 0 }}>
                {fills.length === 0 ? (
                  <div className="d-empty" style={{ padding: 30 }}>
                    <div className="d-empty-msg">Пока нет исполненных ордеров</div>
                  </div>
                ) : (
                  <table className="d-table">
                    <thead>
                      <tr>
                        <th>#</th><th>Тип</th>
                        <th style={{ textAlign: "right" }}>Цена</th>
                        <th style={{ textAlign: "right" }}>Размер</th>
                        <th style={{ textAlign: "right" }}>Маржа</th>
                        <th>Время</th>
                      </tr>
                    </thead>
                    <tbody>
                      {fills.slice().reverse().map((f, i) => (
                        <tr key={i}>
                          <td className="mono muted">{fills.length - i}</td>
                          <td>
                            {f.type === "initial"
                              ? <span className="d-badge d-badge-long">INIT</span>
                              : f.type === "safety"
                                ? <span className="d-badge d-badge-warn">SAFETY #{f.n}</span>
                                : <span className="d-badge">{f.type || "—"}</span>}
                          </td>
                          <td className="mono" style={{ textAlign: "right" }}>{fmtPx(f.price)}</td>
                          <td className="mono" style={{ textAlign: "right" }}>{fmt(f.qty, 4)}</td>
                          <td className="mono" style={{ textAlign: "right" }}>{fmt(f.margin)}</td>
                          <td className="muted" style={{ fontSize: 11 }}>{ago(f.ts)}</td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                )}
              </div>
            )}

            {tab === "levels" && (
              <div className="d-card" style={{ padding: 0 }}>
                {levels.length === 0 ? (
                  <div className="d-empty" style={{ padding: 30 }}>
                    <div className="d-empty-msg">Уровни не инициализированы</div>
                  </div>
                ) : (
                  <table className="d-table">
                    <thead>
                      <tr>
                        <th>#</th>
                        <th style={{ textAlign: "right" }}>Цена</th>
                        <th>Назначение</th>
                        <th>Сторона</th>
                        <th>Статус</th>
                        <th>Ошибка</th>
                      </tr>
                    </thead>
                    <tbody>
                      {levels.map((l, i) => (
                        <tr key={i}>
                          <td className="mono muted">{l.idx ?? i}</td>
                          <td className="mono" style={{ textAlign: "right" }}>{fmtPx(l.price)}</td>
                          <td>
                            <span className="d-badge">{l.purpose || "—"}</span>
                          </td>
                          <td>
                            {l.side ? <span className={"d-badge " + (l.side === "buy" ? "d-badge-long" : "d-badge-short")}>{(l.side || "").toUpperCase()}</span> : "—"}
                          </td>
                          <td>
                            {l.state === "OPEN" && <span className="d-badge d-badge-long">OPEN</span>}
                            {(l.state === "FILLED" || l.state === "FINISHED") && <span className="d-badge d-badge-warn">{l.state}</span>}
                            {String(l.state || "").includes("ERROR") && <span className="d-badge d-badge-short">{l.state}</span>}
                            {!["OPEN", "FILLED", "FINISHED"].includes(l.state) && !String(l.state || "").includes("ERROR") && <span className="d-badge">{l.state || "—"}</span>}
                          </td>
                          <td className="muted" style={{ fontSize: 11 }}>{l.error_reason || "—"}</td>
                        </tr>
                      ))}
                    </tbody>
                  </table>
                )}
              </div>
            )}

            {tab === "params" && (
              <div className="d-card" style={{ padding: 14 }}>
                <div className="d-stat"><span className="d-stat-label">Тип</span><span className="d-stat-val">{bot.bot_type}</span></div>
                <div className="d-stat"><span className="d-stat-label">Направление</span><span className="d-stat-val">{bot.direction}</span></div>
                <div className="d-stat"><span className="d-stat-label">Биржа</span><span className="d-stat-val">{bot.exchange}</span></div>
                <div className="d-stat"><span className="d-stat-label">Инвестиция</span><span className="d-stat-val mono">{fmt(bot.investment_usdt)} USDT</span></div>
                <div className="d-stat"><span className="d-stat-label">Плечо</span><span className="d-stat-val mono">{bot.leverage}x</span></div>
                {Object.keys(cfg).filter(k => !k.startsWith("_")).map(k => (
                  <div className="d-stat" key={k}>
                    <span className="d-stat-label">{k}</span>
                    <span className="d-stat-val mono" style={{ fontSize: 11 }}>{typeof cfg[k] === "object" ? JSON.stringify(cfg[k]) : String(cfg[k])}</span>
                  </div>
                ))}
              </div>
            )}
          </div>
        </div>
      </div>
    </div>
  );
};

// ─────────────────────  Recurring Basket form (used inside BotCreateModal)  ─────────────────────
const BasketCreateForm = ({ basket, setBasket, amount, setAmount, intervalH, setIntervalH }) => {
  const [newSym, setNewSym] = useState("");
  const total = (basket || []).reduce((s, b) => s + (parseFloat(b.percent) || 0), 0);
  const addRow = () => {
    if (!newSym.trim()) return;
    setBasket([...(basket || []), { symbol: newSym.trim().toUpperCase(), percent: 0 }]);
    setNewSym("");
  };
  return (
    <div>
      <div className="d-field">
        <div className="d-label">Корзина токенов ({(basket || []).length})</div>
        {(basket || []).map((b, i) => (
          <div key={i} style={{ display: "flex", gap: 6, marginBottom: 6, alignItems: "center" }}>
            <input className="d-input mono" style={{ flex: 1 }}
                   value={b.symbol} onChange={e => setBasket(basket.map((x, j) => j === i ? { ...x, symbol: e.target.value.toUpperCase() } : x))}/>
            <input className="d-input mono" style={{ width: 80, textAlign: "right" }}
                   value={b.percent}
                   inputMode="decimal"
                   onChange={e => {
                     const v = parseFloat(e.target.value) || 0;
                     setBasket(basket.map((x, j) => j === i ? { ...x, percent: v } : x));
                   }}/>
            <span className="muted" style={{ fontSize: 11, width: 16 }}>%</span>
            <button className="d-btn d-btn-sm d-btn-danger" onClick={() => setBasket(basket.filter((_, j) => j !== i))}>✕</button>
          </div>
        ))}
        <div style={{ display: "flex", gap: 6 }}>
          <input className="d-input mono" style={{ flex: 1 }} placeholder="BTCUSDT"
                 value={newSym} onChange={e => setNewSym(e.target.value.toUpperCase())}
                 onKeyDown={e => { if (e.key === "Enter") addRow(); }}/>
          <button className="d-btn" onClick={addRow}>+ добавить</button>
        </div>
        <div style={{
          marginTop: 8, padding: 6, textAlign: "center",
          background: Math.abs(total - 100) < 0.01 ? "var(--d-success-dim)" : "var(--d-warn-dim)",
          color: Math.abs(total - 100) < 0.01 ? "var(--d-success)" : "var(--d-warn)",
          borderRadius: 6, fontSize: 11.5,
        }}>
          Сумма: <span className="mono">{total.toFixed(1)}%</span> / 100%
        </div>
      </div>

      <div className="d-field">
        <div className="d-label">Сумма за цикл (USDT)</div>
        <input className="d-input mono" value={amount} onChange={e => setAmount(e.target.value)} inputMode="decimal"/>
      </div>
      <div className="d-field">
        <div className="d-label">Интервал (часы)</div>
        <input className="d-input mono" value={intervalH} onChange={e => setIntervalH(e.target.value.replace(/\D/g, ""))}/>
        <div style={{ display: "flex", gap: 4, marginTop: 6 }}>
          {[24, 72, 168, 720].map(h => (
            <button key={h} className="d-btn d-btn-sm"
                    style={{ flex: 1,
                      background: parseInt(intervalH) === h ? "var(--d-accent)" : "",
                      color: parseInt(intervalH) === h ? "white" : "",
                      borderColor: parseInt(intervalH) === h ? "var(--d-accent)" : "" }}
                    onClick={() => setIntervalH(String(h))}>
              {h === 24 ? "1д" : h === 72 ? "3д" : h === 168 ? "1нед" : "1мес"}
            </button>
          ))}
        </div>
      </div>
    </div>
  );
};

// ─────────────────────  Telegram Connect Wizard  ─────────────────────
const TelegramConnectWizard = ({ onClose, onDone, pushToast }) => {
  const [step, setStep] = useState("creds");   // creds | code | password | done
  const [apiId, setApiId] = useState("");
  const [apiHash, setApiHash] = useState("");
  const [phone, setPhone] = useState("");
  const [code, setCode] = useState("");
  const [password, setPassword] = useState("");
  const [busy, setBusy] = useState(false);
  const [forceSms, setForceSms] = useState(false);

  const sendCode = async () => {
    if (!apiId || !apiHash || !phone) {
      pushToast({ msg: "Заполни все поля", err: true });
      return;
    }
    setBusy(true);
    try {
      await window.MobileAPI.tgSendCode(apiId, apiHash, phone, forceSms);
      setStep("code");
      pushToast({ msg: "Код отправлен — проверь Telegram или SMS", ok: true });
    } catch (e) {
      pushToast({ msg: "Ошибка: " + (e.message || e).slice(0, 200), err: true });
    }
    setBusy(false);
  };

  const verifyCode = async () => {
    if (!code) return;
    setBusy(true);
    try {
      const r = await window.MobileAPI.tgVerifyCode(code);
      if (r?.needs_password) {
        setStep("password");
        pushToast({ msg: "Нужен пароль двухфакторной (Cloud Password)", warn: true });
      } else {
        setStep("done");
        if (onDone) onDone();
        pushToast({ msg: "Telegram подключён! Listener запущен.", ok: true });
      }
    } catch (e) {
      pushToast({ msg: "Ошибка: " + (e.message || e).slice(0, 200), err: true });
    }
    setBusy(false);
  };

  const verifyPassword = async () => {
    if (!password) return;
    setBusy(true);
    try {
      await window.MobileAPI.tgVerifyPassword(password);
      setStep("done");
      if (onDone) onDone();
      pushToast({ msg: "Telegram подключён!", ok: true });
    } catch (e) {
      pushToast({ msg: "Ошибка: " + (e.message || e).slice(0, 200), err: true });
    }
    setBusy(false);
  };

  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">📨 Подключение Telegram</div>
          <button className="d-icon-btn" onClick={onClose}><DIcon name="x" size={14}/></button>
        </div>
        <div className="d-modal-body">
          {step === "creds" && (
            <>
              <div className="muted" style={{ fontSize: 11.5, marginBottom: 14, lineHeight: 1.6 }}>
                Нужны <b>api_id</b> и <b>api_hash</b> — создаются на <a href="https://my.telegram.org" target="_blank">my.telegram.org</a> один раз. Бот использует твой аккаунт чтобы читать сигнальные каналы (включая приватные, куда подписан только ты).
              </div>
              <div className="d-field">
                <div className="d-label">API ID</div>
                <input className="d-input mono" value={apiId} onChange={e => setApiId(e.target.value)} placeholder="123456" inputMode="numeric"/>
              </div>
              <div className="d-field">
                <div className="d-label">API Hash</div>
                <input className="d-input mono" value={apiHash} onChange={e => setApiHash(e.target.value)} placeholder="abcdef123456…"/>
              </div>
              <div className="d-field">
                <div className="d-label">Номер телефона (международный формат)</div>
                <input className="d-input mono" value={phone} onChange={e => setPhone(e.target.value)} placeholder="+79991234567"/>
              </div>
              <label style={{ display: "flex", alignItems: "center", gap: 8, fontSize: 12, color: "var(--d-text-1)", cursor: "pointer" }}>
                <input type="checkbox" checked={forceSms} onChange={e => setForceSms(e.target.checked)}/>
                Прислать код по SMS вместо Telegram
              </label>
            </>
          )}

          {step === "code" && (
            <>
              <div className="muted" style={{ fontSize: 11.5, marginBottom: 14 }}>
                Telegram отправил код на <b className="mono">{phone}</b>. Введи его ниже.
              </div>
              <div className="d-field">
                <div className="d-label">Код подтверждения</div>
                <input className="d-input mono"
                       style={{ fontSize: 22, textAlign: "center", letterSpacing: "0.2em" }}
                       value={code} onChange={e => setCode(e.target.value.replace(/\D/g, "").slice(0, 8))}
                       placeholder="12345" inputMode="numeric" autoFocus/>
              </div>
            </>
          )}

          {step === "password" && (
            <>
              <div className="muted" style={{ fontSize: 11.5, marginBottom: 14 }}>
                У аккаунта включена <b>двухфакторная защита (Cloud Password)</b>. Введи пароль:
              </div>
              <div className="d-field">
                <div className="d-label">Cloud Password</div>
                <input className="d-input" type="password" value={password}
                       onChange={e => setPassword(e.target.value)} autoFocus/>
              </div>
            </>
          )}

          {step === "done" && (
            <div style={{ padding: 20, textAlign: "center" }}>
              <div style={{ fontSize: 40, marginBottom: 10 }}>✅</div>
              <div style={{ fontWeight: 600, marginBottom: 6 }}>Подключено!</div>
              <div className="muted" style={{ fontSize: 12 }}>
                Listener запущен. Теперь можешь добавлять сигнальные каналы в разделе «Сигналы».
              </div>
            </div>
          )}
        </div>
        <div className="d-modal-foot">
          <button className="d-btn d-btn-ghost" onClick={onClose}>
            {step === "done" ? "Закрыть" : "Отмена"}
          </button>
          {step === "creds" && <button className="d-btn d-btn-primary" onClick={sendCode} disabled={busy}>{busy ? <span className="d-spinner"/> : "Отправить код →"}</button>}
          {step === "code" && <button className="d-btn d-btn-primary" onClick={verifyCode} disabled={busy || code.length < 4}>{busy ? <span className="d-spinner"/> : "Подтвердить →"}</button>}
          {step === "password" && <button className="d-btn d-btn-primary" onClick={verifyPassword} disabled={busy || !password}>{busy ? <span className="d-spinner"/> : "Подтвердить"}</button>}
          {step === "done" && <button className="d-btn d-btn-primary" onClick={onClose}>OK</button>}
        </div>
      </div>
    </div>
  );
};

// ─────────────────────  Multi-account manager (по 1 на биржу как минимум)  ─────────────────────
const MultiAccountManager = ({ pushToast }) => {
  const [accounts, setAccounts] = useState([]);
  const [loading, setLoading] = useState(true);
  const [editing, setEditing] = useState(null);
  const [addOpen, setAddOpen] = useState(false);

  const reload = useCallback(async () => {
    setLoading(true);
    try {
      const r = await window.MobileAPI.listExchangeAccounts?.();
      setAccounts(Array.isArray(r) ? r : []);
    } catch {}
    setLoading(false);
  }, []);
  useEffect(() => { reload(); }, [reload]);

  if (loading) return <Skel h={140}/>;

  const grouped = accounts.reduce((m, a) => {
    (m[a.exchange] = m[a.exchange] || []).push(a);
    return m;
  }, {});

  return (
    <div className="d-card d-card-pad-lg">
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 14 }}>
        <div className="d-card-title">Аккаунты бирж по label</div>
        <button className="d-btn d-btn-primary" onClick={() => setAddOpen(true)}>+ Добавить аккаунт</button>
      </div>

      {Object.keys(grouped).length === 0 ? (
        <div className="muted" style={{ fontSize: 12 }}>Пока нет ни одного API-ключа. Добавь в первой карточке слева.</div>
      ) : (
        Object.keys(grouped).map(ex => (
          <div key={ex} style={{ marginBottom: 14 }}>
            <div style={{ fontWeight: 600, fontSize: 12, marginBottom: 6, textTransform: "uppercase", letterSpacing: "0.05em" }}>
              {ex} <span className="muted">({grouped[ex].length})</span>
            </div>
            {grouped[ex].map((a, i) => (
              <div key={i} style={{ display: "flex", alignItems: "center", gap: 10, padding: "8px 10px",
                background: "var(--d-bg-2)", borderRadius: 6, marginBottom: 4 }}>
                <span className="d-badge">{a.label || "default"}</span>
                <span className="mono muted" style={{ fontSize: 11 }}>{(a.key_preview || a.key || "").slice(0, 12)}…</span>
                {a.is_active && <span className="d-badge d-badge-long" style={{ marginLeft: "auto" }}>active</span>}
              </div>
            ))}
          </div>
        ))
      )}

      {addOpen && (
        <AddAccountModal exchanges={Object.keys(grouped)} onClose={() => setAddOpen(false)}
                         onSaved={() => { setAddOpen(false); reload(); pushToast({ msg: "Ключ добавлен", ok: true }); }}
                         pushToast={pushToast}/>
      )}
    </div>
  );
};

const AddAccountModal = ({ onClose, onSaved, pushToast }) => {
  const [exch, setExch] = useState("weex");
  const [label, setLabel] = useState("default");
  const [key, setKey] = useState("");
  const [secret, setSecret] = useState("");
  const [pass, setPass] = useState("");
  const [busy, setBusy] = useState(false);
  const save = async () => {
    setBusy(true);
    try {
      await window.creds.save(exch, label.trim() || "default", { key, secret, pass });
      onSaved();
    } catch (e) {
      pushToast({ msg: "Ошибка: " + (e.message || e), err: true });
      setBusy(false);
    }
  };
  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">Добавить API-ключ</div>
          <button className="d-icon-btn" onClick={onClose}><DIcon name="x" size={14}/></button>
        </div>
        <div className="d-modal-body">
          <div className="d-field">
            <div className="d-label">Биржа</div>
            <div className="d-seg">
              {["weex","okx","binance","bybit"].map(e => (
                <button key={e} className={"d-seg-btn" + (exch === e ? " active" : "")} onClick={() => setExch(e)}>{e.toUpperCase()}</button>
              ))}
            </div>
          </div>
          <div className="d-field">
            <div className="d-label">Label (default / sub1 / arbitrage / …)</div>
            <input className="d-input" value={label} onChange={e => setLabel(e.target.value)} placeholder="default"/>
          </div>
          <div className="d-field"><div className="d-label">API Key</div><input className="d-input mono" value={key} onChange={e => setKey(e.target.value)}/></div>
          <div className="d-field"><div className="d-label">API Secret</div><input className="d-input mono" type="password" value={secret} onChange={e => setSecret(e.target.value)}/></div>
          {(exch === "okx" || exch === "weex") && (
            <div className="d-field"><div className="d-label">Passphrase</div><input className="d-input mono" type="password" value={pass} onChange={e => setPass(e.target.value)}/></div>
          )}
        </div>
        <div className="d-modal-foot">
          <button className="d-btn d-btn-ghost" onClick={onClose}>Отмена</button>
          <button className="d-btn d-btn-primary" onClick={save} disabled={busy || !key || !secret}>
            {busy ? <span className="d-spinner"/> : "Сохранить"}
          </button>
        </div>
      </div>
    </div>
  );
};

// ─────────────────────  Notifications Bell  ─────────────────────
const NotificationsBell = () => {
  const [open, setOpen] = useState(false);
  const [items, setItems] = useState([]);
  // Простой полл /api/me/notifications если есть; иначе lokal-only
  useEffect(() => {
    let alive = true;
    (async () => {
      try {
        const r = await fetch("/api/me/notifications?limit=20").then(x => x.ok ? x.json() : []).catch(() => []);
        if (alive) setItems(Array.isArray(r) ? r : []);
      } catch {}
    })();
    return () => { alive = false; };
  }, [open]);

  return (
    <div style={{ position: "relative" }}>
      <button className="d-icon-btn" onClick={() => setOpen(o => !o)} title="Уведомления">
        <DIcon name="bell" size={16}/>
        {items.length > 0 && <span className="d-icon-btn-dot"/>}
      </button>
      {open && (
        <div onClick={e => e.stopPropagation()} style={{
          position: "absolute", top: 40, right: 0,
          width: 320, maxHeight: 420, overflowY: "auto",
          background: "var(--d-bg-2)", border: "1px solid var(--d-line-2)",
          borderRadius: 10, padding: 10,
          boxShadow: "0 16px 40px rgba(0,0,0,0.5)",
          zIndex: 50,
        }}>
          <div style={{ padding: "6px 8px 10px", borderBottom: "1px solid var(--d-line)" }}>
            <div style={{ fontWeight: 600 }}>Уведомления</div>
          </div>
          {items.length === 0 ? (
            <div className="muted" style={{ padding: 20, textAlign: "center", fontSize: 12 }}>
              Пока пусто. События ботов и сигналов появятся здесь.
            </div>
          ) : (
            items.map((n, i) => (
              <div key={i} style={{ padding: "8px 6px", borderBottom: "1px solid var(--d-line-soft)", fontSize: 12 }}>
                <div style={{ fontWeight: 600 }}>{n.title || n.kind || "—"}</div>
                <div className="muted" style={{ fontSize: 11, marginTop: 2 }}>{n.body || ""}</div>
                <div className="muted mono" style={{ fontSize: 10, marginTop: 2 }}>{ago(n.ts_ms || n.created_at)}</div>
              </div>
            ))
          )}
        </div>
      )}
    </div>
  );
};

const Skel = ({ w = "100%", h = 14 }) => <div className="d-skel" style={{ width: w, height: h }}/>;

const KpiMini = ({ label, val, color }) => (
  <div style={{ padding: "6px 0" }}>
    <div className="d-kpi-label" style={{ fontSize: 10 }}>{label}</div>
    <div className="mono" style={{ fontSize: 16, fontWeight: 600, marginTop: 4, color: color || undefined }}>
      {val}
    </div>
  </div>
);

// ─────────────────────  Exchange Bot Details Modal (OKX и др.)  ─────────────────────
const ExchangeBotDetailsModal = ({ bot, exchange, onClose }) => {
  const [details, setDetails] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    (async () => {
      try {
        const algoId = bot.algoId || bot.algo_id || bot.algo_ord_id;
        const algoOrdType = bot.algoOrdType || bot.algo_ord_type || bot.botType || "grid";
        if (!algoId) { setLoading(false); return; }
        const r = await window.MobileAPI.loadBotDetails?.(exchange, algoId, algoOrdType);
        setDetails(r || bot);
      } catch {
        setDetails(bot);
      }
      setLoading(false);
    })();
  }, [bot, exchange]);

  const d = details || bot;
  const pnl = Number(d.totalPnl || d.total_pnl || d.pnl || 0);
  const pnlRatio = Number(d.totalPnlRatio || d.apr || 0);
  const inv = Number(d.investment || d.totalInvestment || 0);
  const grid = Number(d.gridProfit || d.gridProfits || 0);
  const unrealized = Number(d.floatProfit || d.unrealizedPnl || 0);
  const created = Number(d.cTime || d.createTime || d.created_at || 0);
  const uptimeMs = created > 0 ? Date.now() - created : 0;
  const days = Math.floor(uptimeMs / 86400000);
  const hours = Math.floor((uptimeMs % 86400000) / 3600000);
  const upStr = uptimeMs > 0 ? `${days}д ${hours}ч` : "—";

  return (
    <div className="d-modal-backdrop" onClick={onClose}>
      <div className="d-modal wide" onClick={e => e.stopPropagation()} style={{ maxWidth: 920 }}>
        <div className="d-modal-head">
          <div className="d-modal-title" style={{ display: "flex", alignItems: "center", gap: 10 }}>
            <div style={{ width: 32, height: 32, borderRadius: 8, background: "var(--d-bg-3)",
                          display: "grid", placeItems: "center", color: "var(--d-accent)" }}>
              <DIcon name="chart" size={16}/>
            </div>
            <div>
              <div>{String(d.instId || d.symbol || "").toUpperCase()} · <span className="muted" style={{ fontSize: 11, fontWeight: 400 }}>{exchange.toUpperCase()}</span></div>
              <div className="muted mono" style={{ fontSize: 10, fontWeight: 400 }}>
                {String(d.algoOrdType || d.botType || "grid").toUpperCase()} · {d.direction || "neutral"} · {d.algoId || d.algo_id || "—"}
              </div>
            </div>
          </div>
          <button className="d-icon-btn" onClick={onClose}><DIcon name="x" size={14}/></button>
        </div>
        <div className="d-modal-body">
          {loading ? <Skel h={300}/> : (
            <>
              <div style={{ display: "grid", gridTemplateColumns: "2fr 1fr 1fr", gap: 10, marginBottom: 14 }}>
                <div className="d-card" style={{ padding: 14 }}>
                  <div className="d-kpi-label">Общий PnL (USDT)</div>
                  <div className={"d-kpi-value mono " + pctClass(pnl)}>
                    {pnl >= 0 ? "+" : ""}{fmt(pnl)}
                  </div>
                  <div className={"d-kpi-sub mono " + pctClass(pnlRatio)}>
                    {(pnlRatio >= 0 ? "+" : "") + (pnlRatio * 100).toFixed(2)}%
                  </div>
                </div>
                <div className="d-card" style={{ padding: 14 }}>
                  <div className="d-kpi-label">Время работы</div>
                  <div className="d-kpi-value mono" style={{ fontSize: 18 }}>{upStr}</div>
                  <div className="d-kpi-sub" style={{ fontSize: 11 }}>с {ago(created)} назад</div>
                </div>
                <div className="d-card" style={{ padding: 14 }}>
                  <div className="d-kpi-label">Прибыль с сетки</div>
                  <div className={"d-kpi-value mono " + pctClass(grid)} style={{ fontSize: 18 }}>
                    {grid >= 0 ? "+" : ""}{fmt(grid)}
                  </div>
                  <div className="d-kpi-sub" style={{ fontSize: 11 }}>realized grid</div>
                </div>
              </div>

              <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 14, marginBottom: 14 }}>
                <div className="d-card" style={{ padding: 14 }}>
                  <div className="d-label">Параметры бота</div>
                  <div className="d-stat"><span className="d-stat-label">Инвестиция</span><span className="d-stat-val mono">{fmt(inv)} {d.quoteSz || d.currency || "USDT"}</span></div>
                  <div className="d-stat"><span className="d-stat-label">Диапазон</span><span className="d-stat-val mono">{fmtPx(d.minPx || d.min_px)} - {fmtPx(d.maxPx || d.max_px)}</span></div>
                  <div className="d-stat"><span className="d-stat-label">Уровней</span><span className="d-stat-val mono">{d.gridNum || d.grid_num || "—"}</span></div>
                  <div className="d-stat"><span className="d-stat-label">Плечо</span><span className="d-stat-val mono">{d.lever || d.leverage || "—"}x</span></div>
                  <div className="d-stat"><span className="d-stat-label">Тип сетки</span><span className="d-stat-val mono">{d.runType === "1" ? "Арифметика" : d.runType === "2" ? "Геометрия" : "—"}</span></div>
                </div>

                <div className="d-card" style={{ padding: 14 }}>
                  <div className="d-label">PnL разбивка</div>
                  <div className="d-stat"><span className="d-stat-label">Realized (сетка)</span><span className={"d-stat-val mono " + pctClass(grid)}>{grid >= 0 ? "+" : ""}{fmt(grid)}</span></div>
                  <div className="d-stat"><span className="d-stat-label">Unrealized (позиция)</span><span className={"d-stat-val mono " + pctClass(unrealized)}>{unrealized >= 0 ? "+" : ""}{fmt(unrealized)}</span></div>
                  <div className="d-stat"><span className="d-stat-label">Совокупно</span><span className={"d-stat-val mono " + pctClass(pnl)}>{pnl >= 0 ? "+" : ""}{fmt(pnl)}</span></div>
                  <div className="d-stat"><span className="d-stat-label">Annualized return</span><span className={"d-stat-val mono " + pctClass(pnlRatio)}>{(pnlRatio >= 0 ? "+" : "") + (pnlRatio * 100).toFixed(2)}%</span></div>
                  {d.liqPx > 0 && (
                    <div className="d-stat"><span className="d-stat-label">Цена ликвидации</span><span className="d-stat-val mono neg">{fmtPx(d.liqPx)}</span></div>
                  )}
                </div>
              </div>

              {/* Raw data fallback — если API даёт больше полей чем мы маппим */}
              <details>
                <summary style={{ cursor: "pointer", fontSize: 12, color: "var(--d-text-2)", padding: "8px 0" }}>
                  Все поля от биржи (raw JSON)
                </summary>
                <pre style={{ padding: 12, background: "var(--d-bg-2)", borderRadius: 6,
                              fontSize: 11, lineHeight: 1.5, overflow: "auto",
                              maxHeight: 300, fontFamily: "var(--d-font-mono)" }}>
                  {JSON.stringify(d, null, 2)}
                </pre>
              </details>
            </>
          )}
        </div>
      </div>
    </div>
  );
};

window.DesktopExtras = {
  LocalBotDetailsModal,
  ExchangeBotDetailsModal,
  BasketCreateForm,
  TelegramConnectWizard,
  MultiAccountManager,
  NotificationsBell,
};

})();
