import React, { createContext, useContext, useState, useEffect, useCallback } from 'react';
import type { AppUser } from '../types';
import { setApiToken, setApiOrganizationId, getBaseUrl } from '../services/api';
import { useLogto } from '@logto/react';

const API_URL = getBaseUrl();

export interface AuthContextType {
    appUser: AppUser | null;
    isLoading: boolean;
    isSignedIn: boolean;
    error: string | null;
    token: string | null;
    login: (token: string, user: AppUser) => void;
    logout: () => void;
    isAdmin: () => boolean;
    isUser: () => boolean;
    isGuest: () => boolean;
    isDeveloper: () => boolean;
    canEdit: () => boolean;
    refetchUser: () => Promise<void>;
}

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

export const AuthProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
    const { isAuthenticated, getAccessToken, signOut, isLoading: isLogtoLoading } = useLogto();
    const [appUser, setAppUser] = useState<AppUser | null>(null);
    const [token, setToken] = useState<string | null>(null);
    const [isLoading, setIsLoading] = useState(true);
    const [error, setError] = useState<string | null>(null);

    useEffect(() => {
        const fetchTokenAndUser = async () => {
             if (isAuthenticated) {
                 try {
            const accessToken = await getAccessToken(import.meta.env.VITE_LOGTO_RESOURCE || 'https://gpi.reifonas.cloud/api');
                     if (accessToken) {
                         setToken(accessToken);
                         setApiToken(accessToken);
                     }
                 } catch (err) {
                     console.error(err);
                 }
             } else if (!isLogtoLoading) {
                 setIsLoading(false);
             }
        };
        fetchTokenAndUser();
    }, [isAuthenticated, isLogtoLoading, getAccessToken]);

    // Initial load: se tem token, setar no interceptor e buscar dados do usuário
    useEffect(() => {
        if (token) {
            refetchUser();
        }
    }, [token]);

    const login = useCallback((newToken: string, user: AppUser) => {
        setToken(newToken);
        setAppUser(user);
        setApiToken(newToken);
        
        if (user.organizationId) {
             setApiOrganizationId(user.organizationId);
        }
    }, []);

    const logout = useCallback(() => {
        setToken(null);
        setAppUser(null);
        setApiToken(null);
        setApiOrganizationId(null);
        signOut(window.location.origin);
    }, [signOut]);

    const refetchUser = useCallback(async () => {
        if (!token) return;
        setIsLoading(true);
        try {
            const response = await fetch(`${API_URL}/auth/me`, {
                headers: {
                    'Authorization': `Bearer ${token}`
                },
            });

            if (response.ok) {
                const userData = await response.json();
                setAppUser(userData);
                if (userData.organizationId) {
                    setApiOrganizationId(userData.organizationId);
                }
            } else {
                // Token inválido ou expirado
                logout();
            }
        } catch (err) {
            console.error('Error refetching user:', err);
            setError('Falha na comunicação de autenticação.');
        } finally {
            setIsLoading(false);
        }
    }, [token, logout]);

    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 !== null) || isDeveloper(), [appUser, isDeveloper]);

    return (
        <AuthContext.Provider
            value={{
                appUser,
                isLoading,
                isSignedIn: !!appUser,
                error,
                token,
                login,
                logout,
                isAdmin,
                isUser,
                isGuest,
                isDeveloper,
                canEdit,
                refetchUser,
            }}
        >
            {children}
        </AuthContext.Provider>
    );
};

export const useAuth = () => {
    const context = useContext(AuthContext);
    if (!context) {
        throw new Error('useAuth must be used within an AuthProvider');
    }
    return context;
};
