'use client' import { useEffect, useRef, useState } from 'react' import { useRouter } from 'next/navigation' import { useAuth } from '@/hooks/useAuth' import type { UserType } from '@/types/auth' import { USER_TYPE_ROUTES, LOGIN_ROUTES, AUTH_STORAGE_KEYS } from '@/types/auth' interface ProtectedRouteProps { children: React.ReactNode requiredUserType?: UserType[] requiredRoles?: string[] } export default function ProtectedRoute({ children, requiredUserType, requiredRoles }: ProtectedRouteProps) { const { authStatus, user } = useAuth() const router = useRouter() const isRedirecting = useRef(false) const [mounted, setMounted] = useState(false) const [accessDenied, setAccessDenied] = useState(false) // Computa permissões de forma síncrona a partir do user e dos roles/userType const computeHasPermission = () => { // sem requisitos, permite if ((!requiredUserType || requiredUserType.length === 0) && (!requiredRoles || requiredRoles.length === 0)) return true if (!user) return false const userRoles = (user as any).roles || [] // checa requiredRoles (strings arbitrárias de papéis) const rolesOk = requiredRoles && requiredRoles.length > 0 ? requiredRoles.some((req: string) => { if (user.userType === req) return true if (req === 'profissional' && (userRoles.includes('medico') || userRoles.includes('enfermeiro'))) return true if (req === 'administrador' && (userRoles.includes('admin') || userRoles.includes('gestor') || userRoles.includes('secretaria'))) return true if (req === 'paciente' && userRoles.includes('paciente')) return true return userRoles.includes(req) }) : false // checa requiredUserType (compatibilidade com tipos altos do sistema) const userTypeOk = requiredUserType && requiredUserType.length > 0 ? requiredUserType.some((req: UserType) => { if (user.userType === req) return true if (req === 'profissional' && (userRoles.includes('medico') || userRoles.includes('enfermeiro'))) return true if (req === 'administrador' && (userRoles.includes('admin') || userRoles.includes('gestor') || userRoles.includes('secretaria'))) return true if (req === 'paciente' && userRoles.includes('paciente')) return true return userRoles.includes(req) }) : false return rolesOk || userTypeOk } const hasPermission = computeHasPermission() useEffect(() => { // marca que o componente já montou no cliente setMounted(true) // Evitar múltiplos redirects if (isRedirecting.current) return // Durante loading, não fazer nada if (authStatus === 'loading') return // Se não autenticado, redirecionar para login if (authStatus === 'unauthenticated') { isRedirecting.current = true console.log('[PROTECTED-ROUTE] Usuário NÃO autenticado - redirecionando...') // Determinar página de login baseada no histórico let userType: UserType = 'profissional' if (typeof window !== 'undefined') { try { const storedUserType = localStorage.getItem(AUTH_STORAGE_KEYS.USER_TYPE) if (storedUserType && ['profissional', 'paciente', 'administrador'].includes(storedUserType)) { userType = storedUserType as UserType } } catch (error) { console.warn('[PROTECTED-ROUTE] Erro ao ler localStorage:', error) } } const loginRoute = LOGIN_ROUTES[userType] console.log('[PROTECTED-ROUTE] Redirecionando para login:', { userType, loginRoute, timestamp: new Date().toLocaleTimeString() }) router.push(loginRoute) return } // Se autenticado mas não tem permissão para esta página if (authStatus === 'authenticated' && user && requiredUserType && !hasPermission) { console.log('[PROTECTED-ROUTE] Usuário SEM permissão para esta página (accessDenied)', { userType: user.userType, userRoles: (user as any).roles || [], requiredTypes: requiredUserType }) // Marcar acesso negado para renderizar fallback sem redirecionamentos/speinners infinitos setAccessDenied(true) return } // Se chegou aqui, acesso está autorizado if (authStatus === 'authenticated') { console.log('[PROTECTED-ROUTE] ACESSO AUTORIZADO!', { userType: user?.userType, email: user?.email, timestamp: new Date().toLocaleTimeString() }) isRedirecting.current = false } }, [authStatus, user, requiredUserType, router, hasPermission]) // Durante loading, mostrar spinner if (authStatus === 'loading') { // evitar render no servidor para não causar mismatch de hidratação if (!mounted) return null return (

Verificando autenticação...

) } // Se não autenticado ou redirecionando para login, mostrar spinner if (authStatus === 'unauthenticated' || (isRedirecting.current && !accessDenied)) { // evitar render no servidor para não causar mismatch de hidratação if (!mounted) return null return (

Redirecionando...

) } // Se usuário não tem permissão, mostrar fallback (baseado em hasPermission) if (requiredUserType && user && !hasPermission) { return (

Acesso Negado

Você não tem permissão para acessar esta página.

Tipo de acesso necessário: {requiredUserType.join(' ou ')}
Seu tipo de acesso: {user.userType}
Seus papéis: {(user as any).roles ? (user as any).roles.join(', ') : '—'}

) } // Finalmente, renderizar conteúdo protegido return <>{children} }