import { UserEntity } from "../../data/datasource/api/entities/user";
import axios from "axios";
import { UserRole } from "../constants/roles";
import {
  ReactNode,
  createContext,
  useContext,
  useEffect,
  useState,
} from "react";

// Define the shape of the context state and actions
type AuthContextType = {
  user: UserEntity | null; // The authenticated user or null if not authenticated
  login: (user: UserEntity, token: string) => void; // Function to log in the user
  logout: () => void; // Function to log out the user
};

// Create the context with default values
const AuthContext = createContext<AuthContextType>({
  user: null,
  login: () => {},
  logout: () => {},
});

// Define the props for the AuthContextProvider component
type AuthContextProviderProps = {
  children: ReactNode; // The child components that will have access to the context
};

// Create the provider component
export const AuthContextProvider = ({ children }: AuthContextProviderProps) => {
  const [user, setUser] = useState<UserEntity | null>(null); // State to track the authenticated user

  // Function to save the session data in local storage and set the authorization header
  const saveSession = async (user: UserEntity, token: string) => {
    setUser(user);
    localStorage.setItem("token", token);
    localStorage.setItem("user", JSON.stringify(user));
    axios.defaults.headers.common["Authorization"] = `Bearer ${token}`;
  };

  // Function to delete the session data from local storage and clear the authorization header
  const deleteSession = async () => {
    setUser(null);
    localStorage.removeItem("token");
    localStorage.removeItem("user");
    axios.defaults.headers.common["Authorization"] = "";
  };

  // Function to log in the user by saving the session
  const login = async (user: UserEntity, token: string) => {
    await saveSession(user, token);
  };

  // Function to log out the user by deleting the session
  const logout = async () => {
    await deleteSession();
  };

  // Check if there is an existing session in local storage when the component mounts
  useEffect(() => {
    const checkSession = async () => {
      const token = localStorage.getItem("token");
      const user = localStorage.getItem("user");
      if (token && user) {
        const sessionUser = JSON.parse(user);
        await saveSession(
          {
            email: sessionUser.email as string,
            name: sessionUser.name as string,
            role: sessionUser.role as UserRole,
          },
          token
        );
      }
    };
    checkSession();
  }, []);

  // Provide the context value to child components
  const value = { user, login, logout };
  return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
};

// Custom hook to use the AuthContext
export const useAuth = () => {
  if (AuthContext === undefined) {
    throw new Error("useAuth debe se usado dentro de un AuthContextProvider");
  }
  return useContext(AuthContext);
};
