import React, { useState, useEffect, useCallback, useMemo } from 'react';
import { useLogto } from '@logto/react';
import type { AppUser } from '../types';
import { AuthContext } from './AuthContextType';
import { setUser } from '../main';

const API_URL = import.meta.env.VITE_API_URL || '/api';

interface AuthProviderProps {
    children: React.ReactNode;
}

export const AuthProvider: React.FC<AuthProviderProps> = ({ children }) => {
    const { isAuthenticated, getAccessToken, fetchUserInfo, isLoading: isLogtoLoading } = useLogto();
    const [appUser, setAppUser] = useState<AppUser | null>(null);
    const [isAppLoading, setIsAppLoading] = useState(true);
    const [error, setError] = useState<string | null>(null);

    const syncUser = useCallback(async () => {
        if (!isAuthenticated) {
            setAppUser(null);
            setIsAppLoading(false);
            return;
        }

        try {
            setIsAppLoading(true);
            setError(null);

            const token = await getAccessToken();
            if (!token) throw new Error('Token não disponível');

            // Busca dados básicos do Logto se necessário
            const logtoUserInfo = await fetchUserInfo();

            const response = await fetch(`${API_URL}/users/me`, {
                headers: {
                    'Authorization': `Bearer ${token}`,
                },
            });

            if (response.status === 404 && logtoUserInfo) {
                // Usuário não existe no banco (provavelmente redirecionamento pós-login)
                // Vamos tentar sincronizar/provisionar
                const syncResp = await fetch(`${API_URL}/users/sync`, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify({
                        email: logtoUserInfo.email,
                        name: logtoUserInfo.name || logtoUserInfo.username || 'Usuário Logto',
                        logto_id: logtoUserInfo.sub
                    })
                });
                
                if (!syncResp.ok) throw new Error('Falha ao sincronizar usuário');
                
                // Tenta buscar novamente após o sync
                return syncUser();
            }

            if (!response.ok) {
                throw new Error('Falha ao carregar usuário');
            }

            const userData = await response.json();
            const effectiveRole = userData.role || 'guest';
            
            const user = {
                ...userData,
                id: userData._id || userData.id,
                role: effectiveRole,
            };
            
            setUser(token, user);
            setAppUser(user);
        } catch (err) {
            console.error('Error loading user:', err);
            setError('Erro ao carregar dados do usuário');
            setAppUser(null);
        } finally {
            setIsAppLoading(false);
        }
    }, [isAuthenticated, getAccessToken, fetchUserInfo]);

    useEffect(() => {
        if (!isLogtoLoading) {
            syncUser();
        }
    }, [isLogtoLoading, syncUser]);

    const refetchUser = useCallback(async () => {
        await syncUser();
    }, [syncUser]);

    const isDeveloper = useCallback(() => {
        return appUser?.email === 'admtracksteel@gmail.com';
    }, [appUser]);

    const isAdmin = useCallback(() => appUser?.role === 'admin' || isDeveloper(), [appUser, isDeveloper]);
    const isUser = useCallback(() => appUser?.role === 'user' || isAdmin(), [appUser, isAdmin]);
    const isGuest = useCallback(() => appUser?.role === 'guest' && !isDeveloper(), [appUser, isDeveloper]);
    const canEdit = useCallback(() => (appUser?.role !== 'guest' && appUser?.role !== undefined) || isDeveloper(), [appUser, isDeveloper]);

    const isLoading = isLogtoLoading || isAppLoading;

    const value = useMemo(() => ({
        appUser,
        isLoading,
        isSignedIn: isAuthenticated,
        error,
        isAdmin,
        isUser,
        isGuest,
        isDeveloper,
        canEdit,
        refetchUser,
    }), [appUser, isLoading, isAuthenticated, error, isAdmin, isUser, isGuest, isDeveloper, canEdit, refetchUser]);

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