// Auth UI: login / register / forgot / reset + verify-banner + account-modal + admin-panel.
//
// Стиль соответствует существующему дашборду: тёмные карточки, монохром,
// .input/.btn/.field из style.css. Доп. правила в .auth-* классах.

// =====================================================================
// Утилиты
// =====================================================================

const _emailRe = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const validEmail = (s) => _emailRe.test(String(s || "").trim());

const readQuery = (key) => {
  try {
    const params = new URLSearchParams(window.location.search);
    return params.get(key);
  } catch { return null; }
};

const stripQuery = () => {
  try {
    const url = new URL(window.location.href);
    url.search = "";
    window.history.replaceState({}, "", url.toString());
  } catch {}
};

// =====================================================================
// Wrapper-карточка для всех auth-экранов
// =====================================================================

const AuthCard = ({ title, sub, children, footer }) => (
  <div className="auth-page">
    <div className="auth-card">
      <div className="auth-brand">
        <img src="/static/logo.png" alt="API4ATKA" width="44" height="44"
             style={{ width: 44, height: 44, borderRadius: 12, display: "block",
                      boxShadow: "0 6px 18px rgba(99,102,241,.35)" }} />
        <div>
          <div style={{ fontSize: 18, fontWeight: 700, letterSpacing: ".3px" }}>API4ATKA</div>
          <div style={{ fontSize: 11.5, color: "var(--text-3)", marginTop: 2 }}>{sub}</div>
        </div>
      </div>
      <h1 className="auth-title">{title}</h1>
      <div className="auth-body">{children}</div>
      {footer && <div className="auth-foot">{footer}</div>}
    </div>
  </div>
);

const AuthError = ({ msg }) => !msg ? null : (
  <div className="auth-error">⚠ {msg}</div>
);
const AuthInfo = ({ msg }) => !msg ? null : (
  <div className="auth-info">✓ {msg}</div>
);

// =====================================================================
// Login screen
// =====================================================================

const LoginScreen = ({ onLogin, switchTo }) => {
  const [email, setEmail] = useState("");
  const [pw, setPw] = useState("");
  const [showPw, setShowPw] = useState(false);
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState("");

  const submit = async (e) => {
    e.preventDefault();
    setErr("");
    if (!validEmail(email)) return setErr("Неверный формат email");
    if (pw.length < 1) return setErr("Введите пароль");
    setBusy(true);
    try {
      const r = await window.AUTH.login(email.trim(), pw);
      onLogin(r.user);
    } catch (ex) {
      setErr(ex.message || "Ошибка входа");
    } finally {
      setBusy(false);
    }
  };

  return (
    <AuthCard
      title="Вход"
      sub="войдите чтобы продолжить"
      footer={
        <div style={{ fontSize: 12, color: "var(--text-3)" }}>
          Нет аккаунта? <a className="auth-link" onClick={() => switchTo("register")}>Зарегистрироваться</a>
          <span style={{ margin: "0 6px" }}>·</span>
          <a className="auth-link" onClick={() => switchTo("forgot")}>Забыли пароль?</a>
        </div>
      }
    >
      <form onSubmit={submit} autoComplete="on">
        <div className="field">
          <label>Email</label>
          <input className="input" type="email" autoComplete="email" required
            value={email} onChange={e => setEmail(e.target.value)} disabled={busy}/>
        </div>
        <div className="field">
          <label>Пароль</label>
          <div className="input-wrap">
            <input className="input with-toggle" type={showPw ? "text" : "password"}
              autoComplete="current-password" required minLength={1}
              value={pw} onChange={e => setPw(e.target.value)} disabled={busy}/>
            <button type="button" className="input-toggle" onClick={() => setShowPw(s => !s)}
                    tabIndex={-1} aria-label="Показать пароль">
              <Icon name={showPw ? "eyeOff" : "eye"} size={14}/>
            </button>
          </div>
        </div>
        <AuthError msg={err}/>
        <button className="btn primary" type="submit" disabled={busy} style={{ width: "100%", marginTop: 4 }}>
          {busy ? "..." : "Войти"}
        </button>
      </form>
    </AuthCard>
  );
};

// =====================================================================
// Register screen
// =====================================================================

const RegisterScreen = ({ onLogin, switchTo }) => {
  const [email, setEmail] = useState("");
  const [pw, setPw] = useState("");
  const [pw2, setPw2] = useState("");
  const [showPw, setShowPw] = useState(false);
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState("");
  const [tsCfg, setTsCfg] = useState(null);   // {turnstile_enabled, turnstile_site_key}
  const [tsToken, setTsToken] = useState("");

  // Cloudflare Turnstile (капча): тянем site key из /auth/config и рендерим виджет
  useEffect(() => {
    let cancelled = false, iv = null;
    fetch("/api/auth/config", { credentials: "include" }).then(r => r.json()).then(cfg => {
      if (cancelled) return;
      setTsCfg(cfg);
      if (!cfg.turnstile_enabled || !cfg.turnstile_site_key) return;
      if (!document.getElementById("cf-turnstile-js")) {
        const s = document.createElement("script");
        s.id = "cf-turnstile-js";
        s.src = "https://challenges.cloudflare.com/turnstile/v0/api.js";
        s.async = true; s.defer = true;
        document.head.appendChild(s);
      }
      iv = setInterval(() => {
        if (cancelled) { clearInterval(iv); return; }
        const el = document.getElementById("ts-reg");
        if (window.turnstile && el && !el.childElementCount) {
          clearInterval(iv);
          window.turnstile.render("#ts-reg", {
            sitekey: cfg.turnstile_site_key, theme: "dark",
            callback: t => setTsToken(t),
            "error-callback": () => setTsToken(""),
            "expired-callback": () => setTsToken(""),
          });
        }
      }, 200);
      setTimeout(() => iv && clearInterval(iv), 10000);
    }).catch(() => {});
    return () => { cancelled = true; if (iv) clearInterval(iv); };
  }, []);

  const submit = async (e) => {
    e.preventDefault();
    setErr("");
    if (!validEmail(email)) return setErr("Неверный формат email");
    if (pw.length < 8) return setErr("Пароль минимум 8 символов");
    if (pw !== pw2) return setErr("Пароли не совпадают");
    if (/^[a-zA-Z]+$/.test(pw) || /^\d+$/.test(pw))
      return setErr("Пароль должен содержать и буквы, и цифры");
    if (tsCfg && tsCfg.turnstile_enabled && !tsToken)
      return setErr("Подтвердите, что вы не робот");
    setBusy(true);
    try {
      const r = await window.AUTH.register(email.trim(), pw, tsToken);
      onLogin(r.user);
    } catch (ex) {
      setErr(ex.message || "Ошибка регистрации");
    } finally {
      setBusy(false);
    }
  };

  return (
    <AuthCard
      title="Регистрация"
      sub="создайте аккаунт"
      footer={
        <div style={{ fontSize: 12, color: "var(--text-3)" }}>
          Уже есть аккаунт? <a className="auth-link" onClick={() => switchTo("login")}>Войти</a>
        </div>
      }
    >
      <form onSubmit={submit} autoComplete="on">
        <div className="field">
          <label>Email</label>
          <input className="input" type="email" autoComplete="email" required
            value={email} onChange={e => setEmail(e.target.value)} disabled={busy}/>
        </div>
        <div className="field">
          <label>Пароль (мин. 8 символов, буквы + цифры)</label>
          <div className="input-wrap">
            <input className="input with-toggle" type={showPw ? "text" : "password"}
              autoComplete="new-password" required minLength={8}
              value={pw} onChange={e => setPw(e.target.value)} disabled={busy}/>
            <button type="button" className="input-toggle" onClick={() => setShowPw(s => !s)} tabIndex={-1}>
              <Icon name={showPw ? "eyeOff" : "eye"} size={14}/>
            </button>
          </div>
        </div>
        <div className="field">
          <label>Повторите пароль</label>
          <input className="input" type={showPw ? "text" : "password"}
            autoComplete="new-password" required minLength={8}
            value={pw2} onChange={e => setPw2(e.target.value)} disabled={busy}/>
        </div>
        {tsCfg && tsCfg.turnstile_enabled && (
          <div className="field" style={{ display: "flex", justifyContent: "center" }}>
            <div id="ts-reg"></div>
          </div>
        )}
        <AuthError msg={err}/>
        <button className="btn primary" type="submit" disabled={busy} style={{ width: "100%", marginTop: 4 }}>
          {busy ? "..." : "Создать аккаунт"}
        </button>
        <div style={{ fontSize: 11, color: "var(--text-4)", marginTop: 12, textAlign: "center", lineHeight: 1.5 }}>
          Регистрируясь, вы соглашаетесь с условиями использования.<br/>
          Защита от ботов — Cloudflare Turnstile.
        </div>
      </form>
    </AuthCard>
  );
};

// =====================================================================
// Forgot password screen
// =====================================================================

const ForgotScreen = ({ switchTo }) => {
  const [email, setEmail] = useState("");
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState("");
  const [sent, setSent] = useState(false);

  const submit = async (e) => {
    e.preventDefault();
    setErr("");
    if (!validEmail(email)) return setErr("Неверный формат email");
    setBusy(true);
    try {
      await window.AUTH.forgot(email.trim());
      setSent(true);
    } catch (ex) {
      setErr(ex.message || "Ошибка");
    } finally {
      setBusy(false);
    }
  };

  return (
    <AuthCard
      title="Сброс пароля"
      sub="введите email от аккаунта"
      footer={
        <div style={{ fontSize: 12, color: "var(--text-3)" }}>
          <a className="auth-link" onClick={() => switchTo("login")}>← Назад ко входу</a>
        </div>
      }
    >
      {sent ? (
        <>
          <AuthInfo msg="Если такой email зарегистрирован — на него отправлено письмо со ссылкой для сброса (действует 1 час)."/>
          <div style={{ fontSize: 12, color: "var(--text-3)", marginTop: 10, lineHeight: 1.6 }}>
            Не пришло — проверьте спам или попробуйте ещё раз через минуту.
          </div>
        </>
      ) : (
        <form onSubmit={submit}>
          <div className="field">
            <label>Email</label>
            <input className="input" type="email" autoComplete="email" required
              value={email} onChange={e => setEmail(e.target.value)} disabled={busy}/>
          </div>
          <AuthError msg={err}/>
          <button className="btn primary" type="submit" disabled={busy} style={{ width: "100%", marginTop: 4 }}>
            {busy ? "..." : "Отправить ссылку"}
          </button>
        </form>
      )}
    </AuthCard>
  );
};

// =====================================================================
// Reset password screen (?reset=TOKEN в URL)
// =====================================================================

const ResetScreen = ({ token, switchTo }) => {
  const [pw, setPw] = useState("");
  const [pw2, setPw2] = useState("");
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState("");
  const [done, setDone] = useState(false);

  const submit = async (e) => {
    e.preventDefault();
    setErr("");
    if (pw.length < 8) return setErr("Пароль минимум 8 символов");
    if (pw !== pw2) return setErr("Пароли не совпадают");
    if (/^[a-zA-Z]+$/.test(pw) || /^\d+$/.test(pw))
      return setErr("Пароль должен содержать и буквы, и цифры");
    setBusy(true);
    try {
      await window.AUTH.reset(token, pw);
      setDone(true);
      stripQuery();
    } catch (ex) {
      setErr(ex.message || "Ошибка");
    } finally {
      setBusy(false);
    }
  };

  return (
    <AuthCard title="Новый пароль" sub="задайте пароль для аккаунта">
      {done ? (
        <>
          <AuthInfo msg="Пароль обновлён. Теперь войдите с новым паролем."/>
          <button className="btn primary" onClick={() => switchTo("login")} style={{ width: "100%", marginTop: 12 }}>
            К странице входа
          </button>
        </>
      ) : (
        <form onSubmit={submit} autoComplete="on">
          <div className="field">
            <label>Новый пароль</label>
            <input className="input" type="password" autoComplete="new-password" required minLength={8}
              value={pw} onChange={e => setPw(e.target.value)} disabled={busy}/>
          </div>
          <div className="field">
            <label>Повторите</label>
            <input className="input" type="password" autoComplete="new-password" required minLength={8}
              value={pw2} onChange={e => setPw2(e.target.value)} disabled={busy}/>
          </div>
          <AuthError msg={err}/>
          <button className="btn primary" type="submit" disabled={busy} style={{ width: "100%", marginTop: 4 }}>
            {busy ? "..." : "Сохранить"}
          </button>
        </form>
      )}
    </AuthCard>
  );
};

// =====================================================================
// AuthGate — главный компонент. Выбирает screen на основании state.
// =====================================================================

const AuthGate = ({ onLogin }) => {
  // Если в URL ?reset=TOKEN — открываем reset-экран
  const initialReset = readQuery("reset");
  const [screen, setScreen] = useState(initialReset ? "reset" : "login");

  if (screen === "register") return <RegisterScreen onLogin={onLogin} switchTo={setScreen}/>;
  if (screen === "forgot")   return <ForgotScreen switchTo={setScreen}/>;
  if (screen === "reset")    return <ResetScreen token={initialReset} switchTo={(s) => { stripQuery(); setScreen(s); }}/>;
  return <LoginScreen onLogin={onLogin} switchTo={setScreen}/>;
};

// =====================================================================
// Email verification banner (показывается залогиненным с !is_verified)
// =====================================================================

const VerifyBanner = ({ user, onUpdated }) => {
  const [busy, setBusy] = useState(false);
  const [msg, setMsg] = useState("");

  // Если в URL ?verify=TOKEN — попробуем активировать сразу
  useEffect(() => {
    const tok = readQuery("verify");
    if (!tok) return;
    (async () => {
      try {
        await window.AUTH.verifyEmail(tok);
        const fresh = await window.AUTH.me();
        onUpdated(fresh);
        setMsg("✓ Email подтверждён");
      } catch (e) {
        setMsg("⚠ Не удалось подтвердить: " + (e.message || ""));
      } finally {
        stripQuery();
      }
    })();
  }, []);

  if (user.is_verified) return null;

  const resend = async () => {
    setBusy(true); setMsg("");
    try {
      const r = await window.AUTH.resendVerify();
      setMsg(r.sent
        ? "Письмо отправлено. Проверьте почту (и спам)."
        : "SMTP не настроен — ссылка в логе сервера.");
    } catch (e) {
      setMsg("Ошибка: " + (e.message || ""));
    } finally {
      setBusy(false);
    }
  };

  return (
    <div className="verify-banner">
      <Icon name="alert" size={14}/>
      <div style={{ flex: 1 }}>
        <b>Подтвердите email</b> <span style={{ color: "var(--text-3)" }}>·</span>{" "}
        <span style={{ color: "var(--text-2)", fontSize: 12 }}>
          {msg || `Мы отправили ссылку на ${user.email}. Без подтверждения вы не сможете торговать.`}
        </span>
      </div>
      <button className="btn" disabled={busy} onClick={resend} style={{ fontSize: 11, padding: "4px 10px" }}>
        {busy ? "..." : "Отправить снова"}
      </button>
    </div>
  );
};

// =====================================================================
// Account modal — профиль + смена пароля
// =====================================================================

const AccountModal = ({ user, onClose, onLogout }) => {
  const [pwCur, setPwCur] = useState("");
  const [pwNew, setPwNew] = useState("");
  const [pwNew2, setPwNew2] = useState("");
  const [busy, setBusy] = useState(false);
  const [msg, setMsg] = useState({ kind: "", text: "" });

  const changePw = async (e) => {
    e.preventDefault();
    setMsg({ kind: "", text: "" });
    if (pwNew.length < 8) return setMsg({ kind: "err", text: "Минимум 8 символов" });
    if (pwNew !== pwNew2) return setMsg({ kind: "err", text: "Пароли не совпадают" });
    setBusy(true);
    try {
      await window.AUTH.changePassword(pwCur, pwNew);
      setPwCur(""); setPwNew(""); setPwNew2("");
      setMsg({ kind: "ok", text: "✓ Пароль обновлён" });
    } catch (ex) {
      setMsg({ kind: "err", text: ex.message || "Ошибка" });
    } finally {
      setBusy(false);
    }
  };

  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal" style={{ width: "min(480px, 92vw)" }} onClick={e => e.stopPropagation()}>
        <div className="modal-head">
          <h2><Icon name="settings" size={14}/> Аккаунт</h2>
          <button className="icon-btn" onClick={onClose}><Icon name="x" size={14}/></button>
        </div>
        <div className="modal-body">
          <div style={{ display: "grid", gridTemplateColumns: "1fr 1fr", gap: 10, marginBottom: 14 }}>
            <div className="stat-card">
              <div className="stat-label">Email</div>
              <div className="mono" style={{ fontSize: 12, wordBreak: "break-all" }}>{user.email}</div>
            </div>
            <div className="stat-card">
              <div className="stat-label">Статус</div>
              <div className="mono" style={{ fontSize: 12 }}>
                <span className={user.is_verified ? "pos" : "neg"}>
                  {user.is_verified ? "✓ verified" : "⚠ unverified"}
                </span>
                <span style={{ color: "var(--text-3)", marginLeft: 6 }}>· {user.role}</span>
              </div>
            </div>
          </div>

          <div style={{ borderTop: "1px solid var(--border)", paddingTop: 14 }}>
            <div className="section-title" style={{ marginBottom: 10 }}>
              <Icon name="lock" size={11}/> Сменить пароль
            </div>
            <form onSubmit={changePw}>
              <div className="field">
                <label>Текущий пароль</label>
                <input className="input" type="password" required value={pwCur}
                       onChange={e => setPwCur(e.target.value)} disabled={busy}/>
              </div>
              <div className="field">
                <label>Новый пароль</label>
                <input className="input" type="password" required minLength={8} value={pwNew}
                       onChange={e => setPwNew(e.target.value)} disabled={busy}/>
              </div>
              <div className="field">
                <label>Повторите</label>
                <input className="input" type="password" required minLength={8} value={pwNew2}
                       onChange={e => setPwNew2(e.target.value)} disabled={busy}/>
              </div>
              {msg.text && (
                <div className={msg.kind === "err" ? "auth-error" : "auth-info"}>{msg.text}</div>
              )}
              <button className="btn primary" type="submit" disabled={busy} style={{ width: "100%", marginTop: 4 }}>
                {busy ? "..." : "Сохранить"}
              </button>
            </form>
          </div>
        </div>
        <div className="modal-foot">
          <button className="btn ghost" onClick={onClose}>Закрыть</button>
          <button className="btn" onClick={onLogout}><Icon name="arrowRight" size={12}/> Выйти</button>
        </div>
      </div>
    </div>
  );
};

// =====================================================================
// Admin panel (модалка)
// =====================================================================

const AdminPanel = ({ currentUserId, onClose }) => {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [err, setErr] = useState("");

  const reload = async () => {
    setLoading(true); setErr("");
    try { setUsers(await window.AUTH.adminListUsers()); }
    catch (e) { setErr(e.message || "Ошибка"); }
    finally { setLoading(false); }
  };
  useEffect(() => { reload(); }, []);

  const toggleRole = async (u) => {
    const next = u.role === "admin" ? "user" : "admin";
    if (!confirm(`Сменить роль ${u.email} на ${next}?`)) return;
    try { await window.AUTH.adminUpdateUser(u.id, { role: next }); await reload(); }
    catch (e) { alert(e.message || "Ошибка"); }
  };
  const toggleVerify = async (u) => {
    try { await window.AUTH.adminUpdateUser(u.id, { is_verified: !u.is_verified }); await reload(); }
    catch (e) { alert(e.message || "Ошибка"); }
  };
  const del = async (u) => {
    if (!confirm(`Удалить ${u.email}? Действие необратимо.`)) return;
    try { await window.AUTH.adminDeleteUser(u.id); await reload(); }
    catch (e) { alert(e.message || "Ошибка"); }
  };

  return (
    <div className="modal-backdrop" onClick={onClose}>
      <div className="modal" style={{ width: "min(880px, 95vw)", maxHeight: "85vh", display: "flex", flexDirection: "column" }}
           onClick={e => e.stopPropagation()}>
        <div className="modal-head">
          <h2><Icon name="settings" size={14}/> Админка · {users.length} {users.length === 1 ? "юзер" : "юзеров"}</h2>
          <button className="icon-btn" onClick={onClose}><Icon name="x" size={14}/></button>
        </div>
        <div className="modal-body" style={{ overflowY: "auto" }}>
          {err && <div className="auth-error">{err}</div>}
          {loading ? <SkeletonRows rows={5} cols={5}/> : (
            <div className="card" style={{ overflow: "auto" }}>
              <table className="tbl">
                <thead>
                  <tr>
                    <th>Email</th>
                    <th>Роль</th>
                    <th>Verified</th>
                    <th>Создан</th>
                    <th>Действия</th>
                  </tr>
                </thead>
                <tbody>
                  {users.map(u => (
                    <tr key={u.id}>
                      <td><span className="mono" style={{ fontSize: 12 }}>{u.email}</span>
                        {u.id === currentUserId && <span style={{ marginLeft: 6, color: "var(--text-4)", fontSize: 10 }}>(вы)</span>}
                      </td>
                      <td>
                        <span className={"pill " + (u.role === "admin" ? "warn" : "")}>{u.role}</span>
                      </td>
                      <td>
                        <span className={u.is_verified ? "pos" : "neg"} style={{ fontSize: 12 }}>
                          {u.is_verified ? "✓" : "—"}
                        </span>
                      </td>
                      <td className="mono muted" style={{ fontSize: 11 }}>{fmtTime(u.created_at)}</td>
                      <td>
                        <button className="btn" style={{ fontSize: 11, padding: "3px 8px" }}
                                onClick={() => toggleRole(u)}>
                          {u.role === "admin" ? "↓ user" : "↑ admin"}
                        </button>
                        <button className="btn" style={{ fontSize: 11, padding: "3px 8px", marginLeft: 4 }}
                                onClick={() => toggleVerify(u)}>
                          {u.is_verified ? "unverify" : "verify"}
                        </button>
                        {u.id !== currentUserId && (
                          <button className="btn" style={{ fontSize: 11, padding: "3px 8px", marginLeft: 4, color: "var(--short)", borderColor: "var(--short-dim)" }}
                                  onClick={() => del(u)}>
                            <Icon name="x" size={10}/> del
                          </button>
                        )}
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          )}
        </div>
        <div className="modal-foot">
          <button className="btn ghost" onClick={onClose}>Закрыть</button>
          <button className="btn" onClick={reload}><Icon name="refresh" size={12}/> Обновить</button>
        </div>
      </div>
    </div>
  );
};

Object.assign(window, {
  AuthGate, VerifyBanner, AccountModal, AdminPanel,
});
