'use client'

import { useEffect } from 'react'
import { useRouter } from './contexts/RouterContext'
import { useAllauthConfig } from './contexts/ConfigContext'
import { useAuth, useUser, useConfig } from './contexts/AuthContext'

/**
 * Route guard that only renders children if the user is authenticated.
 * Redirects to login page if not authenticated.
 */
export function UserRoute({ children }: { children: React.ReactNode }) {
    const router = useRouter()
    const config = useAllauthConfig()
    const { isAuthenticated } = useAuth()

    useEffect(() => {
        if (!isAuthenticated) {
            const next = encodeURIComponent(router.pathname + router.searchParams.toString())
            router.replace(`${config.routes.login}?next=${next}`)
        }
    }, [isAuthenticated, router, config.routes.login])

    if (!isAuthenticated) return null
    return children
}

/**
 * Route guard that only renders children if the user is authenticated AND is staff.
 * Redirects to login if not authenticated, or to authenticated route if not staff.
 */
export function StaffRoute({ children }: { children: React.ReactNode }) {
    const router = useRouter()
    const config = useAllauthConfig()
    const { isAuthenticated } = useAuth()
    const user = useUser()

    useEffect(() => {
        if (!isAuthenticated) {
            const next = encodeURIComponent(router.pathname + router.searchParams.toString())
            router.replace(`${config.routes.login}?next=${next}`)
        } else if (!user.is_staff) {
            router.replace(config.routes.authenticated)
        }
    }, [isAuthenticated, user.is_staff, router, config.routes])

    if (!isAuthenticated || !user.is_staff) return null
    return children
}

/**
 * Route guard that only renders children if the user is NOT authenticated.
 * Redirects to authenticated route if already logged in.
 */
export function AnonymousRoute({ children }: { children: React.ReactNode }) {
    const router = useRouter()
    const config = useAllauthConfig()
    const { isAuthenticated } = useAuth()

    useEffect(() => {
        if (isAuthenticated) {
            router.replace(config.routes.authenticated)
        }
    }, [isAuthenticated, config.routes.authenticated, router])

    if (isAuthenticated) return null
    return children
}

/**
 * Route guard that checks if a feature is enabled in the allauth config.
 * Redirects to fallback if feature is disabled.
 */
type FeatureKey = 'signup' | 'login_by_code' | 'mfa' | 'socialaccount'

function isFeatureEnabled(config: any, feature: FeatureKey): boolean | undefined {
    if (!config?.data) return undefined
    switch (feature) {
        case 'signup': return config.data.account?.is_open_for_signup
        case 'login_by_code': return config.data.account?.login_by_code_enabled
        case 'mfa': return config.data.mfa !== undefined
        case 'socialaccount': return (config.data.socialaccount?.providers?.length ?? 0) > 0
    }
}

export function FeatureRoute({
    children,
    feature,
    redirectTo,
}: {
    children: React.ReactNode
    feature: FeatureKey
    redirectTo?: string
}) {
    const router = useRouter()
    const allauthConfig = useConfig()
    const config = useAllauthConfig()

    const enabled = isFeatureEnabled(allauthConfig, feature)
    const fallback = redirectTo ?? config.routes.login

    useEffect(() => {
        if (allauthConfig && enabled === false) {
            router.replace(fallback)
        }
    }, [allauthConfig, enabled, fallback, router])

    if (!allauthConfig || enabled === false) return null
    return children
}
