import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react';
import { isAuthenticated, checkAdminExists, getToken as getStoredToken, clearToken, setToken as storeToken } from '../utils/auth';
import api, { API_URL } from '../services/api';
import { User } from '../types';

interface AuthContextType {
  isAuthenticated: boolean;
  user: User | null;
  isLoading: boolean;
  adminExists: boolean;
  login: (token: string, userData: User, remember?: boolean) => Promise<void>;
  logout: () => void;
  updateUser: (userData: Partial<User>) => void;
}

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

export const AuthProvider: React.FC<{ children: ReactNode }> = ({ children }) => {
  const [user, setUser] = useState<User | null>(null);
  const [authenticated, setAuthenticated] = useState<boolean>(false);
  const [loading, setLoading] = useState<boolean>(true);
  const [adminExists, setAdminExists] = useState<boolean>(false);

  useEffect(() => {
    const initializeAuth = async () => {
      // Check if admin exists
      const adminCheck = await checkAdminExists();
      setAdminExists(adminCheck);
      
      // Check authentication
      const token = getStoredToken();
      if (token && isAuthenticated()) {
        try {
          // Fetch user data from API
          const base = API_URL;
          const response = await fetch(`${base}/auth/me`, {
            credentials: 'include',
            headers: {
              'Authorization': `Bearer ${token}`
            }
          });
          if (response.ok) {
            const data = await response.json();
            const userData = data.user || data;
            setUser(userData);
            setAuthenticated(true);
            
            // If this is the first user, they become admin
            if (!adminCheck && !userData.role) {
              const makeAdminResponse = await fetch(`${base}/auth/make-admin`, {
                method: 'POST',
                headers: {
                  'Authorization': `Bearer ${token}`,
                  'Content-Type': 'application/json'
                }
              });
              
              if (makeAdminResponse.ok) {
                const updatedUser = { ...userData, role: 'admin' };
                setUser(updatedUser);
                setAdminExists(true);
              }
            }
          } else {
            clearToken();
          }
        } catch (error) {
          console.error('Error initializing auth:', error);
          clearToken();
        }
      }
      setLoading(false);
    };
    
    initializeAuth();
  }, []);

  const login = async (token: string, userData: User, remember: boolean = true) => {
    storeToken(token, remember);
    
    // If the user already has admin role, reflect it immediately
    if (userData.role === 'admin') {
      setAdminExists(true);
    }
    // Otherwise, try to promote if no admin exists
    else if (!adminExists && !userData.role) {
      try {
        const base = API_URL;
        const response = await fetch(`${base}/auth/make-admin`, {
          method: 'POST',
          headers: {
            'Authorization': `Bearer ${token}`,
            'Content-Type': 'application/json'
          }
        });
        
        if (response.ok) {
          userData.role = 'admin';
          setAdminExists(true);
        }
      } catch (error) {
        console.error('Error making user admin:', error);
      }
    }
    setUser(userData);
    setAuthenticated(true);
  };

  const updateUser = (userData: Partial<User>) => {
    if (user) {
      setUser({ ...user, ...userData });
    }
  };

  const logout = () => {
    // Attempt to clear server-side HttpOnly cookie (if used)
    try {
      // Use axios instance with credentials enabled
      api.post('/auth/logout').catch(() => {});
    } catch {}
    clearToken();
    setUser(null);
    setAuthenticated(false);
  };

  return (
    <AuthContext.Provider value={{
      isAuthenticated: authenticated,
      user,
      isLoading: loading,
      adminExists,
      login,
      logout,
      updateUser
    }}>
      {children}
    </AuthContext.Provider>
  );
};

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