import React, { createContext, useContext, useEffect, useState, useMemo, useCallback } from 'react';
import { signInWithPopup, signOut, User, createUserWithEmailAndPassword, signInWithEmailAndPassword, updateProfile } from 'firebase/auth';
import { auth, googleProvider, isFirebaseConfigured } from '../services/firebase';
import { API_URL } from '../constants';

interface AuthContextType {
    user: User | null;
    loading: boolean;
    signInWithGoogle: () => Promise<void>;
    signOutUser: () => Promise<void>;
    signInWithEmail: (email: string, password: string) => Promise<void>;
    signUpWithEmail: (email: string, password: string, displayName?: string) => Promise<void>;
    sendOTP: (email: string, inviteCode?: string) => Promise<any>;
    verifyOTP: (email: string, otp: string, inviteCode?: string) => Promise<void>;
}

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

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

    useEffect(() => {
        console.log('AuthContext initializing, isFirebaseConfigured:', isFirebaseConfigured);

        // Demo/OTP mode: Check localStorage for persisted session
        console.log('Checking for persisted OTP session');
        const sessionUser = localStorage.getItem('auditly_demo_session');
        if (sessionUser) {
            try {
                const parsedUser = JSON.parse(sessionUser);
                console.log('Restoring session for:', parsedUser.email);
                setUser(parsedUser as User);
            } catch (error) {
                console.error('Failed to parse session user:', error);
                localStorage.removeItem('auditly_demo_session');
                setUser(null);
            }
        } else {
            setUser(null);
        }
        setLoading(false);

        return () => { };

    }, []);

    const signInWithGoogle = useCallback(async () => {
        if (!isFirebaseConfigured) {
            // No-op in demo mode
            return;
        }
        await signInWithPopup(auth, googleProvider);
    }, []);

    const signOutUser = useCallback(async () => {
        try {
            // Sign out from Firebase if configured and user is signed in via Firebase
            if (isFirebaseConfigured && auth.currentUser) {
                await signOut(auth);
                console.log('Firebase signout completed');
            }
        } catch (error) {
            console.error('Firebase signout error:', error);
        }

        // Always clear all local session data
        localStorage.removeItem('auditly_demo_session');
        localStorage.removeItem('auditly_auth_token');
        localStorage.removeItem('auditly_selected_org');
        sessionStorage.clear();

        setUser(null);
        console.log('User signed out and all sessions cleared');
    }, []);

    const signInWithEmail = useCallback(async (email: string, password: string) => {
        console.log('signInWithEmail called, isFirebaseConfigured:', isFirebaseConfigured);
        try {
            console.log('Attempting Firebase auth');
            await signInWithEmailAndPassword(auth, email, password);
        } catch (e: any) {
            const code = e?.code || '';
            console.error('Firebase Auth Error:', code, e?.message);
            if (code === 'auth/configuration-not-found' || code === 'auth/operation-not-allowed') {
                console.warn('Email/Password provider disabled in Firebase. Falling back to local mock user for development.');
                const mock = { uid: `demo-${btoa(email).slice(0, 8)}`, email, displayName: email.split('@')[0] } as unknown as User;
                setUser(mock);
                return;
            }
            throw e;
        }
    }, []);

    const signUpWithEmail = useCallback(async (email: string, password: string, displayName?: string) => {
        try {
            const cred = await createUserWithEmailAndPassword(auth, email, password);
            if (displayName) {
                try { await updateProfile(cred.user, { displayName }); } catch { }
            }
        } catch (e: any) {
            const code = e?.code || '';
            if (code === 'auth/configuration-not-found' || code === 'auth/operation-not-allowed') {
                console.warn('Email/Password provider disabled in Firebase. Falling back to local mock user for development.');
                const mock = { uid: `demo-${btoa(email).slice(0, 8)}`, email, displayName: displayName || email.split('@')[0] } as unknown as User;
                setUser(mock);
                return;
            }
            throw e;
        }
    }, []);

    const sendOTP = useCallback(async (email: string, inviteCode?: string) => {
        const response = await fetch(`${API_URL}/sendOTP`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ email, inviteCode })
        });

        if (!response.ok) {
            const error = await response.json();
            throw new Error(error.error || 'Failed to send OTP');
        }

        return response.json();
    }, []);

    const verifyOTP = useCallback(async (email: string, otp: string, inviteCode?: string) => {
        const response = await fetch(`${API_URL}/verifyOTP`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ email, otp, inviteCode })
        });

        if (!response.ok) {
            const error = await response.json();
            throw new Error(error.error || 'Failed to verify OTP');
        }

        const data = await response.json();

        // Set user in auth context
        const mockUser = {
            uid: data.user.uid,
            email: data.user.email,
            displayName: data.user.displayName,
            emailVerified: true
        } as unknown as User;

        setUser(mockUser);
        localStorage.setItem('auditly_demo_session', JSON.stringify(mockUser));
        localStorage.setItem('auditly_auth_token', data.token);

        return data;
    }, []);

    // Memoize the context value to prevent unnecessary re-renders
    const contextValue = useMemo(() => ({
        user,
        loading,
        signInWithGoogle,
        signOutUser,
        signInWithEmail,
        signUpWithEmail,
        sendOTP,
        verifyOTP,
    }), [user, loading, signInWithGoogle, signOutUser, signInWithEmail, signUpWithEmail, sendOTP, verifyOTP]);


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

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