import { AuthErrorType, authErrorTypes, useAuth } from '@context-providers/auth-context-provider'
import { Route } from '@routes/login'

import { useEffect } from 'react'

import { InfoCard } from '@postxl/ui-components'

import { FileRouteTypes } from '../../routeTree.gen'

function getSafeRedirectUrl(url: string | undefined): string | undefined {
  if (!url) {
    return undefined
  }
  if (!url.startsWith('/') || url.startsWith('//') || url.includes('://')) {
    return undefined
  }
  return url
}

/**
 * Login component
 *
 * the auth check has to be implemented with an effect, because the keycloak.init is async
 * so the isAuthenticated state is not available immediately at the "beforeLoad" option at the route level
 * that's why our login component is a non-visual component, that just checks the auth state
 * and redirects to the dashboard (landing page)
 *
 * - if authProvider is not initialized, it will wait for initializing complete
 * - if the user is not authenticated, it will execute login (redirect to keycloak)
 * - if the user is authenticated, it will wait for the user to be loaded (viewerData !== null)
 * - if the user is loaded, it will redirect to the redirectUrl (if exist), or the user program (if exist), or home page
 */
export const LoginPage = () => {
  const { loginState, login, viewerData } = useAuth()
  const navigate = Route.useNavigate()
  const searchParams = Route.useSearch()

  useEffect(() => {
    // wait for the keycloak init to complete
    if (loginState === 'inProgress') {
      return
    }

    // if not authenticated yet, execute login
    if (loginState === 'loggedOut') {
      void login() // NOSONAR
      return
    }

    // check if auth errors exist and redirect auth error page
    if (authErrorTypes.includes(loginState as AuthErrorType)) {
      void navigate({ to: '/auth-error', search: { type: loginState as AuthErrorType } })
      return
    }

    // user data available
    if (viewerData) {
      // if authenticated, redirect considering the user role
      if (viewerData.userRoles.length === 0) {
        void navigate({ to: '/unauthorized' }) // NOSONAR
      } else {
        // redirect to given redirect url or /dashboard (as fallback)
        const fallbackHome: FileRouteTypes['to'] = '/dashboard'
        const safeRedirectUrl = getSafeRedirectUrl(searchParams.redirectUrl)
        const href: FileRouteTypes['to'] = (safeRedirectUrl as FileRouteTypes['to']) ?? fallbackHome

        // for dev mode and HMR we need to wait for the redirect; otherwise the 'href' is not found by tanstack router
        setTimeout(() => void navigate({ to: href, from: '/login' }), 0) // NOSONAR (we want to ignore the promise here)
      }
    }

    // If user has no programs at all, they'll hit _auth-routes which handles that case
  }, [login, loginState, navigate, searchParams.redirectUrl, viewerData])

  return <InfoCard variant="loading" title="Signing In" message="Please wait while we authenticate your session..." />
}
