import { createContext, useContext, useEffect, useState, ReactNode } from 'react';
import { useAuth0 } from '@auth0/auth0-react';
import { api } from '@/lib/api';

interface BackendUser {
  id: string;
  auth0Id: string;
  email: string;
  name: string | null;
  picture: string | null;
  role: string;
  isApproved: boolean;
}

interface AuthContextType {
  isAuthenticated: boolean;
  isLoading: boolean;
  user: any;
  backendUser: BackendUser | null;
  isApproved: boolean;
  isFetchingUser: boolean;
  authError: string | null;
  loginWithRedirect: () => void;
  logout: () => void;
}

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

export function AuthProvider({ children }: { children: ReactNode }) {
  const {
    isAuthenticated,
    isLoading,
    user,
    loginWithRedirect,
    logout: auth0Logout,
    getAccessTokenSilently,
  } = useAuth0();

  const [backendUser, setBackendUser] = useState<BackendUser | null>(null);
  const [fetchingUser, setFetchingUser] = useState(false);
  const [authError, setAuthError] = useState<string | null>(null);

  // Set up token and fetch backend user profile
  useEffect(() => {
    // Wait for Auth0 to finish loading before fetching token
    if (isAuthenticated && !isLoading && !fetchingUser && !backendUser) {
      setFetchingUser(true);
      setAuthError(null);

      // Add timeout to prevent infinite loading
      const timeoutId = setTimeout(() => {
        setAuthError('Authentication timeout - please try logging in again');
        setFetchingUser(false);
      }, 10000); // 10 second timeout

      getAccessTokenSilently()
        .then(async (token) => {
          clearTimeout(timeoutId);
          console.log('[AUTH] Got access token, fetching user profile');
          localStorage.setItem('auth0_token', token);

          // Fetch backend user profile
          try {
            const response = await api.get('/auth/profile');
            console.log('[AUTH] User profile fetched successfully:', response.data.email);
            setBackendUser(response.data);
            setAuthError(null);
          } catch (error: any) {
            console.error('[AUTH] Failed to fetch user profile:', error);
            setBackendUser(null);

            // Set specific error message
            if (error.response?.status === 401) {
              setAuthError('Your account is pending approval or your session has expired');
            } else {
              setAuthError('Failed to load user profile - please try logging in again');
            }
          }
        })
        .catch((error) => {
          clearTimeout(timeoutId);
          console.error('[AUTH] Failed to get token:', error);
          setBackendUser(null);

          // Handle specific Auth0 errors
          if (error.error === 'missing_refresh_token' || error.message?.includes('Missing Refresh Token')) {
            setAuthError('Session expired - please log in again');
          } else if (error.error === 'login_required') {
            setAuthError('Login required');
          } else {
            setAuthError('Authentication failed - please try logging in again');
          }
        })
        .finally(() => {
          setFetchingUser(false);
        });
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [isAuthenticated, isLoading]);

  const handleLogout = () => {
    localStorage.removeItem('auth0_token');
    auth0Logout({ logoutParams: { returnTo: window.location.origin } });
  };

  return (
    <AuthContext.Provider
      value={{
        isAuthenticated,
        isLoading: isLoading || fetchingUser,
        user,
        backendUser,
        isApproved: backendUser?.isApproved ?? false,
        isFetchingUser: fetchingUser,
        authError,
        loginWithRedirect,
        logout: handleLogout,
      }}
    >
      {children}
    </AuthContext.Provider>
  );
}

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