import { Eye, EyeOff, KeyRound, Mail } from 'lucide-react'
import { useState, type FormEvent } from 'react'
import { Link, useLocation, useNavigate } from 'react-router-dom'

import { AuthLayout } from './AuthLayout'
import { Alert, Button, Input } from '@/components/ui'
import { useAuth } from '@/features/auth/AuthProvider'
import { ApiError } from '@/lib/api'

export function LoginPage() {
  const { login } = useAuth()
  const navigate = useNavigate()
  const location = useLocation()

  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')
  const [remember, setRemember] = useState(false)
  const [showPassword, setShowPassword] = useState(false)

  /*
   * Two-factor is a second step on the same screen rather than a separate
   * route: keeping the entered credentials in component state avoids a
   * half-authenticated server-side state to manage, and the user never loses
   * what they typed.
   */
  const [needsSecondFactor, setNeedsSecondFactor] = useState(false)
  const [useRecoveryCode, setUseRecoveryCode] = useState(false)
  const [secondFactor, setSecondFactor] = useState('')

  const [error, setError] = useState<ApiError | null>(null)
  const [isSubmitting, setIsSubmitting] = useState(false)

  const handleSubmit = async (event: FormEvent) => {
    event.preventDefault()
    setError(null)
    setIsSubmitting(true)

    try {
      await login({
        email,
        password,
        remember,
        ...(needsSecondFactor && !useRecoveryCode ? { two_factor_code: secondFactor } : {}),
        ...(needsSecondFactor && useRecoveryCode ? { recovery_code: secondFactor } : {}),
      })

      const destination = (location.state as { from?: string } | null)?.from ?? '/dashboard'
      navigate(destination, { replace: true })
    } catch (caught) {
      if (caught instanceof ApiError) {
        if (caught.twoFactorRequired) {
          setNeedsSecondFactor(true)
          setError(null)
        } else {
          setError(caught)
        }
      } else {
        throw caught
      }
    } finally {
      setIsSubmitting(false)
    }
  }

  return (
    <AuthLayout
      title={needsSecondFactor ? 'Two-factor authentication' : 'Sign in'}
      description={
        needsSecondFactor
          ? 'Enter the six-digit code from your authenticator app.'
          : 'Access your portfolio, offers and purchases.'
      }
      footer={
        needsSecondFactor ? (
          <button
            type="button"
            className="text-text-accent underline underline-offset-4"
            onClick={() => {
              setNeedsSecondFactor(false)
              setSecondFactor('')
              setUseRecoveryCode(false)
              setError(null)
            }}
          >
            Use a different account
          </button>
        ) : (
          <>
            New to Domainsansar?{' '}
            <Link to="/register" className="font-medium text-text-accent underline underline-offset-4">
              Create an account
            </Link>
          </>
        )
      }
    >
      <form onSubmit={handleSubmit} className="flex flex-col gap-4" noValidate>
        {/*
          The account-standing case (suspended, closed) is a 403 with a real
          explanation, so it is shown as its own message rather than collapsed
          into a generic credential failure.
        */}
        {error !== null && !error.isValidation && (
          <Alert tone="error" title={error.isThrottled ? 'Too many attempts' : 'Cannot sign in'}>
            {error.message}
          </Alert>
        )}

        {needsSecondFactor ? (
          <>
            <Input
              label={useRecoveryCode ? 'Recovery code' : 'Authentication code'}
              value={secondFactor}
              onChange={(event) => setSecondFactor(event.target.value)}
              autoComplete="one-time-code"
              inputMode={useRecoveryCode ? 'text' : 'numeric'}
              autoFocus
              required
              leadingIcon={<KeyRound className="size-4" />}
              error={error?.errorFor('two_factor_code') ?? error?.errorFor('recovery_code')}
              hint={
                useRecoveryCode
                  ? 'Each recovery code works once.'
                  : 'Open your authenticator app to find the current code.'
              }
            />

            <button
              type="button"
              className="self-start text-sm text-text-accent underline underline-offset-4"
              onClick={() => {
                setUseRecoveryCode((value) => !value)
                setSecondFactor('')
              }}
            >
              {useRecoveryCode ? 'Use an authenticator code instead' : 'Use a recovery code instead'}
            </button>
          </>
        ) : (
          <>
            <Input
              label="Email address"
              type="email"
              value={email}
              onChange={(event) => setEmail(event.target.value)}
              autoComplete="email"
              autoFocus
              required
              leadingIcon={<Mail className="size-4" />}
              error={error?.errorFor('email')}
            />

            <Input
              label="Password"
              type={showPassword ? 'text' : 'password'}
              value={password}
              onChange={(event) => setPassword(event.target.value)}
              autoComplete="current-password"
              required
              error={error?.errorFor('password')}
              trailingSlot={
                <button
                  type="button"
                  onClick={() => setShowPassword((value) => !value)}
                  aria-label={showPassword ? 'Hide password' : 'Show password'}
                  className="flex size-8 items-center justify-center rounded-md text-text-muted hover:text-text-primary"
                >
                  {showPassword ? (
                    <EyeOff aria-hidden className="size-4" />
                  ) : (
                    <Eye aria-hidden className="size-4" />
                  )}
                </button>
              }
            />

            <div className="flex items-center justify-between">
              <label className="flex items-center gap-2 text-sm text-text-secondary">
                <input
                  type="checkbox"
                  checked={remember}
                  onChange={(event) => setRemember(event.target.checked)}
                  className="size-4 rounded border-border-control accent-[var(--accent-solid)]"
                />
                Keep me signed in
              </label>

              <Link
                to="/forgot-password"
                className="text-sm text-text-accent underline underline-offset-4"
              >
                Forgot password?
              </Link>
            </div>
          </>
        )}

        <Button type="submit" size="lg" fullWidth isLoading={isSubmitting}>
          {needsSecondFactor ? 'Verify and sign in' : 'Sign in'}
        </Button>
      </form>
    </AuthLayout>
  )
}
