// CalGrillz — Login (email + password OR email + OTP code).
//
// Customers without a password fall back to the code path automatically.
// Mode toggle lives at the top of the right-hand form column.

function CGWLoginPage() {
  // mode: 'password' | 'code'.   step: 'enter' | 'otp' | 'twofa'
  const [mode, setMode] = useState('password');
  const [step, setStep] = useState('enter');
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [otp, setOtp] = useState(['','','','','','']);
  const [error, setError] = useState('');
  const [info, setInfo]  = useState('');
  const [busy, setBusy]  = useState(false);
  const [resendIn, setResendIn] = useState(0);
  const refs = useRef([]);
  // 2FA challenge state (set when the server asks for a second factor).
  const [twoFa, setTwoFa] = useState(null);   // { method, label, emailHint }
  const [twoFaCode, setTwoFaCode] = useState('');

  const URLS = window.CG_URLS || {};
  const CSRF = URLS.csrf || '';

  // Optional return-to path after login (e.g. arriving from the public live
  // draw as ?next=/draw/38). Same-origin ROOT-relative paths only — never an
  // absolute or //host URL — so it can't be used as an open redirect.
  const safeNext = () => {
    try {
      const n = new URLSearchParams(window.location.search).get('next');
      // Must be a plain root-relative path: starts '/', not '//' or '/\', and no
      // backslash / control chars (browsers normalise those into '//host'). Then
      // confirm it still resolves to THIS origin. Blocks open-redirect payloads
      // like /%5Cevil.com or /%09/evil.com.
      if (!n || n.charAt(0) !== '/' || n.charAt(1) === '/' || /[\\\t\n\r\x00]/.test(n)) return null;
      const u = new URL(n, window.location.origin);
      return u.origin === window.location.origin ? (u.pathname + u.search + u.hash) : null;
    } catch (e) {}
    return null;
  };

  useEffect(() => {
    if (resendIn > 0) {
      const t = setInterval(() => setResendIn(s => Math.max(0, s - 1)), 1000);
      return () => clearInterval(t);
    }
  }, [resendIn]);

  const emailValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.trim());

  async function signInWithPassword() {
    setError('');
    if (! emailValid) { setError('Enter your email.'); return; }
    if (! password) { setError('Enter your password.'); return; }
    setBusy(true);
    try {
      const res = await fetch(URLS.loginPassword || '/login/password', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', 'X-CSRF-TOKEN': CSRF },
        body: JSON.stringify({ email: email.trim(), password }),
      });
      const data = await res.json().catch(() => ({}));
      if (! res.ok || ! data.ok) {
        setError(data.error || 'Email and password do not match.');
        return;
      }
      if (data.two_factor_required) { enterTwoFa(data); return; }
      window.location.href = safeNext() || data.redirect_to || (URLS.rewards || '/');
    } catch (e) {
      setError('Network hiccup. Try once more.');
    } finally { setBusy(false); }
  }

  // A second factor is required — switch to the 2FA challenge step.
  function enterTwoFa(data) {
    setTwoFa({ method: data.method, label: data.method_label || 'code', emailHint: data.email_hint || null });
    setTwoFaCode('');
    setError(''); setInfo('');
    setStep('twofa');
    if (data.method === 'email') setResendIn(30);
  }

  async function submitTwoFa() {
    const code = (twoFaCode || '').trim();
    if (! code) { setError('Enter your code.'); return; }
    setError(''); setBusy(true);
    try {
      const res = await fetch(URLS.login2fa || '/login/2fa', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', 'X-CSRF-TOKEN': CSRF },
        body: JSON.stringify({ code }),
      });
      const data = await res.json().catch(() => ({}));
      if (! res.ok || ! data.ok) {
        setError(data.error || 'That code is not correct.');
        if (data.restart) { setStep('enter'); setTwoFa(null); }
        return;
      }
      window.location.href = safeNext() || data.redirect_to || (URLS.rewards || '/');
    } catch (e) {
      setError('Network hiccup. Try once more.');
    } finally { setBusy(false); }
  }

  async function resendTwoFa() {
    setError(''); setInfo('');
    try {
      const res = await fetch(URLS.login2faResend || '/login/2fa/resend', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', 'X-CSRF-TOKEN': CSRF },
        body: JSON.stringify({}),
      });
      const data = await res.json().catch(() => ({}));
      if (data.restart) { setStep('enter'); setTwoFa(null); setError(data.error || 'Please sign in again.'); return; }
      setResendIn(30);
      setInfo('New code sent to your email.');
    } catch (e) { setError('Could not resend. Try again.'); }
  }

  async function sendCode() {
    setError(''); setInfo('');
    if (! emailValid) { setError('Enter a valid email.'); return; }
    setBusy(true);
    try {
      const res = await fetch(URLS.loginRequest || '/login/request', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', 'X-CSRF-TOKEN': CSRF },
        body: JSON.stringify({ email: email.trim() }),
      });
      const data = await res.json().catch(() => ({}));
      // New / unregistered email → registration is required (name + phone).
      // Hand off to the signup page, carrying the typed email for prefill.
      if (data.needs_registration && data.redirect_to) {
        try { sessionStorage.setItem('cg_signup_email', email.trim()); } catch (e) {}
        window.location.href = data.redirect_to;
        return;
      }
      if (! res.ok || ! data.ok) { setError(data.error || 'Could not send the code.'); return; }
      setMode('code'); setStep('otp');
      setResendIn(30);
      if (data.dev_code) setInfo('Dev mode code: ' + data.dev_code);
      else setInfo('Code sent. Check your inbox (and spam folder).');
      setTimeout(() => refs.current[0]?.focus(), 50);
    } catch (e) {
      setError('Network hiccup. Try once more.');
    } finally { setBusy(false); }
  }

  const setOtpChar = (i, ch) => {
    const v = ch.replace(/\D/g, '').slice(-1);
    const next = [...otp]; next[i] = v; setOtp(next);
    if (v && i < 5) refs.current[i + 1]?.focus();
  };
  const onOtpKey = (i, e) => { if (e.key === 'Backspace' && !otp[i] && i > 0) refs.current[i - 1]?.focus(); };
  const onOtpPaste = (e) => {
    const v = (e.clipboardData.getData('text') || '').replace(/\D/g, '').slice(0, 6).split('');
    if (v.length) {
      const next = ['','','','','',''];
      v.forEach((c, i) => next[i] = c);
      setOtp(next);
      refs.current[Math.min(v.length, 5)]?.focus();
      e.preventDefault();
    }
  };

  async function verify() {
    const code = otp.join('');
    if (code.length !== 6) { setError('Enter all 6 digits.'); return; }
    setError(''); setBusy(true);
    try {
      const res = await fetch(URLS.loginVerify || '/login/verify', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', 'Accept': 'application/json', 'X-CSRF-TOKEN': CSRF },
        body: JSON.stringify({ email: email.trim(), code }),
      });
      const data = await res.json().catch(() => ({}));
      if (data.needs_registration && data.redirect_to) {
        try { sessionStorage.setItem('cg_signup_email', email.trim()); } catch (e) {}
        window.location.href = data.redirect_to;
        return;
      }
      if (! res.ok || ! data.ok) { setError(data.error || 'Wrong code or expired.'); return; }
      if (data.two_factor_required) { enterTwoFa(data); return; }
      window.location.href = safeNext() || data.redirect_to || (URLS.rewards || '/');
    } catch (e) {
      setError('Network hiccup. Try once more.');
    } finally { setBusy(false); }
  }

  // ─── Mode toggle (segmented control) ────────────────────────────────────
  const Toggle = (
    <div style={{
      display: 'flex',
      background: 'var(--charcoal-800)',
      padding: 4,
      borderRadius: 12,
      border: '1px solid var(--charcoal-700)',
      marginTop: 28,
      marginBottom: 24,
    }}>
      {['password', 'code'].map(m => (
        <button
          key={m}
          type="button"
          onClick={() => { setMode(m); setStep('enter'); setError(''); setInfo(''); }}
          style={{
            flex: 1, padding: '10px 14px',
            background: mode === m ? 'var(--ember-500)' : 'transparent',
            color: mode === m ? '#fff' : 'var(--cream-dim)',
            border: 0, borderRadius: 9,
            fontSize: 13, fontWeight: 700, letterSpacing: '0.04em',
            cursor: 'pointer', transition: 'background 0.15s, color 0.15s',
          }}>
          {m === 'password' ? 'Password' : 'Email code'}
        </button>
      ))}
    </div>
  );

  return (
    <CGWPage active="" hideFooter>
      <section className="cgw-login" style={{
        minHeight: 'calc(100vh - 76px)',
        display: 'grid',
        gridTemplateColumns: '1fr 1.1fr',
        alignItems: 'stretch',
      }}>
        {/* LEFT — image */}
        <div className="cgw-login__hero" style={{
          position: 'relative',
          backgroundImage: `url(${CG_ASSET('grill-fire.jpg')})`,
          backgroundSize: 'cover',
          backgroundPosition: 'center',
          minHeight: 600,
          overflow: 'hidden',
        }}>
          <div style={{
            position: 'absolute', inset: 0,
            background: 'linear-gradient(135deg, rgba(10,10,10,0.4) 0%, rgba(10,10,10,0.85) 100%)',
          }}/>
          <div style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>
            {Array.from({ length: 20 }).map((_, i) => (
              <span key={i} className="cg-ember" style={{
                left: `${(i * 37) % 100}%`,
                bottom: `${(i * 23) % 60}%`,
                width: 3 + (i % 3), height: 3 + (i % 3),
                animation: `ember-rise ${3 + (i % 4)}s ease-out ${(i % 6) * 0.4}s infinite`,
              }}/>
            ))}
          </div>
          <div style={{ position: 'relative', padding: 60, height: '100%', display: 'flex', flexDirection: 'column', justifyContent: 'flex-end' }}>
            <div>
              <div className="cgw-eyebrow" style={{ color: 'var(--ember-200)' }}>Pick up where you left off</div>
              <h2 className="cgw-h2" style={{ fontSize: 56, marginTop: 14, color: 'var(--cream)' }}>
                Your rewards,<br/>
                <span className="flame">streak</span>, and<br/>
                vouchers.
              </h2>
              <p style={{ color: 'var(--cream-dim)', fontSize: 16, lineHeight: 1.55, maxWidth: 420, marginTop: 22 }}>
                Sign in with your password, or skip it and we'll email you a 6-digit code.
              </p>
            </div>
          </div>
        </div>

        {/* RIGHT — form */}
        <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 60 }}>
          <div style={{ width: '100%', maxWidth: 440 }}>

            {step === 'enter' && (
              <>
                <div className="cgw-eyebrow ember">Sign in</div>
                <h1 className="cgw-h2" style={{ fontSize: 56, marginTop: 8 }}>
                  Welcome to<br/>the pit.
                </h1>
                <p style={{ color: 'var(--cream-dim)', marginTop: 14, fontSize: 15, lineHeight: 1.5 }}>
                  Use your password or get a one-time code.
                </p>

                {Toggle}

                {/* Real <form> with proper name/autoComplete pairs — without a form
                    container, browsers can't reliably resolve credentials and
                    sometimes offer phone-number suggestions instead of emails. */}
                <form
                  autoComplete="on"
                  onSubmit={(e) => { e.preventDefault(); mode === 'password' ? signInWithPassword() : sendCode(); }}
                >
                <div>
                  <label htmlFor="cg-email" style={{ fontSize: 11, color: 'var(--muted)', letterSpacing: '0.12em', textTransform: 'uppercase', fontWeight: 700 }}>Email</label>
                  <div className="cg-input-wrap" style={{
                    marginTop: 8, display: 'flex', alignItems: 'center',
                    background: 'var(--charcoal-800)',
                    border: '1px solid ' + (error ? 'var(--danger)' : 'var(--charcoal-700)'),
                    borderRadius: 14, padding: '4px 4px 4px 18px',
                  }}>
                    <span style={{ fontSize: 18, marginRight: 12 }}>✉️</span>
                    <input
                      id="cg-email"
                      name="email"
                      type="email"
                      inputMode="email"
                      autoComplete="email"
                      autoCapitalize="off"
                      autoCorrect="off"
                      spellCheck="false"
                      value={email}
                      onChange={(e) => { setEmail(e.target.value); setError(''); }}
                      placeholder="you@example.com"
                      className="cg-input"
                      style={{
                        flex: 1, background: 'transparent', border: 'none', outline: 'none',
                        color: 'var(--cream)', fontFamily: 'var(--font-mono)', fontSize: 16,
                        padding: '16px 0', letterSpacing: '0.04em',
                      }}
                    />
                  </div>
                </div>

                {mode === 'password' && (
                  <div style={{ marginTop: 14 }}>
                    <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'baseline' }}>
                      <label htmlFor="cg-password" style={{ fontSize: 11, color: 'var(--muted)', letterSpacing: '0.12em', textTransform: 'uppercase', fontWeight: 700 }}>Password</label>
                      <button type="button" onClick={() => { setMode('code'); setError(''); }} style={{
                        background: 'transparent', border: 'none', color: 'var(--ember-300)',
                        cursor: 'pointer', fontSize: 12, fontWeight: 700,
                      }}>Forgot it? Get a code →</button>
                    </div>
                    <input
                      id="cg-password"
                      name="password"
                      type="password"
                      autoComplete="current-password"
                      value={password}
                      onChange={(e) => { setPassword(e.target.value); setError(''); }}
                      placeholder="Your password"
                      className="cg-input"
                      style={{
                        width: '100%', marginTop: 8, padding: '16px 18px',
                        background: 'var(--charcoal-800)',
                        border: '1px solid var(--charcoal-700)',
                        borderRadius: 14, color: 'var(--cream)', outline: 'none',
                        fontSize: 15, fontFamily: 'var(--font-mono)',
                      }}
                    />
                  </div>
                )}

                {error && <div style={{ color: 'var(--danger)', fontSize: 12, marginTop: 10, fontWeight: 600 }}>{error}</div>}

                <button
                  type="submit"
                  disabled={busy}
                  className="cgw-btn cgw-btn--primary"
                  style={{ width: '100%', marginTop: 18, justifyContent: 'center', padding: 18, opacity: busy ? 0.6 : 1 }}
                >
                  {busy ? (mode === 'password' ? 'Signing in…' : 'Sending…') : (mode === 'password' ? 'Sign in' : 'Send code')}
                  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"><path d="M5 12h14M13 6l6 6-6 6"/></svg>
                </button>

                <div style={{ marginTop: 18, textAlign: 'center', fontSize: 13, color: 'var(--cream-dim)' }}>
                  Don't have an account?{' '}
                  <a href={CG_URL('signup', '/signup')} style={{ color: 'var(--ember-300)', fontWeight: 700 }}>Sign up</a>
                </div>

                <div style={{ fontSize: 11, color: 'var(--muted)', textAlign: 'center', marginTop: 14, lineHeight: 1.6 }}>
                  By continuing you agree to our<br/>
                  <a href="#" style={{ color: 'var(--cream-dim)' }}>Terms</a> &amp; <a href="#" style={{ color: 'var(--cream-dim)' }}>Privacy policy</a>
                </div>
                </form>
              </>
            )}

            {step === 'otp' && (
              <>
                <button onClick={() => { setStep('enter'); setError(''); setInfo(''); }} style={{
                  background: 'transparent', border: 'none', color: 'var(--cream-dim)',
                  fontSize: 12, fontWeight: 700, letterSpacing: '0.08em', textTransform: 'uppercase',
                  cursor: 'pointer', padding: 0, marginBottom: 22,
                  display: 'flex', alignItems: 'center', gap: 6,
                }}>
                  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round"><path d="M15 18l-6-6 6-6"/></svg>
                  Change email
                </button>

                <div className="cgw-eyebrow ember">Step 2 of 2</div>
                <h1 className="cgw-h2" style={{ fontSize: 56, marginTop: 8 }}>
                  Type the<br/>code we sent.
                </h1>
                <p style={{ color: 'var(--cream-dim)', marginTop: 14, fontSize: 15, lineHeight: 1.5 }}>
                  We emailed <span style={{ color: 'var(--cream)', fontFamily: 'var(--font-mono)' }}>{email}</span> a 6-digit code.
                </p>

                {info && (
                  <div style={{
                    marginTop: 14, padding: '10px 12px',
                    background: 'rgba(216,99,44,0.10)',
                    border: '1px solid rgba(216,99,44,0.4)',
                    borderRadius: 10, color: '#d8632c', fontSize: 12, fontWeight: 600,
                  }}>{info}</div>
                )}

                <div style={{ marginTop: 28, display: 'flex', gap: 8, justifyContent: 'space-between', width: '100%' }}>
                  {otp.map((d, i) => (
                    <input
                      key={i}
                      ref={(el) => refs.current[i] = el}
                      type="text" inputMode="numeric" maxLength={1}
                      value={d}
                      onChange={(e) => setOtpChar(i, e.target.value)}
                      onKeyDown={(e) => onOtpKey(i, e)}
                      onPaste={onOtpPaste}
                      style={{
                        flex: '1 1 0', minWidth: 0, maxWidth: 56, height: 62, padding: 0,
                        background: 'var(--charcoal-800)',
                        border: '1.5px solid ' + (d ? 'var(--ember-500)' : 'var(--charcoal-700)'),
                        borderRadius: 12, textAlign: 'center',
                        fontFamily: 'var(--font-display)',
                        fontSize: 26, color: 'var(--cream)', outline: 'none',
                        boxSizing: 'border-box',
                        transition: 'border-color 0.15s',
                      }}
                    />
                  ))}
                </div>

                {error && <div style={{ color: 'var(--danger)', fontSize: 12, marginTop: 12, fontWeight: 600 }}>{error}</div>}

                <button onClick={verify} disabled={busy} className="cgw-btn cgw-btn--primary" style={{
                  width: '100%', marginTop: 22, justifyContent: 'center', padding: 18,
                  opacity: busy ? 0.6 : 1,
                }}>
                  {busy ? 'Verifying…' : 'Verify & sign in'}
                </button>

                <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 18, fontSize: 12, color: 'var(--muted)' }}>
                  <span>Didn't get it?</span>
                  {resendIn > 0
                    ? <span>Resend in {resendIn}s</span>
                    : <button onClick={() => { setOtp(['','','','','','']); sendCode(); }} style={{ background: 'transparent', border: 'none', color: 'var(--ember-300)', cursor: 'pointer', fontSize: 12, fontWeight: 700, letterSpacing: '0.04em' }}>Resend code</button>
                  }
                </div>
              </>
            )}

            {step === 'twofa' && twoFa && (
              <>
                <div className="cgw-eyebrow ember">Two-factor · security check</div>
                <h1 className="cgw-h2" style={{ fontSize: 52, marginTop: 8 }}>
                  One more<br/>step.
                </h1>
                <p style={{ color: 'var(--cream-dim)', marginTop: 14, fontSize: 15, lineHeight: 1.5 }}>
                  {twoFa.method === 'pin' && <>Enter your account <strong style={{ color: 'var(--cream)' }}>PIN</strong> to finish signing in.</>}
                  {twoFa.method === 'totp' && <>Open your <strong style={{ color: 'var(--cream)' }}>authenticator app</strong> and enter the 6-digit code.</>}
                  {twoFa.method === 'email' && <>We sent a 6-digit code to <span style={{ color: 'var(--cream)', fontFamily: 'var(--font-mono)' }}>{twoFa.emailHint || 'your email'}</span>.</>}
                </p>

                {info && (
                  <div style={{ marginTop: 14, padding: '10px 12px', background: 'rgba(216,99,44,0.10)', border: '1px solid rgba(216,99,44,0.4)', borderRadius: 10, color: '#d8632c', fontSize: 12, fontWeight: 600 }}>{info}</div>
                )}

                <form onSubmit={(e) => { e.preventDefault(); submitTwoFa(); }} style={{ marginTop: 24 }}>
                  <input
                    autoFocus
                    type={twoFa.method === 'pin' ? 'password' : 'text'}
                    inputMode="numeric"
                    autoComplete={twoFa.method === 'totp' ? 'one-time-code' : 'off'}
                    value={twoFaCode}
                    maxLength={8}
                    onChange={(e) => { setTwoFaCode(e.target.value.replace(/\D/g, '')); setError(''); }}
                    placeholder={twoFa.method === 'pin' ? 'Your PIN' : '6-digit code'}
                    style={{
                      width: '100%', padding: '18px', textAlign: 'center', letterSpacing: '0.5em',
                      background: 'var(--charcoal-800)', border: '1.5px solid ' + (error ? 'var(--danger)' : 'var(--charcoal-700)'),
                      borderRadius: 14, color: 'var(--cream)', outline: 'none',
                      fontFamily: 'var(--font-mono)', fontSize: 24,
                    }}
                  />

                  {error && <div style={{ color: 'var(--danger)', fontSize: 12, marginTop: 12, fontWeight: 600 }}>{error}</div>}

                  <button type="submit" disabled={busy} className="cgw-btn cgw-btn--primary" style={{ width: '100%', marginTop: 20, justifyContent: 'center', padding: 18, opacity: busy ? 0.6 : 1 }}>
                    {busy ? 'Verifying…' : 'Verify & sign in'}
                  </button>
                </form>

                <div style={{ display: 'flex', justifyContent: 'space-between', marginTop: 18, fontSize: 12, color: 'var(--muted)' }}>
                  <button onClick={() => { setStep('enter'); setTwoFa(null); setError(''); }} style={{ background: 'transparent', border: 'none', color: 'var(--cream-dim)', cursor: 'pointer', fontSize: 12, fontWeight: 700 }}>← Start over</button>
                  {twoFa.method === 'email' && (resendIn > 0
                    ? <span>Resend in {resendIn}s</span>
                    : <button onClick={resendTwoFa} style={{ background: 'transparent', border: 'none', color: 'var(--ember-300)', cursor: 'pointer', fontSize: 12, fontWeight: 700 }}>Resend code</button>
                  )}
                </div>
              </>
            )}
          </div>
        </div>
      </section>
    </CGWPage>
  );
}

ReactDOM.createRoot(document.getElementById('root')).render(<CGWLoginPage/>);
