// Multi-exchange settings — ключи теперь хранятся НА СЕРВЕРЕ в зашифрованном виде.
// localStorage используется только для выбора активной биржи (UX, не секрет).
// При первом заходе после рефактора показываем миграционный диалог.

const ACTIVE_KEY = "active_exchange_v1";
const LEGACY_STORE_KEY = "multi_creds_v1";
const LEGACY_WEEX_KEY = "weex_credentials_v1";

// Метаданные бирж (синхронизированы с /api/exchanges)
const EXCHANGE_META = {
  weex:    { id: "weex",    name: "WEEX",            passphrase: true,  enabled: true, supports_spot: false, supports_bots: false },
  binance: { id: "binance", name: "Binance USDⓈ-M",  passphrase: false, enabled: true, supports_spot: true,  supports_bots: false },
  bybit:   { id: "bybit",   name: "Bybit (V5)",       passphrase: false, enabled: true, supports_spot: true,  supports_bots: false },
  okx:     { id: "okx",     name: "OKX (V5)",         passphrase: true,  enabled: true, supports_spot: true,  supports_bots: true  },
};
const EXCHANGE_ORDER = ["weex", "binance", "bybit", "okx"];

// =============================================================
// window.creds — теперь это server-backed реестр
// =============================================================
//
// Старый API (active/setActive/hasActive/headers) сохранён, чтобы не ломать
// существующий код в app.jsx / spot-tab.jsx / bots-tab.jsx.
// Headers больше не нужны — backend сам тянет ключи из БД по cookie-сессии,
// но возвращаем {} для совместимости.

window.creds = (function () {
  // ready: { weex: true, okx: true, ... } — какие биржи имеют ключи на сервере
  let _ready = {};

  function active() {
    try { return localStorage.getItem(ACTIVE_KEY) || "okx"; }
    catch { return "okx"; }
  }
  function setActive(ex) {
    try { localStorage.setItem(ACTIVE_KEY, ex); } catch {}
  }

  async function refresh() {
    try {
      const list = await window.AUTH.listCreds();
      const r = {};
      (list || []).forEach(c => { r[c.exchange] = true; });
      _ready = r;
      return r;
    } catch (e) {
      // Если не залогинены или encryption не настроено — пусто
      _ready = {};
      return {};
    }
  }

  function isReady(ex) { return !!_ready[ex]; }
  function hasActive() { return isReady(active()); }
  function readyMap() { return { ..._ready }; }

  // Legacy для миграции
  function readLegacy() {
    try {
      const newRaw = localStorage.getItem(LEGACY_STORE_KEY);
      if (newRaw) {
        const parsed = JSON.parse(newRaw);
        const out = {};
        EXCHANGE_ORDER.forEach(ex => {
          const c = parsed[ex];
          if (c && c.key && c.secret) {
            out[ex] = { key: c.key, secret: c.secret, pass: c.pass || "" };
          }
        });
        return out;
      }
      const oldRaw = localStorage.getItem(LEGACY_WEEX_KEY);
      if (oldRaw) {
        const old = JSON.parse(oldRaw);
        if (old.key) return { weex: { key: old.key, secret: old.secret, pass: old.pass || "" } };
      }
    } catch {}
    return {};
  }
  function clearLegacy() {
    try {
      localStorage.removeItem(LEGACY_STORE_KEY);
      localStorage.removeItem(LEGACY_WEEX_KEY);
    } catch {}
  }

  return {
    active, setActive,
    refresh, isReady, hasActive, readyMap,
    headers: () => ({}),  // backend сам читает из БД
    readLegacy, clearLegacy,
  };
})();

window.EXCHANGE_META = EXCHANGE_META;
window.EXCHANGE_ORDER = EXCHANGE_ORDER;


// =============================================================
// Header dropdown — переключение активной биржи
// =============================================================
const ExchangeSwitcher = ({ active, onChange }) => {
  const [open, setOpen] = useState(false);
  const [, setTick] = useState(0);  // re-render когда window.creds._ready обновится
  const ref = useRef(null);
  useEffect(() => {
    const h = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener("mousedown", h);
    return () => document.removeEventListener("mousedown", h);
  }, []);
  // Подписка на обновления creds (через простой event-bus)
  useEffect(() => {
    const onUpd = () => setTick(t => t + 1);
    window.addEventListener("creds-updated", onUpd);
    return () => window.removeEventListener("creds-updated", onUpd);
  }, []);

  const meta = EXCHANGE_META[active] || EXCHANGE_META.weex;
  return (
    <div ref={ref} style={{ position: "relative" }}>
      <button className="status-chip" onClick={() => setOpen(v => !v)} style={{ cursor: "pointer" }}>
        <span style={{ width: 6, height: 6, borderRadius: "50%", background: "var(--accent)" }} />
        {meta.name}
        <Icon name="chevDown" size={10} style={{ marginLeft: 4 }} />
      </button>
      {open && (
        <div className="popover" style={{ right: "auto", left: 0, top: "calc(100% + 6px)", minWidth: 220 }}>
          {EXCHANGE_ORDER.map(id => {
            const m = EXCHANGE_META[id];
            const ready = window.creds.isReady(id);
            return (
              <button
                key={id}
                onClick={() => { onChange(id); setOpen(false); }}
                disabled={!m.enabled}
                style={{
                  width: "100%", display: "flex", alignItems: "center", justifyContent: "space-between",
                  padding: "8px 10px", borderRadius: 6,
                  background: id === active ? "var(--panel-2)" : "transparent",
                  color: m.enabled ? "var(--text)" : "var(--text-4)",
                  cursor: m.enabled ? "pointer" : "not-allowed",
                  fontSize: 12.5,
                }}>
                <span>{m.name}</span>
                <span className="mono" style={{ fontSize: 10, color: ready ? "var(--long)" : "var(--text-4)" }}>
                  {ready ? "● ready" : "○ no key"}
                </span>
              </button>
            );
          })}
        </div>
      )}
    </div>
  );
};


// =============================================================
// Settings modal — server-backed
// =============================================================
const SettingsModal = ({ open, onClose, onSaved, initialExchange }) => {
  const { t } = useLang();
  const [ex, setEx] = useState(initialExchange || window.creds.active());
  const [serverInfo, setServerInfo] = useState(null); // {key_masked, has_passphrase, ...}
  const [c, setC] = useState({ key: "", secret: "", pass: "", label: "" });
  const [show, setShow] = useState({ secret: false, pass: false });
  const [status, setStatus] = useState({ kind: "", text: "" });
  const [busy, setBusy] = useState(false);

  // Загрузить инфу с сервера про эту биржу
  const loadInfo = useCallback(async (exchange) => {
    setStatus({ kind: "", text: "" });
    setC({ key: "", secret: "", pass: "", label: "" });
    try {
      const list = await window.AUTH.listCreds();
      const found = (list || []).find(x => x.exchange === exchange);
      setServerInfo(found || null);
    } catch (e) {
      setServerInfo(null);
      if (e.status === 503) {
        setStatus({ kind: "err", text: e.message });
      }
    }
  }, []);

  useEffect(() => {
    if (open) {
      const newEx = initialExchange || window.creds.active();
      setEx(newEx);
      loadInfo(newEx);
    }
  }, [open, initialExchange, loadInfo]);

  useEffect(() => {
    if (open) loadInfo(ex);
  }, [ex, open, loadInfo]);

  if (!open) return null;

  const meta = EXCHANGE_META[ex];
  const upd = (k, v) => setC(prev => ({ ...prev, [k]: v }));

  const save = async () => {
    if (!c.key || !c.secret || (meta.passphrase && !c.pass)) {
      setStatus({ kind: "err", text: "Заполните все поля" });
      return;
    }
    setBusy(true);
    setStatus({ kind: "muted", text: "Сохраняю..." });
    try {
      await window.AUTH.saveCreds(ex, {
        key: c.key.trim(),
        secret: c.secret.trim(),
        passphrase: (c.pass || "").trim(),
        label: c.label.trim(),
      });
      await window.creds.refresh();
      window.dispatchEvent(new Event("creds-updated"));
      window.creds.setActive(ex);
      setStatus({ kind: "ok", text: "💾 Сохранено в защищённом хранилище" });
      setTimeout(() => { onSaved && onSaved(ex); onClose(); }, 600);
    } catch (e) {
      setStatus({ kind: "err", text: "❌ " + (e.message || "Ошибка") });
    } finally {
      setBusy(false);
    }
  };

  const test = async () => {
    // Тест с введёнными значениями. Если поля пустые — тестируем уже сохранённые.
    setBusy(true);
    setStatus({ kind: "muted", text: "..." });
    try {
      const headers = {};
      if (c.key && c.secret) {
        headers["X-EX-KEY"] = c.key;
        headers["X-EX-SECRET"] = c.secret;
        if (c.pass) headers["X-EX-PASS"] = c.pass;
      }
      const r = await fetch(`/api/ex/${ex}/status`, { headers, credentials: "include" });
      const data = await r.json();
      if (data.ok) setStatus({ kind: "ok", text: "✅ Соединение работает" });
      else setStatus({ kind: "err", text: "❌ " + (data.error || JSON.stringify(data)).substring(0, 200) });
    } catch (e) {
      setStatus({ kind: "err", text: "❌ " + e.message });
    } finally {
      setBusy(false);
    }
  };

  const remove = async () => {
    if (!confirm(`Удалить ключи ${meta.name}?`)) return;
    setBusy(true);
    try {
      await window.AUTH.deleteCreds(ex);
      await window.creds.refresh();
      window.dispatchEvent(new Event("creds-updated"));
      setServerInfo(null);
      setC({ key: "", secret: "", pass: "", label: "" });
      setStatus({ kind: "ok", text: "🗑 Удалено" });
    } catch (e) {
      setStatus({ kind: "err", text: e.message });
    } finally {
      setBusy(false);
    }
  };

  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal" onClick={e => e.stopPropagation()} style={{ width: "min(540px, 92vw)" }}>
        <div className="modal-head">
          <h2><Icon name="settings" size={14} /> API-ключи бирж</h2>
          <button className="icon-btn" onClick={onClose}><Icon name="x" size={14} /></button>
        </div>
        <div className="modal-body">
          <div className="field">
            <label>Биржа</label>
            <select className="select" value={ex} onChange={e => setEx(e.target.value)} disabled={busy}>
              {EXCHANGE_ORDER.map(id => {
                const m = EXCHANGE_META[id];
                return <option key={id} value={id} disabled={!m.enabled}>
                  {m.name}{!m.enabled ? " — coming soon" : ""}
                  {window.creds.isReady(id) ? "  • ready" : ""}
                </option>;
              })}
            </select>
          </div>

          {serverInfo && (
            <div style={{
              padding: "10px 12px", marginBottom: 12,
              background: "var(--long-dim)", border: "1px solid var(--long)",
              borderRadius: "var(--r-2)", color: "var(--long)",
              fontSize: 12, lineHeight: 1.6,
            }}>
              <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between" }}>
                <div>
                  <Icon name="lock" size={11}/>{" "}
                  <b>Ключи сохранены</b> · key={" "}
                  <span className="mono">{serverInfo.key_masked}</span>
                  {serverInfo.has_passphrase && <> · passphrase ✓</>}
                </div>
                <button className="btn" onClick={remove} disabled={busy}
                        style={{ fontSize: 11, padding: "3px 8px",
                                 color: "var(--short)", borderColor: "var(--short-dim)" }}>
                  <Icon name="x" size={10}/> Удалить
                </button>
              </div>
              <div style={{ color: "var(--text-3)", fontSize: 11, marginTop: 4 }}>
                Чтобы заменить — введите новые значения ниже и нажмите "Сохранить".
              </div>
            </div>
          )}

          <div className="field">
            <label>API Key</label>
            <input className="input" type="text" value={c.key}
              onChange={e => upd("key", e.target.value)} disabled={busy}
              placeholder={serverInfo ? "(введите новый ключ для замены)" : "api_key"}
              autoComplete="off" spellCheck={false} />
          </div>

          <div className="field">
            <label>API Secret</label>
            <div className="input-wrap">
              <input className="input with-toggle" type={show.secret ? "text" : "password"} value={c.secret}
                onChange={e => upd("secret", e.target.value)} disabled={busy}
                placeholder={serverInfo ? "(введите новый секрет для замены)" : "••••••••"}
                autoComplete="off" spellCheck={false} />
              <button className="input-toggle" onClick={() => setShow(s => ({ ...s, secret: !s.secret }))}>
                <Icon name={show.secret ? "eyeOff" : "eye"} size={14} />
              </button>
            </div>
          </div>

          {meta.passphrase && (
            <div className="field">
              <label>Passphrase</label>
              <div className="input-wrap">
                <input className="input with-toggle" type={show.pass ? "text" : "password"} value={c.pass}
                  onChange={e => upd("pass", e.target.value)} disabled={busy}
                  placeholder="••••••••" autoComplete="off" spellCheck={false} />
                <button className="input-toggle" onClick={() => setShow(s => ({ ...s, pass: !s.pass }))}>
                  <Icon name={show.pass ? "eyeOff" : "eye"} size={14} />
                </button>
              </div>
            </div>
          )}

          <div className="field">
            <label>Метка (опц.)</label>
            <input className="input" type="text" value={c.label}
              onChange={e => upd("label", e.target.value)} disabled={busy}
              placeholder="main / demo / subaccount-1" autoComplete="off" maxLength={64}/>
          </div>

          <div className="empty-hint" style={{ marginTop: 4, textAlign: "left", lineHeight: 1.5 }}>
            🔐 Ключи шифруются Fernet (AES-128 + HMAC) перед записью в БД.
            Серверу нужен <code>MASTER_ENCRYPTION_KEY</code> в .env.
            Read-only прав API достаточно — у этой системы НЕТ права снятия с биржи.
          </div>

          {status.text && (
            <div style={{ marginTop: 10, fontSize: 12,
                          color: status.kind === "ok" ? "var(--long)"
                              : status.kind === "err" ? "var(--short)" : "var(--text-3)",
                          fontFamily: "var(--font-mono)" }}>
              {status.text}
            </div>
          )}
        </div>
        <div className="modal-foot">
          <button className="btn ghost" onClick={onClose} disabled={busy}>Закрыть</button>
          <div style={{ display: "flex", gap: 6 }}>
            <button className="btn" onClick={test} disabled={busy}>Тест соединения</button>
            <button className="btn primary" onClick={save} disabled={busy}>
              {busy ? "..." : "Сохранить"}
            </button>
          </div>
        </div>
      </div>
    </div>
  );
};

// =============================================================
// Migration modal — переносит localStorage-ключи в серверное хранилище
// =============================================================
const MigrationModal = ({ legacy, onDone, onSkip }) => {
  const [running, setRunning] = useState(false);
  const [progress, setProgress] = useState({});
  const [err, setErr] = useState("");
  // Pre-flight: проверяем настроено ли шифрование на бэке.
  // null = ещё не проверили, true/false = результат.
  const [encryptionReady, setEncryptionReady] = useState(null);

  const items = Object.entries(legacy);

  // GET /me/exchange-creds — если 503, шифрование не настроено.
  useEffect(() => {
    (async () => {
      try {
        await window.AUTH.listCreds();
        setEncryptionReady(true);
      } catch (e) {
        setEncryptionReady(e.status !== 503);
        if (e.status === 503) setErr(e.message);
      }
    })();
  }, []);

  const run = async () => {
    setRunning(true); setErr("");
    const prog = {};
    for (const [ex, c] of items) {
      prog[ex] = "saving";
      setProgress({ ...prog });
      try {
        await window.AUTH.saveCreds(ex, {
          key: c.key, secret: c.secret, passphrase: c.pass || "", label: "migrated",
        });
        prog[ex] = "ok";
      } catch (e) {
        prog[ex] = "err:" + (e.message || "?");
      }
      setProgress({ ...prog });
    }
    const allOk = Object.values(prog).every(s => s === "ok");
    if (allOk) {
      window.creds.clearLegacy();
      await window.creds.refresh();
      window.dispatchEvent(new Event("creds-updated"));
      setTimeout(onDone, 600);
    } else {
      setErr("Часть ключей не перенеслась — localStorage НЕ очищен, твои данные на месте. Исправь ошибку и попробуй снова.");
    }
    setRunning(false);
  };

  // Кнопка "Удалить локальную копию" — только если юзер явно хочет
  const forgetLocally = () => {
    if (!confirm("Удалить локальную копию ключей? После этого восстановить из браузера будет НЕЛЬЗЯ. Используй если уже сохранил их в надёжном месте (менеджер паролей).")) return;
    window.creds.clearLegacy();
    onSkip();
  };

  return (
    <div className="modal-backdrop">
      <div className="modal" onClick={e => e.stopPropagation()} style={{ width: "min(480px, 92vw)" }}>
        <div className="modal-head">
          <h2><Icon name="lock" size={14}/> Перенос ключей в защищённое хранилище</h2>
        </div>
        <div className="modal-body">
          <div style={{ fontSize: 13, lineHeight: 1.55, color: "var(--text-2)" }}>
            Раньше API-ключи бирж хранились в браузере (localStorage). Теперь — на сервере,
            зашифрованные мастер-ключом. Найдены ключи для {items.length} {items.length === 1 ? "биржи" : "бирж"}:
          </div>
          <div style={{ marginTop: 12 }}>
            {items.map(([ex, c]) => {
              const meta = window.EXCHANGE_META[ex] || { name: ex };
              const status = progress[ex];
              return (
                <div key={ex} style={{
                  display: "flex", alignItems: "center", justifyContent: "space-between",
                  padding: "8px 12px", marginBottom: 6,
                  background: "var(--bg-2)", border: "1px solid var(--border)",
                  borderRadius: "var(--r-2)",
                }}>
                  <div>
                    <div style={{ fontSize: 12, fontWeight: 500 }}>{meta.name}</div>
                    <div className="mono muted" style={{ fontSize: 10.5 }}>
                      key: {(c.key || "").substring(0, 8)}…{(c.key || "").slice(-4)}
                    </div>
                  </div>
                  <div className="mono" style={{ fontSize: 11 }}>
                    {status === "ok" && <span className="pos">✓ ok</span>}
                    {status === "saving" && <span style={{ color: "var(--text-3)" }}>...</span>}
                    {status && status.startsWith("err") && <span className="neg">⚠ {status.slice(4)}</span>}
                    {!status && <span style={{ color: "var(--text-4)" }}>—</span>}
                  </div>
                </div>
              );
            })}
          </div>
          {encryptionReady === false && (
            <div style={{
              marginTop: 10, padding: "10px 12px",
              background: "var(--short-dim)", border: "1px solid var(--short)",
              borderRadius: "var(--r-2)", color: "var(--short)",
              fontSize: 12, lineHeight: 1.6,
            }}>
              <b>⚠ Шифрование не настроено на сервере.</b><br/>
              Перенос невозможен. Сначала добавь <code>MASTER_ENCRYPTION_KEY</code> в <code>.env</code>:
              <pre style={{ background: "rgba(0,0,0,0.2)", padding: 6, marginTop: 6, borderRadius: 4, fontSize: 11, overflow: "auto" }}>
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
              </pre>
              Скопируй вывод в <code>.env</code> как <code>MASTER_ENCRYPTION_KEY=...</code> и перезапусти сервер.
              Твои локальные ключи остаются в браузере — они НЕ удалены.
            </div>
          )}
          {err && encryptionReady !== false && (
            <div style={{ marginTop: 10, color: "var(--short)", fontSize: 12 }}>⚠ {err}</div>
          )}
          <div className="empty-hint" style={{ marginTop: 10, textAlign: "left", lineHeight: 1.5 }}>
            "Перенести" — копирует на сервер. Если все ОК, localStorage очищается.<br/>
            "Пропустить" — просто закрывает окно, ключи остаются в браузере. Появится снова при следующем входе.<br/>
            "Удалить локальную копию" — затирает данные из браузера НАВСЕГДА (используй когда уже сохранил в менеджер паролей).
          </div>
        </div>
        <div className="modal-foot">
          <button className="btn" onClick={forgetLocally} disabled={running}
                  style={{ color: "var(--short)", borderColor: "var(--short-dim)" }}>
            Удалить локальную копию
          </button>
          <div style={{ display: "flex", gap: 6 }}>
            <button className="btn ghost" onClick={onSkip} disabled={running}>Пропустить</button>
            <button className="btn primary" onClick={run}
                    disabled={running || encryptionReady === false || encryptionReady === null}>
              {running ? "..." : encryptionReady === null ? "Проверка..." : "Перенести"}
            </button>
          </div>
        </div>
      </div>
    </div>
  );
};

Object.assign(window, { SettingsModal, ExchangeSwitcher, MigrationModal });
