'use client';

import { useState } from 'react';
import { useRouter } from 'next/navigation';
import { useAuth } from '@/lib/auth-context';
import PasswordInput from '@/components/PasswordInput';

type Stage = 'CREDENTIALS' | 'CHANGE_PASSWORD' | 'TWO_FACTOR' | 'ENROLL_SCAN' | 'ENROLL_DONE';

export default function LoginPage() {
  const { login, verifyTwoFactor } = useAuth();
  const router = useRouter();
  const [stage, setStage] = useState<Stage>('CREDENTIALS');
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [code, setCode] = useState('');
  const [error, setError] = useState<string | null>(null);
  const [busy, setBusy] = useState(false);
  const [newPassword, setNewPassword] = useState('');

  // Enrollment-only state — never touches the authenticated session state
  // in lib/auth-context.tsx, since the account isn't logged in yet at this
  // point (see the comment on the confirm step below).
  const [preAuthToken, setPreAuthToken] = useState('');
  const [qrCodeDataUrl, setQrCodeDataUrl] = useState('');
  const [base32, setBase32] = useState('');
  const [recoveryCodes, setRecoveryCodes] = useState<string[]>([]);

  async function handleCredentials(e: React.FormEvent) {
    e.preventDefault();
    setError(null);
    setBusy(true);
    try {
      const data = await login(email, password);
      if (data.status === 'PASSWORD_CHANGE_REQUIRED') {
        // Invited account signing in with its temporary password: choose a real one first.
        setPreAuthToken(data.preAuthToken || '');
        setStage('CHANGE_PASSWORD');
      } else if (data.status === 'TWO_FACTOR_REQUIRED') {
        setStage('TWO_FACTOR');
      } else if (data.status === 'TWO_FACTOR_ENROLLMENT_REQUIRED') {
        // Brand-new account (or 2FA reset): fetch the QR code before
        // showing the scan step.
        const res = await fetch('/api/auth/enroll', {
          method: 'POST', headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({ preAuthToken: data.preAuthToken }),
        });
        const enroll = await res.json();
        if (!res.ok) throw new Error(enroll.error || 'ENROLL_FAILED');
        setPreAuthToken(data.preAuthToken);
        setQrCodeDataUrl(enroll.qrCodeDataUrl);
        setBase32(enroll.base32);
        setStage('ENROLL_SCAN');
      }
    } catch {
      // Same generic message whether the email doesn't exist or the
      // password is wrong — the API already collapses this, we don't
      // re-introduce a leak here.
      setError('Invalid email or password.');
    } finally {
      setBusy(false);
    }
  }

  async function handleChangePassword(e: React.FormEvent) {
    e.preventDefault();
    setError(null);
    if (newPassword.length < 10 || !/[A-Za-z]/.test(newPassword) || !/\d/.test(newPassword)) {
      setError('Use at least 10 characters, with at least one letter and one number.');
      return;
    }
    setBusy(true);
    try {
      const res = await fetch('/api/auth/change-password', {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ preAuthToken, currentPassword: password, newPassword }),
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || 'CHANGE_FAILED');
      // Continue the normal flow with the NEW password: 2FA code, or first-time authenticator enrolment.
      setPassword(newPassword);
      setNewPassword('');
      const next = await login(email, newPassword);
      if (next.status === 'TWO_FACTOR_ENROLLMENT_REQUIRED') {
        const r2 = await fetch('/api/auth/enroll', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ preAuthToken: next.preAuthToken }) });
        const enroll = await r2.json();
        if (!r2.ok) throw new Error(enroll.error || 'ENROLL_FAILED');
        setPreAuthToken(next.preAuthToken || '');
        setQrCodeDataUrl(enroll.qrCodeDataUrl);
        setBase32(enroll.base32);
        setStage('ENROLL_SCAN');
      } else {
        setStage('TWO_FACTOR');
      }
    } catch {
      setError('Could not change the password — check that the temporary password is correct and the new one is strong enough.');
    } finally {
      setBusy(false);
    }
  }

  async function handleTwoFactor(e: React.FormEvent) {
    e.preventDefault();
    setError(null);
    setBusy(true);
    try {
      await verifyTwoFactor(email, code);
      router.push('/');
    } catch {
      setError('Invalid or expired code.');
    } finally {
      setBusy(false);
    }
  }

  async function handleConfirmEnrollment(e: React.FormEvent) {
    e.preventDefault();
    setError(null);
    setBusy(true);
    try {
      const res = await fetch('/api/auth/enroll/confirm', {
        method: 'POST', headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ preAuthToken, base32, token: code }),
      });
      const data = await res.json();
      if (!res.ok) throw new Error(data.error || 'CONFIRM_FAILED');
      setRecoveryCodes(data.recoveryCodes || []);
      setStage('ENROLL_DONE');
    } catch {
      setError('Invalid or expired code — check your authenticator app and try again.');
    } finally {
      setBusy(false);
    }
  }

  function backToLogin() {
    // Deliberately a full reset back to CREDENTIALS rather than trying to
    // splice straight into an authenticated session — 2FA is now enabled,
    // so the very next login will correctly ask for a real TOTP code
    // through the normal TWO_FACTOR stage above.
    setStage('CREDENTIALS');
    setPassword('');
    setCode('');
    setPreAuthToken('');
    setQrCodeDataUrl('');
    setBase32('');
    setRecoveryCodes([]);
  }

  return (
    <div className="min-h-screen flex items-center justify-center bg-brand-bg px-4">
      <div className="w-full max-w-sm bg-white border border-brand-border rounded-2xl shadow-sm p-8">
        <div className="flex items-center gap-3 mb-6">
          <div className="w-9 h-9 rounded bg-brand-charcoal flex items-center justify-center overflow-hidden">
            {/* eslint-disable-next-line @next/next/no-img-element */}
            <img src="/logo.png" alt="LUSSAVARA" className="w-7 h-7 object-contain" />
          </div>
          <div>
            <p className="font-bold text-sm">LUSSAVARA Admin</p>
            <p className="text-[11px] text-gray-500">admin.lussavara.co.tz</p>
          </div>
        </div>

        {stage === 'CREDENTIALS' && (
          <form onSubmit={handleCredentials} className="space-y-3">
            <div>
              <label className="text-xs font-medium text-gray-600">Email</label>
              <input
                type="email" required value={email} onChange={(e) => setEmail(e.target.value)}
                className="mt-1 w-full border border-brand-border rounded-lg px-3 py-2 text-sm focus:outline-none focus:border-brand-red"
                placeholder="you@lussavara.co.tz"
              />
            </div>
            <div>
              <label className="text-xs font-medium text-gray-600">Password</label>
              <div className="mt-1">
                <PasswordInput required value={password} onChange={(e) => setPassword(e.target.value)} autoComplete="current-password" />
              </div>
            </div>
            {error && <p className="text-xs text-brand-red">{error}</p>}
            <button disabled={busy} className="w-full bg-brand-red text-white text-sm font-semibold py-2.5 rounded-lg disabled:opacity-60">
              {busy ? 'Checking…' : 'Continue'}
            </button>
          </form>
        )}

        {stage === 'CHANGE_PASSWORD' && (
          <form onSubmit={handleChangePassword} className="space-y-3">
            <p className="text-xs text-gray-600">Welcome! Your account was created with a temporary password. Choose your own password to continue.</p>
            <PasswordInput required value={newPassword} onChange={(e) => setNewPassword(e.target.value)}
              autoComplete="new-password" placeholder="New password (10+ characters, letters & numbers)" />
            {error && <p className="text-xs text-brand-red">{error}</p>}
            <button disabled={busy} className="w-full bg-brand-red text-white text-sm font-semibold py-2.5 rounded-lg disabled:opacity-60">
              {busy ? 'Saving…' : 'Save password & continue'}
            </button>
          </form>
        )}

        {stage === 'TWO_FACTOR' && (
          <form onSubmit={handleTwoFactor} className="space-y-3">
            <p className="text-xs text-gray-600">Enter the 6-digit code from your authenticator app.</p>
            <input
              inputMode="numeric" maxLength={6} required value={code}
              onChange={(e) => setCode(e.target.value.replace(/\D/g, ''))}
              className="w-full border border-brand-border rounded-lg px-3 py-2 text-center text-lg tracking-[0.5em] focus:outline-none focus:border-brand-red"
              placeholder="••••••"
            />
            {error && <p className="text-xs text-brand-red">{error}</p>}
            <button disabled={busy} className="w-full bg-brand-red text-white text-sm font-semibold py-2.5 rounded-lg disabled:opacity-60">
              {busy ? 'Verifying…' : 'Verify & Sign In'}
            </button>
          </form>
        )}

        {stage === 'ENROLL_SCAN' && (
          <form onSubmit={handleConfirmEnrollment} className="space-y-3">
            <p className="text-xs text-gray-600">
              2FA isn&apos;t set up yet for this account. Scan this QR code with Google
              Authenticator, Authy, or any TOTP app, then enter the 6-digit code it shows.
            </p>
            {qrCodeDataUrl && (
              // eslint-disable-next-line @next/next/no-img-element
              <img src={qrCodeDataUrl} alt="2FA QR code" className="mx-auto w-40 h-40" />
            )}
            <details className="text-[10px] text-gray-400">
              <summary className="cursor-pointer">Can&apos;t scan? Enter manually</summary>
              <p className="font-mono break-all mt-1">{base32}</p>
            </details>
            <input
              inputMode="numeric" maxLength={6} required value={code}
              onChange={(e) => setCode(e.target.value.replace(/\D/g, ''))}
              className="w-full border border-brand-border rounded-lg px-3 py-2 text-center text-lg tracking-[0.5em] focus:outline-none focus:border-brand-red"
              placeholder="••••••"
            />
            {error && <p className="text-xs text-brand-red">{error}</p>}
            <button disabled={busy} className="w-full bg-brand-red text-white text-sm font-semibold py-2.5 rounded-lg disabled:opacity-60">
              {busy ? 'Confirming…' : 'Confirm & Enable 2FA'}
            </button>
          </form>
        )}

        {stage === 'ENROLL_DONE' && (
          <div className="space-y-3">
            <p className="text-xs text-gray-700 font-semibold">2FA is enabled. Save these recovery codes somewhere safe — each works once if you lose your authenticator device.</p>
            <div className="bg-brand-bg border border-brand-border rounded-lg p-3 font-mono text-[11px] grid grid-cols-2 gap-1">
              {recoveryCodes.map((c) => <span key={c}>{c}</span>)}
            </div>
            <button onClick={backToLogin} className="w-full bg-brand-charcoal text-white text-sm font-semibold py-2.5 rounded-lg">
              Continue to Login
            </button>
          </div>
        )}

        <p className="text-[10px] text-gray-400 mt-6 text-center">
          LUSSAVARA COMPANY LIMITED
        </p>
      </div>
    </div>
  );
}
