import React, { createContext, useContext, useState, useEffect, useCallback } from 'react';
import { Session, User } from '@supabase/supabase-js';
import { supabase } from '../supabaseClient';
import { logger } from '../debugConfig';
import { CCUser, CCUserMetadata } from '../services/auth/authService';
import { UserPreferences } from '../services/auth/profileService';
import { storageService, StorageKeys } from '../services/auth/localStorageService';

export interface UserContextType {
  user: CCUser | null;
  loading: boolean;
  error: Error | null;
  profile: CCUser | null;
  preferences: UserPreferences;
  isMobile: boolean;
  isInitialized: boolean;
  updateProfile: (updates: Partial<CCUser>) => Promise<void>;
  updatePreferences: (updates: Partial<UserPreferences>) => Promise<void>;
  clearError: () => void;
}

export const UserContext = createContext<UserContextType>({
  user: null,
  loading: true,
  error: null,
  profile: null,
  preferences: {},
  isMobile: false,
  isInitialized: false,
  updateProfile: async () => {},
  updatePreferences: async () => {},
  clearError: () => {}
});

export const UserProvider = ({ children }: { children: React.ReactNode }) => {
  const [user] = useState<CCUser | null>(null);
  const [profile, setProfile] = useState<CCUser | null>(null);
  const [preferences, setPreferences] = useState<UserPreferences>({});
  const [loading, setLoading] = useState(true);
  const [isInitialized, setIsInitialized] = useState(false);
  const [error, setError] = useState<Error | null>(null);
  const [isMobile] = useState(window.innerWidth <= 768);
  const mountedRef = React.useRef(true);

  // Use the main Supabase client for all operations to ensure proper session persistence
  // This avoids the "Multiple GoTrueClient instances" warning and ensures session restoration works

  const resolveProfile = useCallback(async (supabaseUser?: User | null, session?: Session | null) => {
    // Prevent duplicate work when we already have the same user resolved
    if (mountedRef.current && isInitialized) {
      const resolvedUserId = profile?.id;
      const incomingUserId = supabaseUser?.id ?? session?.user?.id ?? null;

      if (!incomingUserId && !supabaseUser) {
        logger.debug('user-context', '⚠️ Profile already initialized for guest session, skipping resolution');
        return;
      }

      if (incomingUserId && resolvedUserId && resolvedUserId === incomingUserId) {
        logger.debug('user-context', '⚠️ Profile already initialized for current user, skipping resolution');
        return;
      }
    }
    
    let userInfo: User | null = null; // Declare at function scope
    try {
      logger.debug('user-context', '🔄 Resolving user profile', {
        hasSupabaseUser: !!supabaseUser,
        isInitialized
      });
      logger.debug('user-context', '🔧 Step 1: Starting profile resolution...');
      // Don't set loading to true immediately - let the UI show progress naturally
      let authSession = session;
      userInfo = supabaseUser ?? null;

      logger.debug('user-context', '🔧 Step 2: Getting auth session...');
      if (!authSession) {
        const { data } = await supabase.auth.getSession();
        authSession = data.session;
        logger.debug('user-context', '🔧 Step 2a: Got session from supabase', {
          hasSession: !!authSession
        });
      }

      logger.debug('user-context', '🔧 Step 3: Getting user info...');
      if (!userInfo) {
        const { data } = await supabase.auth.getUser();
        userInfo = data.user;
        logger.debug('user-context', '🔧 Step 3a: Got user from supabase', {
          hasUser: !!userInfo
        });
      }

      if (!userInfo) {
        logger.debug('user-context', '⚠️ No user info available - clearing profile');
        if (!mountedRef.current) {
          return;
        }
        setProfile(null);
        setPreferences({});
        setError(null);
        setLoading(false);
        return;
      }

      logger.debug('user-context', '🔧 Step 4: User info available, proceeding...', {
        userId: userInfo.id,
        email: userInfo.email
      });

     let profileRow: Record<string, unknown> | null = null;

      // Fast-path: build profile from auth metadata immediately (no spinner on refresh).
      const fastMetadata = userInfo.user_metadata as CCUserMetadata;
      const fastProfile: CCUser = {
        id: userInfo.id,
        email: userInfo.email,
        user_type: fastMetadata?.user_type || '',
        username: fastMetadata?.username || userInfo.email?.split('@')[0] || 'user',
        display_name: String(fastMetadata?.display_name || ''),
        school_id: null,
        created_at: userInfo.created_at,
        updated_at: userInfo.updated_at
      };
      if (mountedRef.current && !isInitialized) {
        setProfile(fastProfile);
        setLoading(false);
        setIsInitialized(true);
        logger.debug('user-context', '⚡ Fast-path: profile initialized from auth metadata');
      }

      // Background: query Supabase profiles for authoritative data (user_db_name, school_db_name, display_name).
      // No setLoading toggles — spinner is already cleared above.
      const { data, error } = await supabase
        .from('profiles')
        .select('*')
        .eq('id', userInfo.id)
        .single();

      if (error && error.code !== 'PGRST116') {
        logger.warn('user-context', '⚠️ Profiles query failed, using fast-path profile', {
          error: error.message,
          code: error.code
        });
        profileRow = null;
      } else if (data) {
        profileRow = data;
        logger.debug('user-context', '✅ Supabase profile fetched', {
          userId: data.id,
          userDbName: data.user_db_name
        });
      } else {
        profileRow = null;
      }

      logger.debug('user-context', '🔧 Step 6: Processing profile data...', {
        userId: userInfo.id,
        hasProfileRow: !!profileRow,
        hasUserDb: !!profileRow?.user_db_name,
        hasSchoolDb: !!profileRow?.school_db_name
      });


      const metadata = userInfo.user_metadata as CCUserMetadata;
      const userProfile: CCUser = {
        id: userInfo.id,
        email: userInfo.email,
        user_type: metadata.user_type || '',
        username: metadata.username || '',
        display_name: String(metadata.display_name || ''),
        school_id: (profileRow?.school_id as string) ?? null,
        created_at: userInfo.created_at,
        updated_at: userInfo.updated_at
      };

      if (!mountedRef.current) {
        logger.debug('user-context', '❌ Component unmounted during profile creation');
        return;
      }

      logger.debug('user-context', '🔧 Setting profile and preferences...', {
        profileId: userProfile.id
      });

      setProfile(userProfile);
      setPreferences({
        theme: (profileRow?.theme && typeof profileRow.theme === 'string' && ['system', 'light', 'dark'].includes(profileRow.theme)) ? profileRow.theme as 'system' | 'light' | 'dark' : 'system',
        notifications: Boolean(profileRow?.notifications_enabled)
      });

      logger.debug('user-context', '✅ User profile loaded', {
        userId: userProfile.id,
        userType: userProfile.user_type,
        username: userProfile.username
      });
      setError(null);
    } catch (error) {
      logger.error('user-context', '❌ Failed to load user profile', { error });
      if (!mountedRef.current) {
        return;
      }
      logger.error('user-context', '❌ Resolving user profile failed', {
        message: error instanceof Error ? error.message : String(error)
      });
      // Create fallback profile even when errors occur
      logger.debug('user-context', '🔧 Creating fallback profile due to error...', {
        userId: userInfo?.id,
        email: userInfo?.email
      });
      
      if (userInfo) {
        const metadata = userInfo.user_metadata as CCUserMetadata;
        const fallbackProfile: CCUser = {
          id: userInfo.id,
          email: userInfo.email,
          user_type: metadata?.user_type || 'email_teacher',
          username: metadata?.username || userInfo.email?.split('@')[0] || 'user',
          display_name: metadata?.display_name || userInfo.email?.split('@')[0] || 'User',
          school_id: null,
          created_at: userInfo.created_at,
          updated_at: userInfo.updated_at
        };
        setProfile(fallbackProfile);
        logger.debug('user-context', '✅ Fallback profile created', {
          userId: fallbackProfile.id,
          userType: fallbackProfile.user_type
        });
      } else {
        setProfile(null);
      }
      
      setPreferences({});
      setError(error instanceof Error ? error : new Error('Failed to load user profile'));
      setLoading(false); // Ensure loading is cleared on error
    } finally {
      logger.debug('user-context', '🔧 Finalizing user context initialization...', {
        isMounted: mountedRef.current
      });
      
      if (mountedRef.current) {
        // Loading state is already managed above, just log completion
        logger.debug('user-context', '✅ User context initialization complete');
      }
      
      logger.debug('user-context', '🔧 Step 10: Setting isInitialized to true');
      setIsInitialized(true);
      logger.debug('user-context', '✅ User context initialized flag set - initialization complete!', {
        isInitialized: true,
        profileId: profile?.id,
        userType: profile?.user_type
      });
    }
  }, [profile?.id, profile?.user_type, isInitialized]);

  useEffect(() => {
    mountedRef.current = true;

    const { data: { subscription } } = supabase.auth.onAuthStateChange(async (event, session) => {
      if (!mountedRef.current) {
        return;
      }

      logger.debug('user-context', '🔄 Auth state change', {
        event,
        hasSession: !!session,
        hasUser: !!session?.user
      });

      switch (event) {
        case 'SIGNED_OUT':
          setLoading(false);
          setProfile(null);
          setPreferences({});
          setIsInitialized(true);
          setError(null);
          break;
        case 'SIGNED_IN':
        case 'TOKEN_REFRESHED':
        case 'INITIAL_SESSION':
          await resolveProfile(session?.user ?? null, session ?? null);
          break;
        default:
          break;
      }
    });

    return () => {
      mountedRef.current = false;
      subscription.unsubscribe();
    };
  }, [resolveProfile]);

  const updateProfile = async (updates: Partial<CCUser>) => {
    if (!user?.id || !profile) {
      return;
    }

    setLoading(true);
    try {
      const { error } = await supabase
        .from('profiles')
        .update({
          ...updates,
          updated_at: new Date().toISOString()
        })
        .eq('id', user.id);

      if (error) {
        throw error;
      }

      setProfile(prev => prev ? { ...prev, ...updates } : null);
      logger.info('user-context', '✅ Profile updated successfully');
    } catch (error) {
      logger.error('user-context', '❌ Failed to update profile', { error });
      setError(error instanceof Error ? error : new Error('Failed to update profile'));
      throw error;
    } finally {
      setLoading(false);
    }
  };

  const updatePreferences = async (updates: Partial<UserPreferences>) => {
    if (!user?.id) {
      return;
    }

    setLoading(true);
    try {
      const newPreferences = { ...preferences, ...updates };
      setPreferences(newPreferences);

      const { error } = await supabase
        .from('profiles')
        .update({
          preferences: newPreferences,
          updated_at: new Date().toISOString()
        })
        .eq('id', user.id);

      if (error) {
        throw error;
      }

      logger.info('user-context', '✅ Preferences updated successfully');
    } catch (error) {
      logger.error('user-context', '❌ Failed to update preferences', { error });
      setError(error instanceof Error ? error : new Error('Failed to update preferences'));
      throw error;
    } finally {
      setLoading(false);
    }
  };

  // Store profile in localStorage whenever it changes
  useEffect(() => {
    if (profile) {
      storageService.set(StorageKeys.USER, profile);
      logger.debug('user-context', '💾 Stored user profile in localStorage', {
        userId: profile.id,
        userType: profile.user_type
      });
    } else {
      storageService.remove(StorageKeys.USER);
      logger.debug('user-context', '🗑️ Removed user profile from localStorage');
    }
  }, [profile]);

  return (
    <UserContext.Provider
      value={{
        user: profile,
        loading,
        error,
        profile,
        preferences,
        isMobile,
        isInitialized,
        updateProfile,
        updatePreferences,
        clearError: () => setError(null)
      }}
    >
      {children}
    </UserContext.Provider>
  );
}

export const useUser = () => useContext(UserContext);
