// Two-step login: after a correct password, users with 2FA get a short-
// lived pending token and must present a second factor before the real
// session token exists. `stage` flips this screen between the two steps.
// 'invite' = arriving via an activation link (#invite=<token>): the user
// sets their own password and lands straight in the app.
// 'reset' links (#reset=<token>) ride the same stage — same form, different
// wording, and on success they go back to sign-in instead of straight in
// (a reset must not skip 2FA).
const LoginScreen = ({ onLogin }) => {
    const [form, setForm]       = React.useState({ email: '', password: '' });
    const [error, setError]     = React.useState('');
    const [loading, setLoading] = React.useState(false);

    const hashMatch   = window.location.hash.match(/^#(invite|reset)=(.+)$/) || [];
    const inviteToken = hashMatch[2] || null;
    const isReset     = hashMatch[1] === 'reset';
    const [stage, setStage]     = React.useState(inviteToken ? 'invite' : 'password');   // 'password' | '2fa' | 'invite' | 'forgot'
    const [pending, setPending] = React.useState(null);          // { token, methods }
    const [code, setCode]       = React.useState('');

    const [invite, setInvite]         = React.useState(null);    // { first_name, tenant_name, email, purpose, agreement? }
    const [newPass, setNewPass]       = React.useState('');
    const [newPass2, setNewPass2]     = React.useState('');
    // Clickwrap: checkbox state + lazily-loaded terms text (null = collapsed).
    const [agreedTerms, setAgreedTerms] = React.useState(false);
    const [termsText, setTermsText]     = React.useState(null);
    const toggleTerms = () => {
        if (termsText !== null) { setTermsText(null); return; }
        api.getAgreement().then(a => setTermsText(a.text)).catch(() => setTermsText('Could not load the terms — try again.'));
    };

    const [forgotEmail, setForgotEmail] = React.useState('');
    const [notice, setNotice]           = React.useState('');    // green info banner

    // BETA badge — driven by whatsnew.json's `beta` flag so retiring beta
    // status is one edit in one file (same source the What's New modal reads).
    const [isBeta, setIsBeta] = React.useState(false);
    React.useEffect(() => {
        fetch('/src/data/whatsnew.json')
            .then(r => r.ok ? r.json() : null)
            .then(data => setIsBeta(Boolean(data?.beta)))
            .catch(() => {});
    }, []);

    React.useEffect(() => {
        if (!inviteToken) return;
        api.getInvite(inviteToken)
            .then(setInvite)
            .catch(err => { setError(friendlyApiError(err)); setStage('password'); });
    }, []);

    const finish = (data) => {
        // Drop the invite token from the URL so it never lingers in history.
        if (window.location.hash) history.replaceState(null, '', window.location.pathname);
        setToken(data.token); onLogin(data.user);
    };

    const handleActivate = async (e) => {
        e.preventDefault();
        if (newPass !== newPass2) { setError('Passwords don\'t match.'); return; }
        setLoading(true); setError('');
        try {
            const data = await api.redeemInvite(inviteToken, newPass, agreedTerms);
            if (data.token) {
                finish(data);           // invite: activated + signed in
            } else {
                // reset: password set — back to sign-in (2FA still applies there)
                if (window.location.hash) history.replaceState(null, '', window.location.pathname);
                setNotice('Password updated — sign in with your new password.');
                setNewPass(''); setNewPass2('');
                setStage('password');
            }
        } catch (err) {
            setError(friendlyApiError(err));
        } finally {
            setLoading(false);
        }
    };

    const handleForgot = async (e) => {
        e.preventDefault();
        setLoading(true); setError('');
        try {
            const r = await api.forgotPassword(forgotEmail);
            setNotice(r.message);
            setStage('password');
        } catch (err) {
            setError(friendlyApiError(err));
        } finally {
            setLoading(false);
        }
    };

    const handleSubmit = async (e) => {
        e.preventDefault();
        setLoading(true);
        setError('');
        try {
            const data = await api.login(form.email, form.password);
            if (data.requires_2fa) {
                setPending({ token: data.pending_token, methods: data.methods });
                setStage('2fa');
            } else {
                finish(data);
            }
        } catch (err) {
            setError(friendlyApiError(err));
        } finally {
            setLoading(false);
        }
    };

    const handleCode = async (e) => {
        e.preventDefault();
        setLoading(true);
        setError('');
        try {
            finish(await api.verify2faTotp(pending.token, code));
        } catch (err) {
            setError(friendlyApiError(err));
            // Pending tokens expire in 5 min / rate-limit at 10 tries — a 429
            // or expiry means the whole login restarts, so send them back.
            if (/sign in again|expired/i.test(err.message)) backToPassword();
        } finally {
            setLoading(false);
        }
    };

    const handleSecurityKey = async () => {
        setLoading(true);
        setError('');
        try {
            const options = await api.verify2faKeyOptions(pending.token);
            const assertion = await SimpleWebAuthnBrowser.startAuthentication({ optionsJSON: options });
            finish(await api.verify2faKey(pending.token, assertion));
        } catch (err) {
            // NotAllowedError = the user cancelled the browser prompt — not an error worth shouting about.
            setError(err.name === 'NotAllowedError' ? 'Security key prompt was cancelled.' : friendlyApiError(err));
        } finally {
            setLoading(false);
        }
    };

    const backToPassword = () => {
        setStage('password');
        setPending(null);
        setCode('');
    };

    return (
        <div className="login-screen">
            <div className="login-card">
                <div className="login-logo">
                    <img className="login-logo-mark" src="/assets/logo.svg" alt="CRM logo" />
                    <h1>Clerical Repetition Machine{isBeta && <span className="beta-badge">BETA</span>}</h1>
                    <p>{stage === '2fa' ? 'Two-factor verification'
                        : stage === 'forgot' ? 'Reset your password'
                        : stage === 'invite' ? (
                            isReset ? 'Choose a new password'
                            : invite ? `Welcome, ${invite.first_name}!` : 'Checking your invite…')
                        : 'Sign in to your account'}</p>
                </div>

                {error && (
                    <div className="login-error">
                        <i className="fas fa-exclamation-circle"></i>
                        {error}
                    </div>
                )}

                {notice && !error && (
                    <div className="login-error" style={{ background: 'color-mix(in srgb, var(--success) 12%, transparent)', color: 'var(--success)', borderColor: 'var(--success)' }}>
                        <i className="fas fa-check-circle"></i>
                        {notice}
                    </div>
                )}

                {stage === 'invite' && invite && (
                    <form onSubmit={handleActivate}>
                        <p style={{ fontSize: '0.875rem', marginBottom: '1rem', opacity: 0.85 }}>
                            {invite.purpose === 'reset'
                                ? <>Choose a new password for <strong>{invite.email}</strong>. You'll sign in with it right after.</>
                                : <>You've been invited to <strong>{invite.tenant_name}</strong>.
                                   Choose a password for <strong>{invite.email}</strong> and you're in.</>}
                        </p>
                        <div className="form-group" style={{ marginBottom: '0.5rem' }}>
                            <label className="form-label">Choose a password</label>
                            <input type="password" className="form-input" value={newPass}
                                   onChange={(e) => setNewPass(e.target.value)}
                                   placeholder="At least 12 characters" minLength={12} maxLength={72} required autoFocus />
                        </div>
                        <p style={{ fontSize: '0.75rem', opacity: 0.7, marginBottom: '1rem' }}>
                            12+ characters, and not a commonly-used password. A few words strung
                            together beats symbols — no special characters required.
                        </p>
                        <div className="form-group" style={{ marginBottom: '1.5rem' }}>
                            <label className="form-label">Repeat password</label>
                            <input type="password" className="form-input" value={newPass2}
                                   onChange={(e) => setNewPass2(e.target.value)}
                                   placeholder="Same again" minLength={12} maxLength={72} required />
                        </div>
                        {invite.purpose === 'invite' && invite.agreement && (
                            <div style={{ marginBottom: '1.25rem' }}>
                                <label style={{ display: 'flex', alignItems: 'flex-start', gap: '0.5rem', fontSize: '0.8125rem', cursor: 'pointer' }}>
                                    <input type="checkbox" checked={agreedTerms}
                                           onChange={(e) => setAgreedTerms(e.target.checked)}
                                           style={{ marginTop: '0.15rem' }} required />
                                    <span>
                                        I agree to the{' '}
                                        <a href="#" onClick={(e) => { e.preventDefault(); toggleTerms(); }}>
                                            {invite.agreement.label}
                                        </a>{' '}
                                        <span style={{ opacity: 0.6 }}>(v{invite.agreement.version})</span>
                                    </span>
                                </label>
                                {termsText !== null && (
                                    /* min(…, 35vh): on a phone the expanded terms must never push the
                                       Activate button out of reach (real iPhone report, 2026-08-04) */
                                    <div style={{ maxHeight: 'min(10rem, 35vh)', overflowY: 'auto', border: '1px solid var(--border, #d1d5db)', borderRadius: 8, padding: '0.625rem 0.875rem', marginTop: '0.5rem', fontSize: '0.75rem', whiteSpace: 'pre-wrap', opacity: 0.9 }}>
                                        {termsText}
                                    </div>
                                )}
                            </div>
                        )}
                        <button type="submit" className="login-submit" disabled={loading}>
                            {loading ? <><i className="fas fa-spinner fa-spin"></i> {invite.purpose === 'reset' ? 'Saving…' : 'Activating…'}</>
                                     : (invite.purpose === 'reset' ? 'Set new password' : 'Activate my account')}
                        </button>
                    </form>
                )}

                {stage === 'forgot' && (
                    <form onSubmit={handleForgot}>
                        <p style={{ fontSize: '0.875rem', marginBottom: '1rem', opacity: 0.85 }}>
                            Enter your account email and we'll send a reset link if it matches
                            an account. No email set up in your workspace? Ask your admin for a
                            reset link instead.
                        </p>
                        <div className="form-group" style={{ marginBottom: '1.5rem' }}>
                            <label className="form-label">Email</label>
                            <input type="email" className="form-input" value={forgotEmail}
                                   onChange={(e) => setForgotEmail(e.target.value)}
                                   placeholder="you@example.com" required autoFocus />
                        </div>
                        <button type="submit" className="login-submit" disabled={loading}>
                            {loading ? <><i className="fas fa-spinner fa-spin"></i> Sending…</> : 'Send reset link'}
                        </button>
                        <p className="settings-hint" style={{ textAlign: 'center', marginTop: '1rem' }}>
                            <a href="#" onClick={(e) => { e.preventDefault(); setError(''); setStage('password'); }}>← Back to sign in</a>
                        </p>
                    </form>
                )}

                {stage === 'password' && (
                    <form onSubmit={handleSubmit}>
                        <div className="form-group" style={{ marginBottom: '1rem' }}>
                            <label className="form-label">Email</label>
                            <input
                                type="email"
                                className="form-input"
                                value={form.email}
                                onChange={(e) => setForm(p => ({ ...p, email: e.target.value }))}
                                placeholder="you@example.com"
                                required
                                autoFocus
                            />
                        </div>
                        <div className="form-group" style={{ marginBottom: '1.5rem' }}>
                            <label className="form-label">Password</label>
                            <input
                                type="password"
                                className="form-input"
                                value={form.password}
                                onChange={(e) => setForm(p => ({ ...p, password: e.target.value }))}
                                placeholder="••••••••"
                                required
                            />
                        </div>
                        <button type="submit" className="login-submit" disabled={loading}>
                            {loading ? <><i className="fas fa-spinner fa-spin"></i> Signing in…</> : 'Sign In'}
                        </button>
                        <p className="settings-hint" style={{ textAlign: 'center', marginTop: '1rem' }}>
                            <a href="#" onClick={(e) => { e.preventDefault(); setError(''); setNotice(''); setForgotEmail(form.email); setStage('forgot'); }}>Forgot password?</a>
                        </p>
                    </form>
                )}

                {stage === '2fa' && (
                    <div>
                        {pending.methods.webauthn && (
                            <button type="button" className="login-submit" onClick={handleSecurityKey} disabled={loading} style={{ marginBottom: '1rem' }}>
                                <i className="fas fa-key" style={{ marginRight: '0.5rem' }}></i>
                                Use security key
                            </button>
                        )}
                        {pending.methods.totp && (
                            <form onSubmit={handleCode}>
                                <div className="form-group" style={{ marginBottom: '1rem' }}>
                                    <label className="form-label">Authenticator code</label>
                                    <input
                                        type="text"
                                        className="form-input"
                                        value={code}
                                        onChange={(e) => setCode(e.target.value)}
                                        placeholder="123 456 — or a backup code"
                                        autoComplete="one-time-code"
                                        inputMode="numeric"
                                        autoFocus={!pending.methods.webauthn}
                                        required
                                    />
                                </div>
                                <button type="submit" className="login-submit" disabled={loading}>
                                    {loading ? <><i className="fas fa-spinner fa-spin"></i> Verifying…</> : 'Verify'}
                                </button>
                            </form>
                        )}
                        <p className="settings-hint" style={{ textAlign: 'center', marginTop: '1rem' }}>
                            <a href="#" onClick={(e) => { e.preventDefault(); backToPassword(); }}>← Back to sign in</a>
                        </p>
                    </div>
                )}
            </div>
        </div>
    );
};
