import { createContext, useContext, useState, useEffect, useRef } from 'react';
import {
  createUserWithEmailAndPassword,
  signInWithEmailAndPassword,
  signOut,
  onAuthStateChanged,
  updateProfile,
  sendPasswordResetEmail,
  GoogleAuthProvider,
  signInWithPopup,
  signInWithRedirect,
  getRedirectResult,
  sendEmailVerification,
} from 'firebase/auth';
import { doc, setDoc, getDoc, serverTimestamp } from 'firebase/firestore';
import { auth, db } from '../services/firebase';
import { COLLECTIONS, ROLES } from '../utils/constants';

const AuthContext = createContext(null);

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

export function AuthProvider({ children }) {
  const [currentUser, setCurrentUser] = useState(null);
  const [userProfile, setUserProfile] = useState(null);
  const [loading, setLoading] = useState(true);

  // Fetch user profile from Firestore
  async function fetchUserProfile(user) {
    if (!user) {
      setUserProfile(null);
      return null;
    }
    try {
      const docRef = doc(db, COLLECTIONS.USERS, user.uid);
      const docSnap = await getDoc(docRef);
      if (docSnap.exists()) {
        const profile = { uid: user.uid, ...docSnap.data() };
        setUserProfile(profile);
        return profile;
      }
      return null;
    } catch (error) {
      console.error('Error fetching user profile:', error);
      return null;
    }
  }

  // Register with email/password
  async function register(email, password, displayName, phoneNumber = '') {
    const { user } = await createUserWithEmailAndPassword(auth, email, password);

    // Update Firebase Auth profile
    await updateProfile(user, { displayName });

    // Create Firestore user document
    const userDoc = {
      email,
      displayName,
      phoneNumber,
      role: ROLES.CITIZEN,
      createdAt: serverTimestamp(),
      isWhitelisted: false,
      profileImage: '',
      status: 'active',
    };

    await setDoc(doc(db, COLLECTIONS.USERS, user.uid), userDoc);
    setUserProfile({ uid: user.uid, ...userDoc });

    // Send verification email
    await sendEmailVerification(user);

    return user;
  }

  // Login with email/password
  async function login(email, password) {
    const { user } = await signInWithEmailAndPassword(auth, email, password);
    await fetchUserProfile(user);
    return user;
  }

  // Create or fetch Google user profile in Firestore
  async function handleGoogleUser(user) {
    const docRef = doc(db, COLLECTIONS.USERS, user.uid);
    const docSnap = await getDoc(docRef);

    if (!docSnap.exists()) {
      // First time Google sign-in — create profile
      const userDoc = {
        email: user.email,
        displayName: user.displayName || '',
        phoneNumber: user.phoneNumber || '',
        role: ROLES.CITIZEN,
        createdAt: serverTimestamp(),
        isWhitelisted: false,
        profileImage: user.photoURL || '',
        status: 'active',
      };
      await setDoc(docRef, userDoc);
      setUserProfile({ uid: user.uid, ...userDoc });
    } else {
      await fetchUserProfile(user);
    }
    return user;
  }

  // Google sign-in — try popup first, fall back to redirect
  async function loginWithGoogle() {
    const provider = new GoogleAuthProvider();
    try {
      const { user } = await signInWithPopup(auth, provider);
      return await handleGoogleUser(user);
    } catch (error) {
      // If popup blocked by COOP or browser policy, use redirect
      if (
        error.code === 'auth/popup-blocked' ||
        error.code === 'auth/popup-closed-by-user' ||
        error.code === 'auth/cancelled-popup-request' ||
        error.message?.includes('Cross-Origin-Opener-Policy')
      ) {
        await signInWithRedirect(auth, provider);
        return null; // Will be handled by getRedirectResult on reload
      }
      throw error;
    }
  }

  // Logout
  async function logout() {
    await signOut(auth);
    setCurrentUser(null);
    setUserProfile(null);
  }

  // Reset password
  async function resetPassword(email) {
    await sendPasswordResetEmail(auth, email);
  }

  // Resend Verification Email
  async function resendVerification() {
    if (currentUser) {
      await sendEmailVerification(currentUser);
    }
  }

  // Check role access
  function hasRole(requiredRole) {
    if (!userProfile) return false;
    const roleHierarchy = [
      ROLES.CITIZEN,
      ROLES.VOLUNTEER_COORDINATOR,
      ROLES.MANAGER,
      ROLES.CONTENT_MANAGER,
      ROLES.ADMIN,
    ];
    const userRoleIndex = roleHierarchy.indexOf(userProfile.role);
    const requiredRoleIndex = roleHierarchy.indexOf(requiredRole);
    return userRoleIndex >= requiredRoleIndex;
  }

  // Check specific role (exact match)
  function isRole(role) {
    return userProfile?.role === role;
  }

  // Handle redirect result (for Google sign-in redirect fallback)
  const redirectHandled = useRef(false);
  useEffect(() => {
    if (redirectHandled.current) return;
    redirectHandled.current = true;

    getRedirectResult(auth)
      .then(async (result) => {
        if (result?.user) {
          await handleGoogleUser(result.user);
        }
      })
      .catch((error) => {
        console.error('Redirect result error:', error);
      });
  }, []);

  // Auth state listener
  useEffect(() => {
    const unsubscribe = onAuthStateChanged(auth, async (user) => {
      setCurrentUser(user);
      if (user) {
        await fetchUserProfile(user);
      } else {
        setUserProfile(null);
      }
      setLoading(false);
    });

    return unsubscribe;
  }, []);

  const value = {
    currentUser,
    userProfile,
    loading,
    register,
    login,
    loginWithGoogle,
    logout,
    resetPassword,
    resendVerification,
    hasRole,
    isRole,
    fetchUserProfile,
  };

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

export default AuthContext;
