import { useState, type FormEvent } from 'react'
import { Link, useNavigate, useSearch } from '@tanstack/react-router'
import { AuthCard } from '@/components/auth/AuthCard'
import { Alert } from '@/components/ui/Alert'
import { Button, buttonClasses } from '@/components/ui/Button'
import { Divider } from '@/components/ui/Divider'
import { TextField } from '@/components/ui/TextField'
import { API_BASE, errorMessage } from '@/lib/api'
import { useLogin, useProviders } from '@/lib/auth'
import { safeRedirectPath } from '@/lib/redirect'
import { usePageTitle } from '@/lib/usePageTitle'

// Server-initiated redirect (not a fetch): the browser navigates to the Go
// handler, which 302s to the IdP.
const OIDC_LOGIN_URL = `${API_BASE}/auth/oidc/login`

// Messages for the ?error= codes the OIDC callback redirects back with.
const callbackErrors: Record<string, string> = {
  oidc: 'Single sign-on did not complete. Please try again.',
  oidc_unavailable: 'The single sign-on provider is currently unavailable.',
  state: 'Your sign-in attempt expired. Please start again.',
  no_email: 'Your identity provider did not share an email address, which pansy needs.',
  email_unverified: 'Your email address is not verified with the identity provider.',
  oidc_conflict: 'That single sign-on identity conflicts with an existing account.',
}

export function LoginPage() {
  usePageTitle('Sign in')
  const search = useSearch({ from: '/login' })
  const navigate = useNavigate()
  const providers = useProviders()
  const login = useLogin()
  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')

  const dest = safeRedirectPath(search.redirect)
  const callbackError = search.error ? (callbackErrors[search.error] ?? callbackErrors.oidc) : null

  async function onSubmit(e: FormEvent) {
    e.preventDefault()
    try {
      await login.mutateAsync({ email, password })
      await navigate({ to: dest })
    } catch {
      // Shown below via login.error.
    }
  }

  const local = providers.data?.local ?? false
  const oidc = providers.data?.oidc ?? false

  return (
    <AuthCard title="Sign in to pansy" subtitle="Plan your garden, bed by bed.">
      <div className="flex flex-col gap-4">
        {callbackError && <Alert>{callbackError}</Alert>}

        {providers.isPending && <p className="text-sm text-muted">Loading…</p>}
        {providers.isError && <Alert>Could not load sign-in options. Please refresh.</Alert>}

        {oidc && (
          <a href={OIDC_LOGIN_URL} className={buttonClasses('primary', 'w-full')}>
            {providers.data?.oidcLabel || 'Sign in with SSO'}
          </a>
        )}

        {oidc && local && <Divider>or</Divider>}

        {local && (
          <form onSubmit={onSubmit} className="flex flex-col gap-3">
            <TextField
              label="Email"
              name="email"
              type="email"
              autoComplete="email"
              autoCapitalize="none"
              spellCheck={false}
              required
              value={email}
              onChange={(e) => setEmail(e.target.value)}
            />
            <TextField
              label="Password"
              name="password"
              type="password"
              autoComplete="current-password"
              required
              value={password}
              onChange={(e) => setPassword(e.target.value)}
            />
            {login.isError && <Alert>{errorMessage(login.error, 'Could not sign in.')}</Alert>}
            <Button type="submit" disabled={login.isPending} className="mt-1">
              {login.isPending ? 'Signing in…' : 'Sign in'}
            </Button>
          </form>
        )}

        {providers.isSuccess && !local && !oidc && (
          <Alert tone="info">No sign-in methods are configured on this server.</Alert>
        )}

        {local && (
          <p className="text-center text-sm text-muted">
            No account?{' '}
            <Link to="/register" className="font-medium text-accent-strong hover:underline">
              Create one
            </Link>
          </p>
        )}
      </div>
    </AuthCard>
  )
}
