// Login page — static SPA, no import/export, globals: React, useT, useLang, navigateTo, useAuth, PBNav, PBFooter, PBLogo

const LoginPage = () => {
  const t = useT();
  const lang = useLang();
  const a = t.auth.login;
  const errs = t.auth.errors;
  const { login, user } = useAuth();

  React.useEffect(() => {
    // Only redirect off /login if we're STILL on /login. Without this guard,
    // a successful onSubmit() race between the user-state update and the
    // explicit navigateTo() ends with the user on /dashboard instead of the
    // captured `next` path. (M3.8c / Pro2 bug.)
    if (user && (window.location.hash || '').startsWith('#/login')) {
      navigateTo(getNextPath() || '/dashboard');
    }
  }, [user]);

  const [form, setForm] = React.useState({ email: '', password: '', rememberMe: false });
  const [errors, setErrors] = React.useState({});
  const [banner, setBanner] = React.useState(null);
  const [submitting, setSubmitting] = React.useState(false);
  const [providers, setProviders] = React.useState({ github: { enabled: false, authUrl: null } });

  // Probe which OAuth providers are configured server-side; conditionally
  // render the GitHub button only when GITHUB_OAUTH_* env vars are set.
  React.useEffect(() => {
    let cancelled = false;
    fetch('/api/auth/providers', { credentials: 'same-origin' })
      .then((r) => (r.ok ? r.json() : { providers: {} }))
      .then((d) => { if (!cancelled && d && d.providers) setProviders(d.providers); })
      .catch(() => {});
    return () => { cancelled = true; };
  }, []);

  const setField = (k) => (e) => {
    const v = e.target.type === 'checkbox' ? e.target.checked : e.target.value;
    setForm((f) => ({ ...f, [k]: v }));
    setErrors((er) => ({ ...er, [k]: undefined }));
  };

  const onSubmit = async (e) => {
    e.preventDefault();
    setBanner(null);
    setErrors({});
    if (!form.email) { setErrors({ email: errs.required }); return; }
    if (!form.password) { setErrors({ password: errs.required }); return; }
    // Capture the next path BEFORE await login() — once cookie sets and the
    // user state propagates, the useEffect above may also navigate, and we
    // must not lose the original `next` query.
    const nextPath = getNextPath() || '/dashboard';
    setSubmitting(true);
    try {
      await login(form);
      navigateTo(nextPath);
    } catch (err) {
      if (err && err.status === 401) {
        setBanner(errs.wrong_credentials);
      } else if (err && err.status === 423) {
        const mins = Math.max(1, Math.ceil((err.retryAfter || 300) / 60));
        setBanner(typeof errs.locked_minutes === 'function' ? errs.locked_minutes(mins) : errs.account_locked);
      } else if (err && err.status === 429) {
        setBanner(errs.rate_limited);
      } else if (err && err.status === 400 && err.fields) {
        const mapped = {};
        Object.entries(err.fields).forEach(([k, code]) => { mapped[k] = errs[code] || errs.unknown; });
        setErrors(mapped);
      } else {
        setBanner(errs.network);
      }
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <div className="pb-scroll">
      <PBNav />
      <div className="pb-auth-shell">
        <div className="pb-auth-card" data-testid="login-card">
          <div style={{ marginBottom: 12 }}><PBLogo size={36} /></div>
          <h1 className="pb-auth-title">{a.title}</h1>
          <p className="pb-auth-sub">{a.sub}</p>

          {banner && (
            <div className="pb-auth-banner error" data-testid="login-banner">{banner}</div>
          )}

          <form className="pb-auth-form" onSubmit={onSubmit} noValidate>
            <div>
              <label className="pb-label" htmlFor="login-email">{a.email}</label>
              <input
                id="login-email"
                className="pb-input"
                type="email"
                autoComplete="email"
                value={form.email}
                onChange={setField('email')}
                data-testid="login-email"
                required
              />
              {errors.email && <div className="pb-auth-error">{errors.email}</div>}
            </div>

            <div>
              <label className="pb-label" htmlFor="login-password">{a.password}</label>
              <input
                id="login-password"
                className="pb-input"
                type="password"
                autoComplete="current-password"
                value={form.password}
                onChange={setField('password')}
                data-testid="login-password"
                required
              />
              {errors.password && <div className="pb-auth-error">{errors.password}</div>}
            </div>

            <label className="pb-auth-checkbox">
              <input type="checkbox" checked={form.rememberMe} onChange={setField('rememberMe')} />
              <span>{a.remember}</span>
            </label>

            <button
              type="submit"
              className="pb-btn pb-btn-primary"
              style={{ marginTop: 8 }}
              disabled={submitting}
              data-testid="login-submit"
            >
              {submitting ? a.submitting : a.submit}
            </button>
          </form>

          {providers.github && providers.github.enabled && (
            <div data-testid="login-oauth" style={{ marginTop: 20 }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 12, color: 'var(--pb-fg-muted)', fontSize: 12, margin: '12px 0' }}>
                <div style={{ flex: 1, height: 1, background: 'var(--pb-border)' }}/>
                <span>{t.auth.oauth.or}</span>
                <div style={{ flex: 1, height: 1, background: 'var(--pb-border)' }}/>
              </div>
              <a
                href={providers.github.authUrl + '?next=' + encodeURIComponent(getNextPath() || '/dashboard')}
                className="pb-btn pb-btn-ghost"
                data-testid="login-oauth-github"
                style={{ width: '100%', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 8, textDecoration: 'none' }}
              >
                <svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
                  <path d="M12 .5C5.65.5.5 5.65.5 12c0 5.08 3.29 9.39 7.86 10.91.58.1.79-.25.79-.56 0-.28-.01-1.02-.02-2-3.2.7-3.87-1.54-3.87-1.54-.52-1.33-1.27-1.69-1.27-1.69-1.04-.71.08-.7.08-.7 1.15.08 1.76 1.18 1.76 1.18 1.02 1.75 2.68 1.24 3.34.95.1-.74.4-1.24.72-1.53-2.55-.29-5.24-1.28-5.24-5.69 0-1.26.45-2.29 1.18-3.1-.12-.29-.51-1.46.11-3.04 0 0 .96-.31 3.15 1.18a10.93 10.93 0 0 1 5.74 0c2.19-1.49 3.15-1.18 3.15-1.18.62 1.58.23 2.75.11 3.04.74.81 1.18 1.84 1.18 3.1 0 4.42-2.69 5.39-5.25 5.68.41.36.78 1.05.78 2.12 0 1.53-.01 2.76-.01 3.13 0 .31.21.67.8.55C20.21 21.39 23.5 17.08 23.5 12 23.5 5.65 18.35.5 12 .5z"/>
                </svg>
                {t.auth.oauth.signinGithub}
              </a>
            </div>
          )}

          <div className="pb-auth-meta" style={{ marginTop: 24 }}>
            {a.no_account_q}{' '}
            <span
              className="pb-link"
              onClick={() => navigateTo('/register' + currentNextSuffix())}
              data-testid="login-to-register"
            >
              {a.sign_up_link}
            </span>
          </div>
        </div>
      </div>
      <PBFooter />
    </div>
  );
};

function getNextPath() {
  const h = window.location.hash || '';
  const qi = h.indexOf('?');
  if (qi < 0) return null;
  const params = new URLSearchParams(h.slice(qi + 1));
  const next = params.get('next');
  if (!next) return null;
  const decoded = decodeURIComponent(next);
  return decoded.startsWith('#') ? decoded.slice(1) : decoded;
}

function currentNextSuffix() {
  const next = getNextPath();
  return next ? '?next=' + encodeURIComponent('#' + next) : '';
}

window.LoginPage = LoginPage;
