import { createContext, useContext, useState, useEffect, useCallback, useMemo } from 'react';
import type { ReactNode } from 'react';
import { useNavigate } from 'react-router-dom';
import { authService, type AppUser, type UserRole } from '@/api';

interface AuthSession {
  user: AppUser;
  access_token: string;
}

interface AuthContextType {
  user: AppUser | null;
  session: AuthSession | null;
  userRole: UserRole;
  loading: boolean;
  signIn: (username: string, password: string) => Promise<{ error: { message: string } | null }>;
  signOut: () => Promise<void>;
}

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

/**
 * Maps the API user_id to the application's UserRole.
 * 1 -> helpdesk
 * 2 -> bank_customer
 * 3 -> manufacturing_customer
 */
const mapUserIdToRole = (userId: string): UserRole => {
  switch (userId) {
    case '1':
      return 'helpdesk';
    case '2':
      return 'bank_customer';
    case '3':
      return 'manufacturing_customer';
    default:
      console.warn(`Unknown user_id: ${userId}. Defaulting to null role.`);
      return null;
  }
};

export const AuthProvider = ({ children }: { children: ReactNode }) => {
  // OPTIMIZATION: Initialize from localStorage synchronously to avoid blocking render
  const getInitialSession = (): AuthSession | null => {
    try {
      const storedSession = localStorage.getItem('dealer360_session');
      if (storedSession) {
        return JSON.parse(storedSession) as AuthSession;
      }
    } catch (e) {
      localStorage.removeItem('dealer360_session');
    }
    return null;
  };

  const initialSession = getInitialSession();
  const [user, setUser] = useState<AppUser | null>(initialSession?.user || null);
  const [session, setSession] = useState<AuthSession | null>(initialSession);
  const [userRole, setUserRole] = useState<UserRole>(initialSession?.user?.role || null);
  const [loading, setLoading] = useState(false); // Start as false since we sync synchronously
  const navigate = useNavigate();

  // Helper to sync state from localStorage
  const syncStateFromStorage = useCallback(() => {
    const storedSession = localStorage.getItem('dealer360_session');
    if (storedSession) {
      try {
        const parsedSession = JSON.parse(storedSession) as AuthSession;
        setSession(parsedSession);
        setUser(parsedSession.user);
        setUserRole(parsedSession.user.role);
      } catch (e) {
        localStorage.removeItem('dealer360_session');
        setSession(null);
        setUser(null);
        setUserRole(null);
      }
    } else {
      setSession(null);
      setUser(null);
      setUserRole(null);
    }
  }, []);

  useEffect(() => {
    // Initial sync (already done synchronously, but keep for consistency)
    // This is mainly for storage event listeners

    // Listen for storage changes (multi-tab support)
    const handleStorageChange = (e: StorageEvent) => {
      if (e.key === 'dealer360_session') {
        syncStateFromStorage();
        // If logged out in another tab, redirect to login
        if (!e.newValue && !window.location.pathname.includes('/login')) {
          navigate('/login');
        }
      }
    };

    window.addEventListener('storage', handleStorageChange);
    return () => window.removeEventListener('storage', handleStorageChange);
  }, [syncStateFromStorage, navigate]);

  const signIn = async (username: string, password: string): Promise<{ error: { message: string } | null }> => {
    try {
      const response = await authService.login({ username, password });

      if (response.success && response.data) {
        const { user_id, email, username: apiUsername, company_name, token } = response.data;

        const role = mapUserIdToRole(user_id);

        const appUser: AppUser = {
          id: user_id,
          username: apiUsername,
          email: email,
          role: role,
          company_name: company_name,
        };

        const authSession: AuthSession = {
          user: appUser,
          access_token: token,
        };

        // Store session in localStorage for persistence
        localStorage.setItem('dealer360_session', JSON.stringify(authSession));

        setUser(appUser);
        setSession(authSession);
        setUserRole(role);

        return { error: null };
      }

      return { error: { message: response.message || 'Login failed' } };
    } catch (error: any) {
      const errorMessage = error.response?.data?.message || error.message || 'An unexpected error occurred during login';
      return { error: { message: errorMessage } };
    }
  };

  const signOut = async () => {
    // Clear state
    localStorage.removeItem('dealer360_session');
    setUser(null);
    setSession(null);
    setUserRole(null);

    // Attempt to notify backend
    try {
      await authService.logout();
    } catch (e) {
      // Silent fail
    }

    navigate('/login');
  };

  // Memoize context value to prevent unnecessary re-renders
  const contextValue = useMemo(
    () => ({ user, session, userRole, loading, signIn, signOut }),
    [user, session, userRole, loading, signIn, signOut]
  );

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

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