/* global React */
const { useState: useLS, useEffect: useLE } = React;

// Password input with a show/hide toggle. Behaves exactly like a normal
// input — pass `value`, `onChange`, `placeholder`, `onKeyDown` etc.
function PasswordInput({ value, onChange, placeholder, onKeyDown, autoFocus }) {
  const [shown, setShown] = useLS(false);
  return (
    <div style={{ position: 'relative' }}>
      <input type={shown ? 'text' : 'password'} value={value}
        onChange={onChange} onKeyDown={onKeyDown} placeholder={placeholder}
        autoFocus={autoFocus}
        style={{ ...authInput, paddingRight: 56 }} />
      <button type="button" onClick={() => setShown(s => !s)}
        aria-label={shown ? 'Hide password' : 'Show password'}
        title={shown ? 'Hide password' : 'Show password'}
        style={{
          position: 'absolute', top: '50%', right: 8, transform: 'translateY(-50%)',
          height: 30, padding: '0 8px', borderRadius: 8,
          background: 'transparent', border: 'none', cursor: 'pointer',
          color: 'var(--c-petrol-800)',
          fontFamily: "'Inter', sans-serif", fontSize: 11, fontWeight: 700,
          letterSpacing: '0.04em', textTransform: 'uppercase',
        }}>
        {shown ? 'Hide' : 'Show'}
      </button>
    </div>
  );
}

function LoginScreen({ onLogin }) {
  const [mode, setMode] = useLS('login'); // 'login' | 'forgot'
  return (
    <div style={{
      position: 'fixed', inset: 0, zIndex: 200,
      background: 'var(--c-cream-100)',
      display: 'flex', alignItems: 'center', justifyContent: 'center',
      padding: 24, boxSizing: 'border-box',
      animation: 'pr-fade-in .2s ease-out',
    }}>
      {/* Subtle texture/wash */}
      <div aria-hidden style={{
        position: 'absolute', inset: 0, pointerEvents: 'none',
        background: 'radial-gradient(60% 50% at 50% 0%, rgba(31, 73, 84, 0.06), transparent 70%)',
      }} />

      <div style={{
        position: 'relative',
        width: '100%', maxWidth: 420,
        background: 'var(--c-cream-50)',
        border: '1px solid var(--border-subtle)',
        borderRadius: 20,
        boxShadow: 'var(--shadow-float-lg)',
        padding: '32px 32px 28px',
        boxSizing: 'border-box',
        display: 'flex', flexDirection: 'column', gap: 20,
      }}>
        {/* Brand mark */}
        <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
          <div style={{
            width: 36, height: 36, borderRadius: 10,
            background: 'var(--c-petrol-800)', color: '#fff',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            fontFamily: "'Suisse Int\\'l', sans-serif", fontWeight: 700, fontSize: 14, letterSpacing: '-0.02em',
          }}>R</div>
          <div style={{
            fontFamily: "'Suisse Int\\'l', sans-serif", fontWeight: 700, fontSize: 16,
            letterSpacing: '-0.01em', color: 'var(--c-ink-800)',
          }}>Project R</div>
        </div>

        {mode === 'login'
          ? <LoginForm onLogin={onLogin} onForgot={() => setMode('forgot')} />
          : <ForgotForm onBack={() => setMode('login')} onDone={() => setMode('login')} />
        }
      </div>
    </div>
  );
}

function LoginForm({ onLogin, onForgot }) {
  const [email, setEmail] = useLS('');
  const [pw, setPw] = useLS('');
  const [touched, setTouched] = useLS(false);
  const [busy, setBusy] = useLS(false);
  const [serverError, setServerError] = useLS('');

  const emailValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
  const pwValid = pw.length > 0;
  const valid = emailValid && pwValid;

  const submit = async () => {
    setTouched(true);
    setServerError('');
    if (!valid || busy) return;
    setBusy(true);
    try {
      const r = await fetch('/api/auth/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email, password: pw }),
      });
      const data = await r.json().catch(() => ({}));
      if (!r.ok) {
        setServerError(data.error === 'invalid_credentials' ? 'Email or password is incorrect.' : 'Could not sign in. Try again.');
        return;
      }
      try { localStorage.setItem('pr.token', data.token); localStorage.setItem('pr.user', JSON.stringify(data.user)); } catch {}
      onLogin(data.user);
    } catch {
      setServerError('Network error. Is the server running?');
    } finally {
      setBusy(false);
    }
  };

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>
      <div>
        <div className="eyebrow" style={{ color: 'var(--c-ink-500)', letterSpacing: '1.5px' }}>Sign in</div>
        <h1 style={{
          margin: '6px 0 0', fontFamily: "'Suisse Int\\'l', sans-serif", fontWeight: 700,
          fontSize: 26, letterSpacing: '-0.02em', color: 'var(--c-ink-800)',
        }}>Welcome back</h1>
        <p style={{ margin: '6px 0 0', fontSize: 13, color: 'var(--c-ink-600)' }}>
          Sign in to manage skills across your organizations.
        </p>
      </div>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
        <label style={authLabel}>Email address</label>
        <input type="email" autoFocus value={email} onChange={e => setEmail(e.target.value)}
          onKeyDown={e => { if (e.key === 'Enter') submit(); }}
          placeholder="name@company.com" style={authInput} />
        {touched && email.length > 0 && !emailValid && (
          <span style={errorText}>Enter a valid email address.</span>
        )}
      </div>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
        <div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: 8 }}>
          <label style={authLabel}>Password</label>
          <button type="button" onClick={onForgot} style={linkBtn}>Forgot password?</button>
        </div>
        <PasswordInput value={pw} onChange={e => setPw(e.target.value)}
          onKeyDown={e => { if (e.key === 'Enter') submit(); }}
          placeholder="Your password" />
      </div>

      {serverError && <span style={errorText}>{serverError}</span>}
      <button onClick={submit} disabled={!valid || busy} style={{
        ...primaryBtn,
        background: (valid && !busy) ? 'var(--c-petrol-800)' : 'var(--c-cream-100)',
        color: (valid && !busy) ? '#fff' : 'var(--c-ink-300)',
        boxShadow: (valid && !busy) ? 'var(--shadow-raised)' : 'none',
        cursor: (valid && !busy) ? 'pointer' : 'not-allowed',
      }}>{busy ? 'Signing in…' : 'Sign in'}</button>
    </div>
  );
}

// Two-phase reset:
//   Phase 1 ("request"): user enters email → backend mints a single-use
//     reset token, stores its SHA-256 + expiry on the auth doc, and logs
//     the raw token to the server console for an operator to relay.
//   Phase 2 ("apply"): user enters the token + new password → backend
//     verifies the hash, applies the new password, clears the token.
//
// The pre-fix flow let any visitor reset any account by knowing only
// the email — full account-takeover. Knowing the token (which never
// leaves the server console / future email pipeline) is the proof of
// account ownership.
function ForgotForm({ onBack, onDone }) {
  const [phase, setPhase] = useLS('request'); // 'request' | 'apply'
  const [email, setEmail] = useLS('');
  const [token, setToken] = useLS('');
  const [pw, setPw] = useLS('');
  const [pw2, setPw2] = useLS('');
  const [submitted, setSubmitted] = useLS(false);
  const [busy, setBusy] = useLS(false);
  const [serverError, setServerError] = useLS('');

  const emailValid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
  const tokenValid = token.length >= 16;
  const pwValid = pw.length >= 8;
  const pwMatches = pw2.length > 0 && pw === pw2;

  const sendCode = async () => {
    setServerError('');
    if (!emailValid || busy) return;
    setBusy(true);
    try {
      const r = await fetch('/api/auth/forgot-password', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email }),
      });
      if (!r.ok) {
        setServerError('Could not start reset. Try again.');
        return;
      }
      // Backend returns ok regardless of whether the email exists, so we
      // always advance to phase 2 — anything else would let an attacker
      // enumerate accounts.
      setPhase('apply');
    } catch {
      setServerError('Network error. Is the server running?');
    } finally {
      setBusy(false);
    }
  };

  const applyReset = async () => {
    setServerError('');
    if (!emailValid || !tokenValid || !pwValid || !pwMatches || busy) return;
    setBusy(true);
    try {
      const r = await fetch('/api/auth/reset-password', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email, token: token.trim(), newPassword: pw }),
      });
      const data = await r.json().catch(() => ({}));
      if (!r.ok) {
        setServerError(
          data.error === 'invalid_or_expired_token' ? 'That code is invalid or has expired. Request a new one.'
          : data.error === 'password_too_short'    ? 'Password must be at least 8 characters.'
          : 'Could not update password. Try again.'
        );
        return;
      }
      setSubmitted(true);
      setTimeout(() => onDone(), 900);
    } catch {
      setServerError('Network error. Is the server running?');
    } finally {
      setBusy(false);
    }
  };

  const back = (
    <button onClick={onBack} style={{
      display: 'inline-flex', alignItems: 'center', gap: 6,
      background: 'transparent', border: 'none', padding: 0, cursor: 'pointer',
      color: 'var(--c-petrol-800)', fontFamily: "'Inter', sans-serif", fontWeight: 600, fontSize: 12,
      marginBottom: 4,
    }}>
      <span style={{ fontSize: 14, lineHeight: 1 }}>‹</span> Back to sign in
    </button>
  );

  if (phase === 'request') {
    return (
      <div style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>
        <div>
          {back}
          <div className="eyebrow" style={{ color: 'var(--c-ink-500)', letterSpacing: '1.5px' }}>Reset password</div>
          <h1 style={{
            margin: '6px 0 0', fontFamily: "'Suisse Int\\'l', sans-serif", fontWeight: 700,
            fontSize: 24, letterSpacing: '-0.02em', color: 'var(--c-ink-800)',
          }}>Get a reset code</h1>
          <p style={{ margin: '6px 0 0', fontSize: 13, color: 'var(--c-ink-600)' }}>
            Enter your email and we'll generate a one-time reset code. Ask your administrator for the code, then return here to set a new password.
          </p>
        </div>
        <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
          <label style={authLabel}>Email address</label>
          <input type="email" autoFocus value={email} onChange={e => setEmail(e.target.value)}
            onKeyDown={e => { if (e.key === 'Enter') sendCode(); }}
            placeholder="name@company.com" style={authInput} />
          {email.length > 0 && !emailValid && (
            <span style={errorText}>Enter a valid email address.</span>
          )}
        </div>
        {serverError && <span style={errorText}>{serverError}</span>}
        <button onClick={sendCode} disabled={!emailValid || busy} style={{
          ...primaryBtn,
          background: (emailValid && !busy) ? 'var(--c-petrol-800)' : 'var(--c-cream-100)',
          color: (emailValid && !busy) ? '#fff' : 'var(--c-ink-300)',
          boxShadow: (emailValid && !busy) ? 'var(--shadow-raised)' : 'none',
          cursor: (emailValid && !busy) ? 'pointer' : 'not-allowed',
        }}>{busy ? 'Sending…' : 'Send reset code'}</button>
        <button onClick={() => setPhase('apply')} style={{
          ...linkBtn, alignSelf: 'flex-start',
        }}>I already have a code</button>
      </div>
    );
  }

  const valid = emailValid && tokenValid && pwValid && pwMatches;
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 18 }}>
      <div>
        {back}
        <div className="eyebrow" style={{ color: 'var(--c-ink-500)', letterSpacing: '1.5px' }}>Reset password</div>
        <h1 style={{
          margin: '6px 0 0', fontFamily: "'Suisse Int\\'l', sans-serif", fontWeight: 700,
          fontSize: 24, letterSpacing: '-0.02em', color: 'var(--c-ink-800)',
        }}>Enter your code &amp; new password</h1>
        <p style={{ margin: '6px 0 0', fontSize: 13, color: 'var(--c-ink-600)' }}>
          Paste the one-time reset code your administrator gave you, then set a new password.
        </p>
      </div>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
        <label style={authLabel}>Email address</label>
        <input type="email" value={email} onChange={e => setEmail(e.target.value)}
          placeholder="name@company.com" style={authInput} />
      </div>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
        <label style={authLabel}>Reset code</label>
        <input type="text" autoFocus={phase === 'apply'}
          value={token} onChange={e => setToken(e.target.value)}
          placeholder="Paste the reset code" style={{
            ...authInput,
            fontFamily: 'ui-monospace, "JetBrains Mono", Menlo, monospace',
            fontSize: 13, letterSpacing: '0.02em',
          }} />
        {token.length > 0 && !tokenValid && (
          <span style={errorText}>The code looks too short.</span>
        )}
      </div>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
        <label style={authLabel}>New password</label>
        <PasswordInput value={pw} onChange={e => setPw(e.target.value)}
          placeholder="At least 8 characters" />
        {pw.length > 0 && !pwValid && (
          <span style={errorText}>Use at least 8 characters.</span>
        )}
      </div>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
        <label style={authLabel}>Confirm new password</label>
        <PasswordInput value={pw2} onChange={e => setPw2(e.target.value)}
          onKeyDown={e => { if (e.key === 'Enter' && valid && !submitted) applyReset(); }}
          placeholder="Re-enter new password" />
        {pw2.length > 0 && !pwMatches && (
          <span style={errorText}>Passwords do not match.</span>
        )}
      </div>

      {serverError && <span style={errorText}>{serverError}</span>}
      <button onClick={applyReset} disabled={!valid || submitted || busy} style={{
        ...primaryBtn,
        background: (valid && !busy) ? 'var(--c-petrol-800)' : 'var(--c-cream-100)',
        color: (valid && !busy) ? '#fff' : 'var(--c-ink-300)',
        boxShadow: (valid && !submitted && !busy) ? 'var(--shadow-raised)' : 'none',
        cursor: (valid && !submitted && !busy) ? 'pointer' : 'not-allowed',
      }}>{submitted ? 'Password updated ✓' : busy ? 'Updating…' : 'Update password'}</button>
    </div>
  );
}

const authLabel = {
  fontFamily: "'Inter', sans-serif", fontSize: 11, fontWeight: 700,
  letterSpacing: '0.08em', textTransform: 'uppercase', color: 'var(--c-ink-600)',
};
const authInput = {
  height: 44, padding: '0 14px', borderRadius: 12,
  background: 'var(--c-cream-50)',
  border: '1.5px solid var(--border-subtle)',
  boxShadow: 'var(--shadow-inset-input)',
  fontFamily: "'Suisse Int\\'l', sans-serif", fontSize: 14, color: 'var(--c-ink-900)',
  width: '100%', outline: 'none', boxSizing: 'border-box',
};
const errorText = { fontSize: 12, color: 'var(--c-terra-600, #C65A42)' };
const primaryBtn = {
  height: 46, padding: '0 22px', borderRadius: 12, border: 'none',
  fontFamily: "'Inter', sans-serif", fontWeight: 700, fontSize: 13,
  marginTop: 4,
};
const linkBtn = {
  background: 'transparent', border: 'none', padding: 0, cursor: 'pointer',
  color: 'var(--c-petrol-800)', fontFamily: "'Inter', sans-serif", fontWeight: 600, fontSize: 11,
  textDecoration: 'underline',
};

Object.assign(window, { LoginScreen });
