import React, { createContext, useContext, useEffect, useMemo, useState } from "react";
import { UserManager } from "oidc-client-ts";
import { ConfigContext } from "./ConfigProvider";

export const AuthContext = createContext({
    user: null,
    login: () => {},
    logout: () => {},
    roles: [],
});

const AuthProvider = ({ children }) => {
    const { config, isLoading, error } = useContext(ConfigContext);
    const [user, setUser] = useState(null);
    const [roles, setRoles] = useState([]);

    const userManager = useMemo(() => {
        if (config && config.OIDC_CONFIG) {
            return new UserManager(config.OIDC_CONFIG);
        }
        return null;
    }, [config]);

    useEffect(() => {
        if (isLoading || error || !userManager) return;

        userManager.getUser()
            .then((user) => {
                if (user && !user.expired) {
                    setUser(user);
                    localStorage.setItem("accessToken", user.access_token);
                    const clientRoles = user?.profile?.resource_access?.[config.KC_CLIENT_ID]?.roles || [];
                    setRoles(clientRoles);
                } else if (user && user.expired) {
                    userManager
                        .signinSilent()
                        .then((newUser) => {
                            setUser(newUser);
                            localStorage.setItem("accessToken", newUser.access_token);
                            const clientRoles = newUser?.profile?.resource_access?.[config.KC_CLIENT_ID]?.roles || [];
                            setRoles(clientRoles);
                        })
                        .catch((err) => {
                            console.error(err);
                            logout();
                        });
                }
            })
            .catch((err) => {
                console.error(err);
                logout();
            });

        const onUserLoaded = (loadedUser) => {
            setUser(loadedUser);
            localStorage.setItem("accessToken", loadedUser.access_token);
            const clientRoles = loadedUser?.profile?.resource_access?.[config.KC_CLIENT_ID]?.roles || [];
            setRoles(clientRoles);
        };

        const onUserUnloaded = () => {
            setUser(null);
            setRoles([]);
            localStorage.removeItem("accessToken");
        };

        userManager.events.addUserLoaded(onUserLoaded);
        userManager.events.addUserUnloaded(onUserUnloaded);

        return () => {
            userManager.events.removeUserLoaded(onUserLoaded);
            userManager.events.removeUserUnloaded(onUserUnloaded);
        };
    }, [userManager, isLoading, error, config]);

    const login = () => {
        if (userManager) {
            userManager
                .signinRedirect()
                .catch((err) => {
                    console.log(config);
                    console.log(err);
                });
        }
    };

    const logout = () => {
        if (userManager) {
            userManager.signoutRedirect();
        }
    };

    return (
        <AuthContext.Provider value={{ user, roles, login, logout }}>
            {children}
        </AuthContext.Provider>
    );
};

export default AuthProvider;
