import { useState } from 'react';

interface Props {
  serverUrl: string;
  /** Called once the backend has confirmed the credentials and set a session cookie. */
  onSuccess: () => void;
  onBack: () => void;
}

type Stage = 'credentials' | 'totp' | 'webauthn';

interface ApiError {
  message?: string;
}

async function postJson(url: string, body: unknown): Promise<{ ok: boolean; data: any }> {
  const res = await fetch(url, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    credentials: 'include',
    body: JSON.stringify(body),
  });
  const data = await res.json().catch(() => ({}));
  return { ok: res.ok, data };
}

export default function LoginScreen({ serverUrl, onSuccess, onBack }: Props) {
  const [stage, setStage] = useState<Stage>('credentials');
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const [code, setCode] = useState('');
  const [challengeToken, setChallengeToken] = useState('');
  const [error, setError] = useState('');
  const [loading, setLoading] = useState(false);

  function handleKey(e: React.KeyboardEvent) {
    if (e.key !== 'Enter') return;
    if (stage === 'credentials') handleLogin();
    if (stage === 'totp') handleTotp();
  }

  async function handleLogin() {
    if (!username.trim() || !password) {
      setError('Enter your username and password.');
      return;
    }
    setError('');
    setLoading(true);
    try {
      const { ok, data } = await postJson(`${serverUrl}/api/auth/login`, {
        username: username.trim(),
        password,
      });

      if (!ok) {
        setError((data as ApiError)?.message || 'Invalid username or password.');
        return;
      }

      if (data.requires_totp) {
        setChallengeToken(data.challenge_token);
        setStage('totp');
        return;
      }

      if (data.requires_webauthn) {
        setStage('webauthn');
        return;
      }

      onSuccess();
    } catch {
      setError('Could not reach the server. Check the URL and your connection.');
    } finally {
      setLoading(false);
    }
  }

  async function handleTotp() {
    if (!code.trim()) {
      setError('Enter your authenticator code.');
      return;
    }
    setError('');
    setLoading(true);
    try {
      const { ok, data } = await postJson(`${serverUrl}/api/auth/totp/challenge`, {
        challenge_token: challengeToken,
        code: code.trim(),
      });

      if (!ok) {
        setError((data as ApiError)?.message || 'Invalid authenticator code.');
        return;
      }

      onSuccess();
    } catch {
      setError('Could not reach the server. Check the URL and your connection.');
    } finally {
      setLoading(false);
    }
  }

  if (stage === 'webauthn') {
    return (
      <div className="setup-root">
        <div className="setup-card">
          <h1 className="setup-title">Security key required</h1>
          <p className="setup-subtitle">
            This account signs in with a security key. Continue to sign in through the server's
            web interface.
          </p>
          <button className="btn-primary" onClick={onSuccess}>
            Continue
          </button>
          <button className="btn-secondary" onClick={onBack}>
            Back
          </button>
        </div>
      </div>
    );
  }

  if (stage === 'totp') {
    return (
      <div className="setup-root">
        <div className="setup-card">
          <h1 className="setup-title">Two-factor code</h1>
          <p className="setup-subtitle">Enter the code from your authenticator app.</p>

          <div className="form-group">
            <label className="form-label" htmlFor="totp-code">Code</label>
            <input
              id="totp-code"
              className="form-input"
              type="text"
              inputMode="numeric"
              autoCapitalize="none"
              autoCorrect="off"
              spellCheck={false}
              placeholder="123456"
              value={code}
              onChange={e => { setCode(e.target.value); setError(''); }}
              onKeyDown={handleKey}
              disabled={loading}
              autoFocus
            />
            {error && <p className="form-error">{error}</p>}
          </div>

          <button className="btn-primary" onClick={handleTotp} disabled={loading || !code.trim()}>
            {loading ? 'Verifying…' : 'Verify'}
          </button>
          <button className="btn-secondary" onClick={onBack} disabled={loading}>
            Back
          </button>
        </div>
      </div>
    );
  }

  return (
    <div className="setup-root">
      <div className="setup-card">
        <h1 className="setup-title">Sign in</h1>
        <p className="setup-subtitle">Sign in to {serverUrl}</p>

        <div className="form-group">
          <label className="form-label" htmlFor="login-username">Username</label>
          <input
            id="login-username"
            className="form-input"
            type="text"
            inputMode="text"
            autoCapitalize="none"
            autoCorrect="off"
            spellCheck={false}
            placeholder="Username"
            value={username}
            onChange={e => { setUsername(e.target.value); setError(''); }}
            onKeyDown={handleKey}
            disabled={loading}
            autoFocus
          />
        </div>

        <div className="form-group">
          <label className="form-label" htmlFor="login-password">Password</label>
          <input
            id="login-password"
            className="form-input"
            type="password"
            autoCapitalize="none"
            autoCorrect="off"
            spellCheck={false}
            placeholder="Password"
            value={password}
            onChange={e => { setPassword(e.target.value); setError(''); }}
            onKeyDown={handleKey}
            disabled={loading}
          />
          {error && <p className="form-error">{error}</p>}
        </div>

        <button className="btn-primary" onClick={handleLogin} disabled={loading || !username.trim() || !password}>
          {loading ? 'Signing in…' : 'Sign In'}
        </button>
        <button className="btn-secondary" onClick={onBack} disabled={loading}>
          Back
        </button>
      </div>
    </div>
  );
}
