import React, { createContext, useContext, useEffect, useState } from 'react';
import { onAuthStateChanged, signInWithPopup, signOut, User, createUserWithEmailAndPassword, signInWithEmailAndPassword, updateProfile } from 'firebase/auth';
import { auth, googleProvider, isFirebaseConfigured } from '../services/firebase';
import { demoStorage } from '../services/demoStorage';
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>;
    signInWithOTP: (token: string, userData: any) => 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);

        if (isFirebaseConfigured) {
            // Firebase mode: Set up proper Firebase auth state listener
            const unsubscribe = onAuthStateChanged(auth, (firebaseUser) => {
                console.log('Firebase auth state changed:', firebaseUser?.email);
                if (firebaseUser) {
                    setUser(firebaseUser);
                } else {
                    // Check for OTP session as fallback
                    const sessionUser = localStorage.getItem('auditly_demo_session');
                    if (sessionUser) {
                        try {
                            const parsedUser = JSON.parse(sessionUser);
                            console.log('Restoring OTP 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 unsubscribe;
        } else {
            // 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 = async () => {
        if (!isFirebaseConfigured) {
            // No-op in demo mode
            return;
        }
        await signInWithPopup(auth, googleProvider);
    };

    const signOutUser = 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 = async (email: string, password: string) => {
        console.log('signInWithEmail called, isFirebaseConfigured:', isFirebaseConfigured);
        if (!isFirebaseConfigured) {
            console.log('Demo mode: authenticating user', email);
            const existingUser = demoStorage.getUserByEmail(email);

            if (existingUser) {
                // Verify password
                if (demoStorage.verifyPassword(password, existingUser.passwordHash)) {
                    const mockUser = {
                        uid: existingUser.uid,
                        email: existingUser.email,
                        displayName: existingUser.displayName
                    } as unknown as User;

                    setUser(mockUser);
                    localStorage.setItem('auditly_demo_session', JSON.stringify(mockUser));
                    console.log('Demo login successful for:', email);
                } else {
                    throw new Error('Invalid password');
                }
            } else {
                throw new Error('User not found. Please sign up first.');
            }
            return;
        }
        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 = async (email: string, password: string, displayName?: string) => {
        if (!isFirebaseConfigured) {
            console.log('Demo mode: creating new user', email);
            // Check if user already exists
            const existingUser = demoStorage.getUserByEmail(email);
            if (existingUser) {
                throw new Error('User already exists with this email');
            }

            // Create new user
            const uid = `demo-${btoa(email).slice(0, 8)}`;
            const newUser = {
                uid,
                email,
                displayName: displayName || email.split('@')[0],
                passwordHash: demoStorage.hashPassword(password)
            };

            demoStorage.saveUser(newUser);

            const mockUser = {
                uid: newUser.uid,
                email: newUser.email,
                displayName: newUser.displayName
            } as unknown as User;

            setUser(mockUser);
            localStorage.setItem('auditly_demo_session', JSON.stringify(mockUser));
            console.log('Demo signup successful for:', email);
            return;
        }
        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 = 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 = 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;
    };

    const signInWithOTP = async (token: string, userData: any) => {
        const mockUser = {
            uid: userData.uid,
            email: userData.email,
            displayName: userData.displayName,
            emailVerified: true
        } as unknown as User;

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

    return (
        <AuthContext.Provider value={{
            user,
            loading,
            signInWithGoogle,
            signOutUser,
            signInWithEmail,
            signUpWithEmail,
            sendOTP,
            verifyOTP,
            signInWithOTP
        }}>
            {children}
        </AuthContext.Provider>
    );
};

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