import React, { createContext, useContext, useEffect, useMemo, useState, useRef } from 'react';
import { InteractionManager } from 'react-native';
import accountService, { AuthUser } from '../services/AccountService';
import supabase from '../services/supabaseClient';
import syncService from '../services/SyncService';

type AccountContextValue = {
  user: AuthUser | null;
  loading: boolean;
  signIn: (email: string, password: string) => Promise<string | null>;
  signUp: (email: string, password: string) => Promise<string | null>;
  signOut: () => Promise<void>;
  refreshCurrentUser: () => Promise<void>;
  updateProfile: (partial: { avatarUrl?: string; displayName?: string }) => Promise<string | null>;
};

const AccountContext = createContext<AccountContextValue | undefined>(undefined);

export const AccountProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const [user, setUser] = useState<AuthUser | null>(null);
  const [loading, setLoading] = useState(true);
  const loadingTimeoutRef = useRef<NodeJS.Timeout | null>(null);

  useEffect(() => {
    // Initial session (load full profile)
    // Defer heavy work until after initial interactions to reduce launch CPU spike
    const task = InteractionManager.runAfterInteractions(() => {
      (async () => {
        const u = await accountService.getCurrentUser();
        setUser(u);
        setLoading(false);
        // Stage sync operations to avoid blocking the JS thread
        syncService.init();
        if (u) {
          try {
            await syncService.migrateLocalScopeToUser();
            // Longer yield to event loop to reduce CPU pressure
            await new Promise(resolve => setTimeout(resolve, 100));
            await syncService.subscribeRealtime();
            await new Promise(resolve => setTimeout(resolve, 100));
            // Pull first to hydrate local state, then push to avoid wiping server with empty local
            await syncService.fullPull();
            await new Promise(resolve => setTimeout(resolve, 100));
            await syncService.fullPush();
          } catch {}
        }
      })();
    });

    // Auth state listener
    const { data: subscription } = supabase.auth.onAuthStateChange(async (event, session) => {
      // Only set loading for actual auth changes, not initial session
      if (event !== 'INITIAL_SESSION') {
        setLoading(true);
      }
      try {
        const fullUser = session?.user ? await accountService.getCurrentUser() : null;
        setUser(fullUser);
        // Immediately clear loading so UI can transition to MainTabs/Auth
        setLoading(false);
        if (fullUser) {
          // Run sync in background without blocking UI
          setTimeout(async () => {
            try {
              await syncService.migrateLocalScopeToUser();
              await new Promise(r => setTimeout(r, 0));
              await syncService.subscribeRealtime();
              await new Promise(r => setTimeout(r, 0));
              await syncService.fullPull();
              await new Promise(r => setTimeout(r, 0));
              await syncService.fullPush();
            } catch (error) {
              console.warn('[AccountContext] Background sync failed:', error);
            }
          }, 0);
        } else {
          syncService.unsubscribeRealtime();
        }
      } catch (e) {
        setLoading(false);
      }
    });

    return () => {
      subscription.subscription.unsubscribe();
      task.cancel();
      if (loadingTimeoutRef.current) {
        clearTimeout(loadingTimeoutRef.current);
        loadingTimeoutRef.current = null;
      }
    };
  }, []);

  const value = useMemo<AccountContextValue>(() => ({
    user,
    loading,
    signIn: async (email: string, password: string) => {
      const { error } = await accountService.signInWithEmail(email, password);
      return error || null;
    },
    signUp: async (email: string, password: string) => {
      const { error } = await accountService.signUpWithEmail(email, password);
      return error || null;
    },
    signOut: async () => {
      await accountService.signOut();
      setUser(null);
    },
    refreshCurrentUser: async () => {
      // Don't set loading if already loading to avoid conflicts
      if (loading) {
        if (__DEV__) console.log('[AccountContext] Already loading, skipping refresh');
        return;
      }

      if (__DEV__) console.log('[AccountContext] Starting refreshCurrentUser');
      setLoading(true);

      // Set a timeout to prevent loading from getting stuck
      loadingTimeoutRef.current = setTimeout(() => {
        console.warn('[AccountContext] Account loading timeout, forcing loading to false');
        setLoading(false);
      }, 5000); // Reduced to 5 seconds for faster fallback

      try {
        const u = await accountService.getCurrentUser();
        if (__DEV__) console.log('[AccountContext] refreshCurrentUser completed:', u ? 'user found' : 'no user');
        setUser(u);
      } catch (error) {
        console.error('[AccountContext] Failed to refresh current user:', error);
        // Still set user to null on error to ensure we don't get stuck
        setUser(null);
      } finally {
        if (loadingTimeoutRef.current) {
          clearTimeout(loadingTimeoutRef.current);
          loadingTimeoutRef.current = null;
        }
        setLoading(false);
        if (__DEV__) console.log('[AccountContext] refreshCurrentUser finished');
      }
    },
    updateProfile: async (partial) => {
      const err = await accountService.updateProfile(partial);
      if (!err) {
        // Refresh user from server to pick updated fields
        const u = await accountService.getCurrentUser();
        setUser(u);
      }
      return err;
    }
  }), [user, loading]);

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

export const useAccount = (): AccountContextValue => {
  const ctx = useContext(AccountContext);
  if (!ctx) throw new Error('useAccount must be used within AccountProvider');
  return ctx;
};

export default AccountContext;

