// MobileLogin.jsx — mobile-optimized terminal login with Turnstile, MFA, reveal animation
// SECURITY: same generic error messages as desktop. No user enumeration.

const MobileLogin = ({ onLoggedIn, onSwitchToRegister }) => {
  const [email, setEmail] = React.useState('');
  const [password, setPassword] = React.useState('');
  const [phase, setPhase] = React.useState('idle'); // idle | submitting | mfa | revealing | granted | denied
  const [err, setErr] = React.useState(null);
  const [scrambled, setScrambled] = React.useState({ handle: '', email: '', tier: '' });
  const [deniedInfo, setDeniedInfo] = React.useState({ lockout: 3, attempt: 1 });
  const [turnstileToken, setTurnstileToken] = React.useState(null);
  const [mfaCode, setMfaCode] = React.useState('');
  const [mfaMode, setMfaMode] = React.useState('totp');
  const [mfaMethods, setMfaMethods] = React.useState([]);
  const [mfaErr, setMfaErr] = React.useState(null);
  const [mfaSubmitting, setMfaSubmitting] = React.useState(false);
  const [resolvedUser, setResolvedUser] = React.useState(null);
  const turnstileWidgetId = React.useRef(null);
  const [attempts, setAttempts] = React.useState(0);

  // Turnstile widget lifecycle
  React.useEffect(() => {
    if (phase === 'idle' && window.turnstile) {
      if (turnstileWidgetId.current != null) {
        try { window.turnstile.remove(turnstileWidgetId.current); } catch (e) { /* noop */ }
        turnstileWidgetId.current = null;
      }
      const el = document.getElementById('m-login-turnstile');
      if (!el) return;
      turnstileWidgetId.current = window.turnstile.render('#m-login-turnstile', {
        sitekey: '0x4AAAAAADT5ebjsA6gd7yaa',
        theme: 'dark',
        callback: (token) => setTurnstileToken(token),
        'expired-callback': () => setTurnstileToken(null),
        'error-callback': () => setTurnstileToken(null),
      });
    }
    return () => {
      if (turnstileWidgetId.current != null) {
        try { window.turnstile.remove(turnstileWidgetId.current); } catch (e) { /* noop */ }
        turnstileWidgetId.current = null;
      }
    };
  }, [phase]);

  const beginReveal = (user) => {
    setResolvedUser(user);
    setPhase('revealing');
    scrambleTo('handle', user.handle || user.email, 1300);
    scrambleTo('email', user.email, 1500);
    scrambleTo('tier', user.tier || 'OPERATOR', 1100);
    setTimeout(() => setPhase('granted'), 1700);
    setTimeout(() => onLoggedIn(user), 2700);
  };

  const triggerDenied = () => {
    setDeniedInfo({ lockout: 3, attempt: attempts + 1 });
    setPhase('denied');
    let n = 3;
    const tick = setInterval(() => {
      n -= 1;
      setDeniedInfo((d) => ({ ...d, lockout: n }));
      if (n <= 0) {
        clearInterval(tick);
        setTimeout(() => { setPhase('idle'); setPassword(''); setTurnstileToken(null); }, 400);
      }
    }, 1000);
  };

  const submit = async (e) => {
    e.preventDefault();
    if (phase !== 'idle') return;
    setErr(null);

    if (!email.trim() || !password) { setErr('// missing input. supply both fields.'); return; }
    if (email.length > 320 || password.length > 1000) { setErr('// payload too large.'); return; }
    if (!turnstileToken && window.OBC_API.mode !== 'mock') { setErr('// captcha verification required.'); return; }

    setPhase('submitting');
    setAttempts((a) => a + 1);

    try {
      const result = await window.OBC_API.login(email, password, turnstileToken);
      if (result && result.mfa_required) {
        setMfaMethods(result.methods || ['totp']);
        if (result.methods?.includes('passkey') && window.OBC_WebAuthn?.isSupported()) {
          setMfaMode('passkey');
        } else {
          setMfaMode('totp');
        }
        setPhase('mfa');
        return;
      }
      beginReveal(result);
    } catch (error) {
      triggerDenied();
    }
  };

  const submitMfa = async (e) => {
    if (e) e.preventDefault();
    if (mfaSubmitting) return;
    setMfaErr(null);

    if (mfaMode === 'passkey') {
      setMfaSubmitting(true);
      try {
        const result = await window.OBC_API.verifyMfaPasskey();
        if (result.customer) { beginReveal(result.customer); }
        else { setMfaErr('// passkey verification failed.'); }
      } catch (error) {
        if (error.name === 'NotAllowedError') { setMfaErr('// passkey prompt cancelled.'); }
        else { setMfaErr('// passkey verification failed.'); }
      } finally { setMfaSubmitting(false); }
      return;
    }

    const code = mfaCode.trim();
    const isRecovery = mfaMode === 'recovery';
    if (!code) { setMfaErr('// enter a code.'); return; }
    if (!isRecovery && (code.length !== 6 || !/^\d{6}$/.test(code))) {
      setMfaErr('// TOTP code must be 6 digits.'); return;
    }

    setMfaSubmitting(true);
    try {
      const result = await window.OBC_API.verifyMfa(code, isRecovery, mfaMode);
      if (result.customer) { beginReveal(result.customer); }
      else { setMfaErr('// verification failed. try again.'); }
    } catch (error) {
      setMfaErr('// verification failed. try again.');
    } finally { setMfaSubmitting(false); }
  };

  const scrambleTo = (key, target, dur) => {
    const chars = '!@#$%^&*()_+-={}[]|:;<>,.?/~`ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
    const start = Date.now();
    const tick = () => {
      const elapsed = Date.now() - start;
      const t = Math.min(elapsed / dur, 1);
      const locked = Math.floor(t * target.length);
      let out = '';
      for (let i = 0; i < target.length; i++) {
        if (i < locked) out += target[i];
        else if (target[i] === ' ' || target[i] === '@' || target[i] === '-' || target[i] === '.') out += target[i];
        else out += chars[Math.floor(Math.random() * chars.length)];
      }
      setScrambled((s) => ({ ...s, [key]: out }));
      if (t < 1) requestAnimationFrame(tick);
    };
    tick();
  };

  const isMock = window.OBC_API.mode === 'mock';
  const canSubmit = turnstileToken || isMock;

  return (
    <section style={{ padding: '24px 16px 60px', maxWidth: 480, margin: '0 auto' }}>
      {/* IDLE — login form */}
      {phase === 'idle' && (
        <form onSubmit={submit}>
          <div style={{ fontSize: 11, color: '#00FF41', letterSpacing: '0.22em', marginBottom: 8 }}>$ ./auth --login</div>
          <h2 style={{ fontSize: 26, fontWeight: 800, color: '#FFF', letterSpacing: '0.04em', margin: '0 0 6px' }}>AUTHENTICATE</h2>
          <p style={{ fontSize: 12, color: '#BFBFBF', lineHeight: 1.6, letterSpacing: '0.04em', margin: '0 0 24px' }}>
            // identify yourself to access /account.
          </p>

          <MField label="HANDLE OR EMAIL" value={email} onChange={setEmail} placeholder="operator@brew-co" autoFocus autoComplete="username" />
          <MField label="PASSWORD" value={password} onChange={setPassword} type="password" placeholder="••••••••••••" autoComplete="current-password" />

          {/* Turnstile */}
          <div style={{ margin: '16px 0', padding: '12px', border: '1px dashed rgba(255,255,255,0.22)', background: '#0A0A0A' }}>
            <div style={{ fontSize: 10, letterSpacing: '0.2em', color: '#9A9A9A', marginBottom: 8 }}>// CAPTCHA VERIFICATION</div>
            <div id="m-login-turnstile"></div>
          </div>

          {err && (
            <div role="alert" style={{ marginTop: 14, padding: '10px 14px', border: '1px solid #FF3344', color: '#FF3344', fontSize: 12, letterSpacing: '0.06em' }}>
              {err}
            </div>
          )}

          <button type="submit" disabled={!canSubmit} style={{
            width: '100%', marginTop: 20, background: canSubmit ? '#00FF41' : '#3A3A3A',
            color: '#000', border: '1px solid ' + (canSubmit ? '#00FF41' : '#3A3A3A'),
            padding: '16px', fontFamily: 'inherit', fontWeight: 800, fontSize: 14,
            letterSpacing: '0.22em', cursor: canSubmit ? 'pointer' : 'not-allowed',
            borderRadius: 2, opacity: canSubmit ? 1 : 0.5, minHeight: 52,
          }}>{'>'} ./execute</button>

          <div style={{ marginTop: 16, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
            <span onClick={onSwitchToRegister} style={{ fontSize: 12, color: '#00FF41', cursor: 'pointer', letterSpacing: '0.1em' }}>
              $ ./register
            </span>
            <span onClick={() => setErr('// recovery link sent — if the account exists.')} style={{ fontSize: 12, color: '#BFBFBF', cursor: 'pointer', letterSpacing: '0.1em' }}>
              ./forgot
            </span>
          </div>
        </form>
      )}

      {/* SUBMITTING — spinner */}
      {phase === 'submitting' && (
        <div style={{ color: '#00FF41', fontSize: 13, lineHeight: 1.9, letterSpacing: '0.04em', padding: '40px 0' }}>
          <div>$ ./auth --execute</div>
          <div>&nbsp;&nbsp;resolving identity ........ <span style={{ color: '#00FF41' }}>[ OK ]</span></div>
          <div>&nbsp;&nbsp;hashing credentials ....... <span style={{ color: '#00FF41' }}>[ OK ]</span></div>
          <div>&nbsp;&nbsp;verifying session ......... <span style={{ color: '#FFD23F' }}>[OK]</span></div>
          <div style={{ marginTop: 8, color: '#BFBFBF' }}>// stand by<MobileCursor /></div>
        </div>
      )}

      {/* MFA — passkey / TOTP / recovery */}
      {phase === 'mfa' && (
        <form onSubmit={submitMfa}>
          <div style={{ fontSize: 11, color: '#FFD23F', letterSpacing: '0.22em', marginBottom: 14 }}>$ ./auth --mfa-verify</div>
          <div style={{ fontSize: 12, color: '#BFBFBF', lineHeight: 1.7, marginBottom: 20 }}>
            {'>'} {mfaMode === 'passkey' ? 'use your passkey to authenticate'
              : mfaMode === 'totp' ? 'enter 6-digit TOTP code'
              : 'enter 8-character recovery code'}
          </div>

          {mfaMode === 'passkey' && (
            <div style={{ textAlign: 'center', padding: '24px 0' }}>
              <div style={{ fontSize: 36, marginBottom: 14 }}>&#x1F511;</div>
              <button type="button" onClick={submitMfa} disabled={mfaSubmitting} style={{
                width: '100%', background: mfaSubmitting ? '#3A3A3A' : '#00E5FF',
                color: '#000', border: '1px solid ' + (mfaSubmitting ? '#3A3A3A' : '#00E5FF'),
                padding: '16px', fontFamily: 'inherit', fontWeight: 800, fontSize: 14,
                letterSpacing: '0.22em', cursor: mfaSubmitting ? 'not-allowed' : 'pointer',
                borderRadius: 2, opacity: mfaSubmitting ? 0.5 : 1, minHeight: 52,
              }}>{mfaSubmitting ? '// authenticating...' : '> ./use-passkey'}</button>
            </div>
          )}

          {mfaMode === 'totp' && (
            <div style={{ marginBottom: 16 }}>
              <div style={{ fontSize: 11, letterSpacing: '0.22em', color: '#E0E0E0', fontWeight: 700, marginBottom: 6 }}>{'>'} TOTP CODE</div>
              <input
                value={mfaCode}
                onChange={(e) => { setMfaCode(e.target.value.replace(/\D/g, '').slice(0, 6)); setMfaErr(null); }}
                maxLength={6} pattern="[0-9]*" inputMode="numeric" autoComplete="one-time-code" autoFocus placeholder="000000"
                style={{ width: '100%', background: '#0A0A0A', border: '1px solid rgba(255,255,255,0.28)', color: '#FFF', fontFamily: 'inherit', fontSize: 24, padding: '14px', borderRadius: 2, letterSpacing: '0.3em', textAlign: 'center', minHeight: 52 }}
                onFocus={(e) => { e.target.style.borderColor = '#00FF41'; e.target.style.boxShadow = '0 0 0 1px #00FF41'; }}
                onBlur={(e) => { e.target.style.borderColor = 'rgba(255,255,255,0.28)'; e.target.style.boxShadow = 'none'; }}
              />
            </div>
          )}

          {mfaMode === 'recovery' && (
            <div style={{ marginBottom: 16 }}>
              <div style={{ fontSize: 11, letterSpacing: '0.22em', color: '#E0E0E0', fontWeight: 700, marginBottom: 6 }}>{'>'} RECOVERY CODE</div>
              <input
                value={mfaCode}
                onChange={(e) => { setMfaCode(e.target.value.toLowerCase().slice(0, 8)); setMfaErr(null); }}
                maxLength={8} autoComplete="off" autoFocus placeholder="abcd1234"
                style={{ width: '100%', background: '#0A0A0A', border: '1px solid rgba(255,255,255,0.28)', color: '#FFF', fontFamily: 'inherit', fontSize: 24, padding: '14px', borderRadius: 2, letterSpacing: '0.3em', textAlign: 'center', minHeight: 52 }}
                onFocus={(e) => { e.target.style.borderColor = '#00FF41'; e.target.style.boxShadow = '0 0 0 1px #00FF41'; }}
                onBlur={(e) => { e.target.style.borderColor = 'rgba(255,255,255,0.28)'; e.target.style.boxShadow = 'none'; }}
              />
            </div>
          )}

          {mfaErr && (
            <div role="alert" style={{ marginBottom: 14, padding: '10px 14px', border: '1px solid #FF3344', color: '#FF3344', fontSize: 12, letterSpacing: '0.06em' }}>
              {mfaErr}
            </div>
          )}

          {mfaMode !== 'passkey' && (
            <button type="submit" disabled={mfaSubmitting} style={{
              width: '100%', background: mfaSubmitting ? '#3A3A3A' : '#00FF41',
              color: '#000', border: '1px solid ' + (mfaSubmitting ? '#3A3A3A' : '#00FF41'),
              padding: '16px', fontFamily: 'inherit', fontWeight: 800, fontSize: 14,
              letterSpacing: '0.22em', cursor: mfaSubmitting ? 'not-allowed' : 'pointer',
              borderRadius: 2, opacity: mfaSubmitting ? 0.5 : 1, minHeight: 52,
            }}>{mfaSubmitting ? '// verifying...' : '> ./verify'}</button>
          )}

          {/* Method switcher — horizontal pills */}
          <div style={{ marginTop: 16, display: 'flex', gap: 8, flexWrap: 'wrap', justifyContent: 'center' }}>
            {mfaMode !== 'passkey' && mfaMethods.includes('passkey') && window.OBC_WebAuthn?.isSupported() && (
              <MfaPill active={false} onClick={() => { setMfaMode('passkey'); setMfaCode(''); setMfaErr(null); }} color="#00E5FF">passkey</MfaPill>
            )}
            {mfaMode !== 'totp' && mfaMethods.includes('totp') && (
              <MfaPill active={false} onClick={() => { setMfaMode('totp'); setMfaCode(''); setMfaErr(null); }} color="#BFBFBF">TOTP</MfaPill>
            )}
            {mfaMode !== 'recovery' && (
              <MfaPill active={false} onClick={() => { setMfaMode('recovery'); setMfaCode(''); setMfaErr(null); }} color="#BFBFBF">recovery</MfaPill>
            )}
          </div>
        </form>
      )}

      {/* DENIED — simplified flash + cooldown */}
      {phase === 'denied' && (
        <div className="m-denied-shake" style={{ padding: '40px 0', textAlign: 'center' }}>
          <div style={{ padding: '20px', border: '2px solid #FF3344', background: 'rgba(255,51,68,0.06)', marginBottom: 20 }}>
            <span className="m-denied-flash">[ ACCESS DENIED ]</span>
          </div>
          <div style={{ fontSize: 12, color: '#FF3344', letterSpacing: '0.15em', fontWeight: 700, marginBottom: 14 }}>
            // CREDENTIALS REJECTED
          </div>
          <div style={{ padding: '12px 16px', border: '1px solid #FF3344', background: '#000', fontSize: 12, color: '#FFFFFF', letterSpacing: '0.06em', lineHeight: 1.7 }}>
            // authentication failed.<br />
            // <span style={{ color: '#FFD23F' }}>cooldown: {String(Math.max(0, deniedInfo.lockout)).padStart(2, '0')}s</span>
          </div>
        </div>
      )}

      {/* REVEALING + GRANTED — scramble animation */}
      {(phase === 'revealing' || phase === 'granted') && (
        <div style={{ padding: '40px 0' }}>
          <div style={{ fontSize: 11, color: '#00FF41', letterSpacing: '0.22em', marginBottom: 18 }}>$ whoami</div>
          <MobileIdentityRow label="HANDLE" value={scrambled.handle || '████████'} accent="#00FF41" />
          <MobileIdentityRow label="EMAIL" value={scrambled.email || '████████████████████'} accent="#00E5FF" />
          <MobileIdentityRow label="TIER" value={scrambled.tier || '████████'} accent="#FFD23F" />

          {phase === 'granted' && (
            <div style={{ marginTop: 28, textAlign: 'center' }}>
              <span className="m-login-granted">[ ACCESS GRANTED ]</span>
              <div style={{ marginTop: 12, color: '#BFBFBF', fontSize: 12, letterSpacing: '0.15em' }}>redirecting<MobileCursor /></div>
            </div>
          )}
        </div>
      )}

      <style>{`
        .m-login-granted {
          display: inline-block;
          background: #00FF41; color: #000;
          padding: 10px 20px;
          font-size: 16px; font-weight: 800; letter-spacing: 0.25em;
          box-shadow: 0 0 24px rgba(0,255,65,0.6);
          animation: mGrantedFlash 160ms steps(2) 5;
        }
        @keyframes mGrantedFlash {
          0%, 100% { opacity: 1; }
          50% { opacity: 0.15; }
        }
        .m-denied-flash {
          display: inline-block;
          background: #FF3344; color: #000;
          padding: 12px 20px;
          font-size: 22px; font-weight: 800; letter-spacing: 0.3em;
          box-shadow: 0 0 32px rgba(255,51,68,0.8);
          animation: mDeniedFlash 220ms steps(2) infinite;
        }
        @keyframes mDeniedFlash {
          0%, 100% { opacity: 1; background: #FF3344; color: #000; }
          50%      { opacity: 1; background: #000; color: #FF3344; box-shadow: 0 0 32px rgba(255,51,68,0.4), inset 0 0 0 2px #FF3344; }
        }
        .m-denied-shake { animation: mDeniedShake 120ms ease-out 6; }
        @keyframes mDeniedShake {
          0%, 100% { transform: translate(0,0); }
          25%      { transform: translate(-3px, 1px); }
          50%      { transform: translate(3px, -1px); }
          75%      { transform: translate(-2px, -1px); }
        }
      `}</style>
    </section>
  );
};

const MField = ({ label, value, onChange, type = 'text', placeholder, autoFocus, autoComplete }) => (
  <div style={{ marginBottom: 14 }}>
    <div style={{ fontSize: 11, letterSpacing: '0.22em', color: '#E0E0E0', fontWeight: 700, marginBottom: 6 }}>{'>'} {label}</div>
    <input
      type={type}
      value={value}
      onChange={(e) => onChange(e.target.value)}
      placeholder={placeholder}
      autoFocus={autoFocus}
      autoComplete={autoComplete}
      maxLength={type === 'password' ? 256 : 320}
      style={{
        width: '100%', background: '#0A0A0A', border: '1px solid rgba(255,255,255,0.28)',
        color: '#FFF', fontFamily: 'inherit', fontSize: 16, padding: '14px', borderRadius: 2,
        minHeight: 48,
      }}
      onFocus={(e) => { e.target.style.borderColor = '#00FF41'; e.target.style.boxShadow = '0 0 0 1px #00FF41'; }}
      onBlur={(e) => { e.target.style.borderColor = 'rgba(255,255,255,0.28)'; e.target.style.boxShadow = 'none'; }}
    />
  </div>
);

const MobileIdentityRow = ({ label, value, accent }) => (
  <div style={{ padding: '12px 0', borderBottom: '1px dashed rgba(255,255,255,0.18)' }}>
    <div style={{ fontSize: 10, color: '#BFBFBF', letterSpacing: '0.22em', fontWeight: 700, marginBottom: 4 }}>{label}</div>
    <div style={{ fontSize: 16, color: accent, letterSpacing: '0.06em', fontFamily: 'inherit', fontWeight: 700, wordBreak: 'break-all' }}>{value}</div>
  </div>
);

const MfaPill = ({ children, onClick, color }) => (
  <span onClick={onClick} style={{
    padding: '8px 16px', border: '1px solid ' + color, color: color,
    fontSize: 11, fontWeight: 700, letterSpacing: '0.12em',
    cursor: 'pointer', borderRadius: 2, minHeight: 44,
    display: 'inline-flex', alignItems: 'center',
  }}>// {children}</span>
);

const MobileCursor = () => <span style={{ background: '#00FF41', color: '#000', marginLeft: 4, padding: '0 4px' }}>_</span>;

window.MobileLogin = MobileLogin;
