import { useEffect, useState } from 'react'
import { useAuth } from '../../contexts/AuthContext'
import { Alert, AlertDescription } from '@/components/ui/alert'
import { Button } from '@/components/ui/button'

/** Landing page for the OIDC redirect.
 *
 *  Authentik bounces the browser to /auth/callback?access_token=...&refresh_token=...
 *  (or ?error=oidc_xxx when something went wrong). We pull those out of
 *  the URL, hand them to AuthContext, then replace history so the
 *  tokens don't linger in the location bar, the back button, or
 *  whatever screen-recording the user has going.
 *
 *  Tokens in the query string are an accepted trade-off here: they're
 *  short-lived, they never leave the app origin, and the alternative
 *  (HTTP-only cookies) would be a much larger rework of an otherwise
 *  JWT-in-localStorage codebase.
 */
const ERROR_MESSAGES: Record<string, string> = {
  oidc_exchange_failed: 'Could not complete sign-in with the identity provider.',
  oidc_missing_sub: 'Identity provider did not return a user identifier.',
  oidc_signup_disabled: 'Your identity provider account has not been authorized for this instance.',
  oidc_deactivated: 'This account has been deactivated.',
}

export function OidcCallback() {
  const { onOidcTokens } = useAuth()
  const [error, setError] = useState<string | null>(null)

  useEffect(() => {
    const params = new URLSearchParams(window.location.search)
    const accessToken = params.get('access_token')
    const refreshToken = params.get('refresh_token')
    const errCode = params.get('error')

    // Drop everything after the origin + root path, including the
    // tokens, so refreshing or sharing the URL doesn't leak them.
    const clean = () => window.history.replaceState({}, '', '/')

    if (errCode) {
      // Don't auto-bounce back to Authentik on the next LoginPage
      // mount — show the error and let the user fall back to password
      // or retry deliberately.
      sessionStorage.setItem('skipAutoSso', '1')
      setError(ERROR_MESSAGES[errCode] || 'Sign-in failed. Please try again.')
      clean()
      return
    }

    if (!accessToken || !refreshToken) {
      sessionStorage.setItem('skipAutoSso', '1')
      setError('The identity provider did not return the expected tokens.')
      clean()
      return
    }

    ;(async () => {
      try {
        await onOidcTokens(accessToken, refreshToken)
      } catch {
        setError('Could not complete sign-in. Please try again.')
      } finally {
        clean()
      }
    })()
  }, [onOidcTokens])

  if (error) {
    return (
      <div className="flex min-h-screen items-center justify-center bg-bg px-4">
        <div className="w-full max-w-sm space-y-4 rounded-lg border border-border bg-surface p-8 shadow-xl">
          <h1 className="text-center text-lg font-semibold text-text">Sign-in failed</h1>
          <Alert variant="destructive">
            <AlertDescription>{error}</AlertDescription>
          </Alert>
          <Button className="w-full" onClick={() => (window.location.href = '/')}>
            Back to sign in
          </Button>
        </div>
      </div>
    )
  }

  return (
    <div className="flex min-h-screen items-center justify-center bg-bg">
      <div className="text-text-muted">Signing you in&hellip;</div>
    </div>
  )
}
