'use client';

import React, { createContext, useContext, useState, useEffect, useCallback } from 'react';
import { useRouter } from 'next/navigation';
import { User, LoginCredentials, RegisterData, AuthResponse } from '@/types';
import { authService } from '@/services/auth.service';
import { setToken, removeToken, getToken, storage } from '@/utils/helpers';
import { STORAGE_KEYS, ROUTES } from '@/utils/constants';
import toast from 'react-hot-toast';

interface AuthContextType {
  user: User | null;
  isLoading: boolean;
  isAuthenticated: boolean;
  login: (credentials: LoginCredentials) => Promise<void>;
  register: (data: RegisterData) => Promise<void>;
  logout: () => Promise<void>;
  googleLogin: (token: string) => Promise<void>;
  facebookLogin: (token: string) => Promise<void>;
  refreshUser: () => Promise<void>;
}

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

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

interface AuthProviderProps {
  children: React.ReactNode;
}

export const AuthProvider: React.FC<AuthProviderProps> = ({ children }) => {
  const [user, setUser] = useState<User | null>(null);
  const [isLoading, setIsLoading] = useState(true);
  const router = useRouter();

  const loadUser = useCallback(async () => {
    const token = getToken();
    if (!token) {
      setIsLoading(false);
      return;
    }

    // Try to load cached user first for faster initial render
    const cachedUser = storage.get(STORAGE_KEYS.USER);
    if (cachedUser) {
      try {
        const parsedUser = JSON.parse(cachedUser);
        setUser(parsedUser);
        setIsLoading(false);

        // Refresh user data in background (don't block UI)
        authService.getCurrentUser()
          .then(userData => {
            setUser(userData);
            storage.set(STORAGE_KEYS.USER, JSON.stringify(userData));
          })
          .catch(error => {
            console.error('Error refreshing user:', error);
            // If refresh fails, keep cached user
          });
        return;
      } catch (e) {
        // Invalid cached data, continue to fetch
      }
    }

    try {
      const userData = await authService.getCurrentUser();
      setUser(userData);
      storage.set(STORAGE_KEYS.USER, JSON.stringify(userData));
    } catch (error) {
      console.error('Error loading user:', error);
      removeToken();
      storage.remove(STORAGE_KEYS.USER);
    } finally {
      setIsLoading(false);
    }
  }, []);

  useEffect(() => {
    loadUser();
  }, [loadUser]);

  const login = async (credentials: LoginCredentials) => {
    try {
      const response: AuthResponse = await authService.login(credentials);
      setToken(response.token);
      setUser(response.user);
      storage.set(STORAGE_KEYS.USER, JSON.stringify(response.user));
      toast.success('Connexion réussie !');

      // Redirect based on role (support both uppercase and lowercase)
      // Use replace() to remove login page from history
      const role = response.user.role.toUpperCase();
      if (role === 'ADMIN') {
        router.replace(ROUTES.ADMIN_DASHBOARD);
      } else if (role === 'EMPLOYEE') {
        router.replace(ROUTES.EMPLOYEE_DASHBOARD);
      } else {
        router.replace(ROUTES.CLIENT_DASHBOARD);
      }
    } catch (error: any) {
      toast.error(error.message || 'Erreur lors de la connexion');
      throw error;
    }
  };

  const register = async (data: RegisterData) => {
    try {
      const response: AuthResponse = await authService.register(data);
      setToken(response.token);
      setUser(response.user);
      storage.set(STORAGE_KEYS.USER, JSON.stringify(response.user));
      toast.success('Inscription réussie !');
      router.push(ROUTES.CLIENT_DASHBOARD);
    } catch (error: any) {
      toast.error(error.message || 'Erreur lors de l\'inscription');
      throw error;
    }
  };

  const logout = async () => {
    try {
      await authService.logout();
    } catch (error) {
      console.error('Error during logout:', error);
    } finally {
      removeToken();
      storage.remove(STORAGE_KEYS.USER);
      setUser(null);
      toast.success('Déconnexion réussie');
      router.push(ROUTES.LOGIN);
    }
  };

  const googleLogin = async (token: string) => {
    try {
      const response: AuthResponse = await authService.googleLogin(token);
      setToken(response.token);
      setUser(response.user);
      storage.set(STORAGE_KEYS.USER, JSON.stringify(response.user));
      toast.success('Connexion avec Google réussie !');

      // Redirect based on role (support both uppercase and lowercase)
      // Use replace() to remove login page from history
      const role = response.user.role.toUpperCase();
      if (role === 'ADMIN') {
        router.replace(ROUTES.ADMIN_DASHBOARD);
      } else if (role === 'EMPLOYEE') {
        router.replace(ROUTES.EMPLOYEE_DASHBOARD);
      } else {
        router.replace(ROUTES.CLIENT_DASHBOARD);
      }
    } catch (error: any) {
      toast.error(error.message || 'Erreur lors de la connexion avec Google');
      throw error;
    }
  };

  const facebookLogin = async (token: string) => {
    try {
      const response: AuthResponse = await authService.facebookLogin(token);
      setToken(response.token);
      setUser(response.user);
      storage.set(STORAGE_KEYS.USER, JSON.stringify(response.user));
      toast.success('Connexion avec Facebook réussie !');

      // Redirect based on role (support both uppercase and lowercase)
      // Use replace() to remove login page from history
      const role = response.user.role.toUpperCase();
      if (role === 'ADMIN') {
        router.replace(ROUTES.ADMIN_DASHBOARD);
      } else if (role === 'EMPLOYEE') {
        router.replace(ROUTES.EMPLOYEE_DASHBOARD);
      } else {
        router.replace(ROUTES.CLIENT_DASHBOARD);
      }
    } catch (error: any) {
      toast.error(error.message || 'Erreur lors de la connexion avec Facebook');
      throw error;
    }
  };

  const refreshUser = async () => {
    try {
      const userData = await authService.getCurrentUser();
      setUser(userData);
      storage.set(STORAGE_KEYS.USER, JSON.stringify(userData));
    } catch (error) {
      console.error('Error refreshing user:', error);
      throw error;
    }
  };

  const value: AuthContextType = {
    user,
    isLoading,
    isAuthenticated: !!user,
    login,
    register,
    logout,
    googleLogin,
    facebookLogin,
    refreshUser,
  };

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