'use client'
import { createContext, useContext, useEffect, useState, ReactNode, useCallback, useMemo, useRef } from 'react'
import { useRouter } from 'next/navigation'
import { loginUser, logoutUser, AuthenticationError } from '@/lib/auth'
import { getUserInfo } from '@/lib/api'
import { ENV_CONFIG } from '@/lib/env-config'
import { isExpired, parseJwt } from '@/lib/jwt'
import { httpClient } from '@/lib/http'
import type { 
  AuthContextType, 
  UserData, 
  AuthStatus,
  UserType
} from '@/types/auth'
import { AUTH_STORAGE_KEYS, LOGIN_ROUTES } from '@/types/auth'

const AuthContext = createContext<AuthContextType | undefined>(undefined)

export function AuthProvider({ children }: { children: ReactNode }) {
  const [authStatus, setAuthStatus] = useState<AuthStatus>('loading')
  const [user, setUser] = useState<UserData | null>(null)
  const [token, setToken] = useState<string | null>(null)
  const router = useRouter()
  const hasInitialized = useRef(false)

  // Utilitários de armazenamento memorizados
  const clearAuthData = useCallback(() => {
    if (typeof window !== 'undefined') {
      localStorage.removeItem(AUTH_STORAGE_KEYS.TOKEN)
      localStorage.removeItem(AUTH_STORAGE_KEYS.USER)
      localStorage.removeItem(AUTH_STORAGE_KEYS.REFRESH_TOKEN)
      // Manter USER_TYPE para redirecionamento correto
    }
    setUser(null)
    setToken(null)
    setAuthStatus('unauthenticated')
    console.log('[AUTH] Dados de autenticação limpos - logout realizado')
  }, [])

  const saveAuthData = useCallback((
    accessToken: string,
    userData: UserData,
    refreshToken?: string
  ) => {
    try {
      if (typeof window !== 'undefined') {
        // Persistir dados de forma atômica
        localStorage.setItem(AUTH_STORAGE_KEYS.TOKEN, accessToken)
        // Garantir que roles também sejam persistidos se presentes
        const toStore = { ...userData } as any
        if (userData && (userData as any).roles) {
          toStore.roles = (userData as any).roles
        }
        localStorage.setItem(AUTH_STORAGE_KEYS.USER, JSON.stringify(toStore))
        localStorage.setItem(AUTH_STORAGE_KEYS.USER_TYPE, toStore.userType)
        
        if (refreshToken) {
          localStorage.setItem(AUTH_STORAGE_KEYS.REFRESH_TOKEN, refreshToken)
        }
      }
      
      setToken(accessToken)
  // Garantir que o estado mantenha roles também
  setUser(userData as any)
      setAuthStatus('authenticated')
      
      console.log('[AUTH] LOGIN realizado - Dados salvos!', {
        userType: userData.userType,
        email: userData.email,
        timestamp: new Date().toLocaleTimeString()
      })
    } catch (error) {
      console.error('[AUTH] Erro ao salvar dados:', error)
      clearAuthData()
    }
  }, [clearAuthData])

  // Verificação inicial de autenticação
  const checkAuth = useCallback(async (): Promise<void> => {
    if (typeof window === 'undefined') {
      setAuthStatus('unauthenticated')
      return
    }

    try {
      const storedToken = localStorage.getItem(AUTH_STORAGE_KEYS.TOKEN)
      const storedUser = localStorage.getItem(AUTH_STORAGE_KEYS.USER)

      console.log('[AUTH] Verificando sessão...', {
        hasToken: !!storedToken,
        hasUser: !!storedUser,
        timestamp: new Date().toLocaleTimeString()
      })

      // Pequeno delay para visualizar logs
      await new Promise(resolve => setTimeout(resolve, 800))

      if (!storedToken || !storedUser) {
        console.log('[AUTH] Dados ausentes - sessão inválida')
        await new Promise(resolve => setTimeout(resolve, 500))
        clearAuthData()
        return
      }

      // Verificar se token está expirado
      if (isExpired(storedToken)) {
        console.log('[AUTH] Token expirado - tentando renovar...')
        await new Promise(resolve => setTimeout(resolve, 1000))

        const refreshToken = localStorage.getItem(AUTH_STORAGE_KEYS.REFRESH_TOKEN)
        if (refreshToken && !isExpired(refreshToken)) {
          // Refresh automático foi desativado no cliente. A renovação de tokens
          // deve ser feita via backend seguro. Se desejar habilitar refresh no
          // cliente, implemente um flow server-side ou use o SDK autenticado.
          console.log('[AUTH] Refresh token presente, mas refresh automático desativado no cliente')
        }

        clearAuthData()
        return
      }

      // Restaurar sessão válida
      const userData = JSON.parse(storedUser) as UserData
      setToken(storedToken)
      // Nota: chamadas a user-info foram removidas do cliente. Mantemos os dados do
      // usuário que já estavam persistidos localmente sem tentar reconciliar com funções remotas.

      setUser(userData)
      setAuthStatus('authenticated')

      console.log('[AUTH] Sessão RESTAURADA com sucesso!', {
        userId: userData.id,
        userType: userData.userType,
        email: userData.email,
        timestamp: new Date().toLocaleTimeString()
      })
      await new Promise(resolve => setTimeout(resolve, 1000))

    } catch (error) {
      console.error('[AUTH] Erro na verificação:', error)
      clearAuthData()
    }
  }, [clearAuthData])

  // Login memoizado
  const login = useCallback(async (
    email: string,
    password: string,
    userType: UserType
  ): Promise<boolean> => {
    try {
      console.log('[AUTH] Iniciando login:', { email, userType })
      
  const response = await loginUser(email, password)
      
      // Nota: busca de user-info e reconciliação via funções server-side foi removida do cliente.
      // Mantemos o objeto response.user retornado pelo fluxo de autenticação sem tentativas
      // adicionais de mesclagem aqui.

      // Salva dados iniciais (token + user retornado pelo login)
      saveAuthData(
        response.access_token,
        response.user,
        response.refresh_token
      )

      // Tentar buscar informações consolidadas do usuário (profile + roles)
      try {
        const userInfo = await getUserInfo()
        if (userInfo) {
        const mergedUser: any = {
            ...response.user,
            // prefer profile and roles vindos do userInfo
            profile: userInfo.profile ?? (response.user as any).profile,
            roles: userInfo.roles ?? (response.user as any).roles ?? [],
            // garantir id/email caso estejam no userInfo
            id: (response.user as any).id || (userInfo.user as any)?.id,
            email: (response.user as any).email || (userInfo.user as any)?.email,
          }

          // Inferir userType a partir de roles se estiver ausente
          if (!mergedUser.userType || mergedUser.userType === undefined) {
            const r: string[] = mergedUser.roles || [];
            if (r.includes('admin') || r.includes('gestor') || r.includes('secretaria')) mergedUser.userType = 'administrador'
            else if (r.includes('medico') || r.includes('enfermeiro')) mergedUser.userType = 'profissional'
            else if (r.includes('paciente')) mergedUser.userType = 'paciente'
          }

          // Persistir e atualizar estado com dados consolidados
          try {
            if (typeof window !== 'undefined') {
              localStorage.setItem(AUTH_STORAGE_KEYS.USER, JSON.stringify(mergedUser))
              localStorage.setItem(AUTH_STORAGE_KEYS.USER_TYPE, mergedUser.userType || '')
            }
            setUser(mergedUser as any)
            console.log('[AUTH] userInfo consolidado e salvo:', { email: mergedUser.email, roles: mergedUser.roles })
          } catch (e) {
            console.warn('[AUTH] Não foi possível persistir userInfo consolidado:', e)
          }
        }
      } catch (infoErr) {
        console.warn('[AUTH] getUserInfo falhou (ignorar no cliente):', infoErr)
      }

      console.log('[AUTH] Login realizado com sucesso')
      return true

    } catch (error) {
      console.error('[AUTH] Erro no login:', error)
      
      if (error instanceof AuthenticationError) {
        throw error
      }
      
      throw new AuthenticationError(
        'Erro inesperado durante o login',
        'UNKNOWN_ERROR',
        error
      )
    }
  }, [saveAuthData])

  // Logout memoizado
  const logout = useCallback(async (): Promise<void> => {
    console.log('[AUTH] Iniciando logout')
    
    const currentUserType = user?.userType || 
      (typeof window !== 'undefined' ? localStorage.getItem(AUTH_STORAGE_KEYS.USER_TYPE) : null) || 
      'profissional'
    
    try {
      if (token) {
        await logoutUser(token)
        console.log('[AUTH] Logout realizado na API')
      }
    } catch (error) {
      console.error('[AUTH] Erro no logout da API:', error)
    }

    clearAuthData()
    
    // Redirecionamento baseado no tipo de usuário
    const loginRoute = LOGIN_ROUTES[currentUserType as UserType] || '/login'
    
    console.log('[AUTH] Redirecionando para:', loginRoute)
    
    if (typeof window !== 'undefined') {
      window.location.href = loginRoute
    }
  }, [user?.userType, token, clearAuthData])

  // Refresh token memoizado (usado pelo HTTP client)
  const refreshToken = useCallback(async (): Promise<boolean> => {
    // Esta função é principalmente para compatibilidade
    // O refresh real é feito pelo HTTP client
    return false
  }, [])

  // Getters memorizados
  const contextValue = useMemo(() => ({
    authStatus,
    user,
    token,
    login,
    logout,
    refreshToken
  }), [authStatus, user, token, login, logout, refreshToken])

  // Inicialização única
  useEffect(() => {
    if (!hasInitialized.current && typeof window !== 'undefined') {
      hasInitialized.current = true
      checkAuth()
    }
  }, [checkAuth])

  return (
    <AuthContext.Provider value={contextValue}>
      {children}
    </AuthContext.Provider>
  )
}

export const useAuth = () => {
  const context = useContext(AuthContext)
  if (context === undefined) {
    throw new Error('useAuth deve ser usado dentro de AuthProvider')
  }
  return context
}