'use client';

import { createContext, useState, useContext, useEffect } from 'react';
import { base44, reinitializeClient } from '@/api/base44Client';
import { withRateLimit } from '@/lib/rateLimiter';
import { cleanupOnLogout } from '@/lib/cleanupOnLogout';

// Track last known token to detect OAuth redirects
let lastKnownToken = null;

const AuthContext = createContext(null);

export const AuthProvider = ({ children }) => {
  const [user, setUser] = useState(null);
  const [isAuthenticated, setIsAuthenticated] = useState(false);
  // Synchronously detect token AND logout state so public pages NEVER see a loading state
  const hasTokenSync = typeof window !== 'undefined' && !!window.localStorage.getItem('base44_access_token');
  const hasLogoutMarkerSync = typeof window !== 'undefined' && 
    (!!(typeof window.localStorage !== 'undefined' && window.localStorage.getItem('zipgy_logout_timestamp')) ||
     !!(typeof window.sessionStorage !== 'undefined' && window.sessionStorage.getItem('zipgy_logout_timestamp')));
  // Only start loading if token exists AND no logout marker (prevents loader on public pages after logout)
  const [isLoadingAuth, setIsLoadingAuth] = useState(hasTokenSync && !hasLogoutMarkerSync);
  const [isLoadingPublicSettings, setIsLoadingPublicSettings] = useState(false);
  const [authError, setAuthError] = useState(null);
  const [appPublicSettings, setAppPublicSettings] = useState(null);
  const [needsProfileCompletion, setNeedsProfileCompletion] = useState(false);

  useEffect(() => {
    let debounceTimer = null;
    const debouncedCheckAppState = () => {
      clearTimeout(debounceTimer);
      debounceTimer = setTimeout(() => checkAppState(), 300);
    };

    // Defer auth check to idle (non-blocking)
    if ('requestIdleCallback' in window) {
      requestIdleCallback(() => checkAppState(), { timeout: 100 });
    } else {
      checkAppState();
    }

    // Multi-tab sync — re-validate auth when token changes in another tab
    const handleTokenChange = () => {
      console.log('[Auth] Token changed in another tab, re-validating');
      debouncedCheckAppState();
    };
    window.addEventListener('base44:token_changed', handleTokenChange);
    return () => {
      window.removeEventListener('base44:token_changed', handleTokenChange);
      clearTimeout(debounceTimer);
    };
  }, []);

  const checkAppState = async () => {
    try {
      await checkUserAuth();
    } catch (error) {
      console.error('Unexpected error:', error);
      setIsLoadingAuth(false);
      setIsLoadingPublicSettings(false);
    }
  };

  const CACHED_USER_KEY = 'zipgy_cached_user';
  const BUSINESS_TRACKING_KEY = 'zipgy_business_tracking';

  const getCachedUser = () => {
    try {
      const raw = window.localStorage.getItem(CACHED_USER_KEY);
      if (!raw) return null;
      const { user, ts } = JSON.parse(raw);
      if (Date.now() - ts < 24 * 60 * 60 * 1000) return user;
    } catch (_) {}
    return null;
  };

  const setCachedUser = (user) => {
    try {
      window.localStorage.setItem(CACHED_USER_KEY, JSON.stringify({ user, ts: Date.now() }));
    } catch (_) {}
  };

  const clearCachedUser = () => {
    try { window.localStorage.removeItem(CACHED_USER_KEY); } catch (_) {}
  };

  const getBusinessTracking = () => {
    try {
      const raw = window.localStorage.getItem(BUSINESS_TRACKING_KEY);
      if (!raw) return null;
      const { business_type, business_id, timestamp, email, session_id } = JSON.parse(raw);
      if (Date.now() - timestamp < 7 * 24 * 60 * 60 * 1000) {
        return { business_type, business_id, email, session_id };
      }
    } catch (_) {}
    return null;
  };

  const setBusinessTracking = (business_type, business_id, email) => {
    try {
      const session_id = `sess_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
      window.localStorage.setItem(BUSINESS_TRACKING_KEY, JSON.stringify({
        business_type,
        business_id,
        email,
        session_id,
        timestamp: Date.now()
      }));
    } catch (_) {}
  };

  const clearBusinessTracking = () => {
    try { window.localStorage.removeItem(BUSINESS_TRACKING_KEY); } catch (_) {}
  };

  const checkUserAuth = async () => {
    try {
      // Batch localStorage reads (single pass)
      const hasToken = window.localStorage.getItem('base44_access_token');
      const logoutTimestamp = window.localStorage.getItem('zipgy_logout_timestamp') || window.sessionStorage.getItem('zipgy_logout_timestamp');
      
      // Check if user just logged out
      const urlParams = new URLSearchParams(window.location.search);
      const justLoggedOut = urlParams.get('logged_out') === '1';
      
      if (justLoggedOut || logoutTimestamp) {
        console.log('[Auth] User just logged out');
        if (logoutTimestamp) {
          try {
            window.localStorage.removeItem('zipgy_logout_timestamp');
            window.sessionStorage.removeItem('zipgy_logout_timestamp');
          } catch (_) {}
        }
        setIsAuthenticated(false);
        setUser(null);
        clearCachedUser();
        clearBusinessTracking();
        setIsLoadingAuth(false);
        setIsLoadingPublicSettings(false);
        setAuthError(null);
        setNeedsProfileCompletion(false);
        return;
      }
      
      // No token = logged out, show public site (instant, no network)
      if (!hasToken) {
        console.log('[Auth] No token - showing public site');
        setIsAuthenticated(false);
        setUser(null);
        clearCachedUser();
        clearBusinessTracking();
        setIsLoadingAuth(false);
        setIsLoadingPublicSettings(false);
        setAuthError(null);
        setNeedsProfileCompletion(false);
        return;
      }
      
      // Token exists - reinitialize if changed
      if (hasToken && hasToken !== lastKnownToken) {
        console.log('[Auth] Token changed, reinitializing');
        lastKnownToken = hasToken;
        reinitializeClient();
      }

      // OPTIMIZATION: Use cached user first for instant UI, then refresh in background
      const cachedUser = getCachedUser();
      if (cachedUser) {
        // CRITICAL: Flatten nested business data in cache if present
        let processedCachedUser = cachedUser;
        const userData = cachedUser.data || {};
        const nestedData = userData.data || {};
        
        if (nestedData.business_type || nestedData.business_id) {
          const flattenedData = {
            ...userData,
            business_type: nestedData.business_type || userData.business_type,
            business_id: nestedData.business_id || userData.business_id,
          };
          processedCachedUser = {
            ...cachedUser,
            data: flattenedData,
            business_type: flattenedData.business_type,
            business_id: flattenedData.business_id,
          };
          setCachedUser(processedCachedUser);
        }
        
        setUser(processedCachedUser);
        setIsAuthenticated(true);
        setIsLoadingAuth(false);
        setIsLoadingPublicSettings(false);
        setAuthError(null);
        
        // Validate silently in background using native SDK (no rate-limit cost)
        (async () => {
          try {
            const freshUser = await base44.auth.me();
            if (freshUser) {
              // Also flatten fresh user data
              const freshUserData = freshUser.data || {};
              const freshNestedData = freshUserData.data || {};
              
              let processedFreshUser = freshUser;
              if (freshNestedData.business_type || freshNestedData.business_id) {
                const freshFlattened = {
                  ...freshUserData,
                  business_type: freshNestedData.business_type || freshUserData.business_type,
                  business_id: freshNestedData.business_id || freshUserData.business_id,
                };
                processedFreshUser = {
                  ...freshUser,
                  data: freshFlattened,
                  business_type: freshFlattened.business_type,
                  business_id: freshFlattened.business_id,
                };
              }
              
              setUser(processedFreshUser);
              setCachedUser(processedFreshUser);
              const isRegularUser = !processedFreshUser.business_type && processedFreshUser.role === 'user';
              const isProfileComplete = !!processedFreshUser.profile_completed_at;
              setNeedsProfileCompletion(isRegularUser && !isProfileComplete);
            } else {
              // Token invalid - clear and redirect
              clearCachedUser();
              window.localStorage.removeItem('base44_access_token');
              setIsAuthenticated(false);
              setUser(null);
              setNeedsProfileCompletion(false);
              setAuthError(null);
              window.location.href = '/?logged_out=1';
            }
          } catch (validationError) {
            console.error('[Auth] Background validation error:', validationError);
            // Distinguish a DELETED/INVALID account from a transient network error.
            // Deleted accounts throw auth errors (401/403/not registered) — those must
            // be force-logged-out to /welcome. Network errors keep the cached user.
            const msg = (validationError?.message || '').toLowerCase();
            const status = validationError?.status || validationError?.response?.status;
            const isAuthFailure =
              status === 401 || status === 403 || status === 404 ||
              msg.includes('not registered') || msg.includes('unauthorized') ||
              msg.includes('forbidden') || msg.includes('not found') ||
              msg.includes('does not exist') || msg.includes('user not found');
            if (isAuthFailure) {
              clearCachedUser();
              clearBusinessTracking();
              try {
                window.localStorage.removeItem('base44_access_token');
                window.sessionStorage.removeItem('base44_access_token');
              } catch (_) {}
              setIsAuthenticated(false);
              setUser(null);
              setNeedsProfileCompletion(false);
              setAuthError(null);
              window.location.href = '/welcome?logged_out=1';
            }
            // else: transient network error — keep cached user, don't log them out
          }
        })();
        
        return;
      }

      // No cached user - validate using native SDK (no rate-limit cost)
      try {
        const freshUser = await base44.auth.me();
        if (freshUser) {
          // CRITICAL: Flatten nested business data if present (fixes double-nesting bug)
          let processedUser = freshUser;
          const userData = freshUser.data || {};
          const nestedData = userData.data || {};
          
          // Check if business_type/business_id are nested too deep
          if (nestedData.business_type || nestedData.business_id) {
            const flattenedData = {
              ...userData,
              business_type: nestedData.business_type || userData.business_type,
              business_id: nestedData.business_id || userData.business_id,
            };
            // Remove nested data if it exists
            if (nestedData.business_type) delete nestedData.business_type;
            if (nestedData.business_id) delete nestedData.business_id;
            
            processedUser = {
              ...freshUser,
              data: flattenedData,
              business_type: flattenedData.business_type,
              business_id: flattenedData.business_id,
            };
            
            // Silently fix the user record in background
            base44.auth.updateMe({
              business_type: flattenedData.business_type,
              business_id: flattenedData.business_id,
            }).catch(() => {});
          }
          
          setUser(processedUser);
          setIsAuthenticated(true);
          setCachedUser(processedUser);
          const isRegularUser = !processedUser.business_type && processedUser.role === 'user';
          const isProfileComplete = !!processedUser.profile_completed_at;
          setNeedsProfileCompletion(isRegularUser && !isProfileComplete);
        } else {
          clearCachedUser();
          window.localStorage.removeItem('base44_access_token');
          setIsAuthenticated(false);
          setUser(null);
          setNeedsProfileCompletion(false);
        }
      } catch (validationError) {
        console.error('[Auth] Validation error:', validationError);
        setNeedsProfileCompletion(false);
        // Deleted/invalid account → force clean logout to /welcome
        const msg = (validationError?.message || '').toLowerCase();
        const status = validationError?.status || validationError?.response?.status;
        const isAuthFailure =
          status === 401 || status === 403 || status === 404 ||
          msg.includes('not registered') || msg.includes('unauthorized') ||
          msg.includes('forbidden') || msg.includes('not found') ||
          msg.includes('does not exist') || msg.includes('user not found');
        if (isAuthFailure) {
          clearCachedUser();
          clearBusinessTracking();
          try {
            window.localStorage.removeItem('base44_access_token');
            window.sessionStorage.removeItem('base44_access_token');
          } catch (_) {}
          setIsAuthenticated(false);
          setUser(null);
          window.location.href = '/welcome?logged_out=1';
          return;
        }
      } finally {
        setIsLoadingAuth(false);
        setIsLoadingPublicSettings(false);
        setAuthError(null);
      }
    } catch (error) {
      console.error('[Auth] Critical error:', error);
      setIsAuthenticated(false);
      setUser(null);
      setAuthError(null);
      setIsLoadingAuth(false);
      setIsLoadingPublicSettings(false);
      try {
        clearCachedUser();
        window.localStorage.removeItem('base44_access_token');
      } catch (_) {}
    }
  };

  const logout = () => {
    console.log('[Logout] Starting logout');
    
    setUser(null);
    setIsAuthenticated(false);
    setIsLoadingAuth(false);
    setNeedsProfileCompletion(false);
    
    try {
      // Run comprehensive cleanup of all location/address/GPS data
      cleanupOnLogout();
      
      const logoutTimestamp = Date.now();
      window.localStorage.setItem('zipgy_logout_timestamp', logoutTimestamp.toString());
      window.sessionStorage.setItem('zipgy_logout_timestamp', logoutTimestamp.toString());
      
      window.localStorage.removeItem('base44_access_token');
      window.sessionStorage.removeItem('base44_access_token');
      
      const keysToRemove = [
        'zipgy_cached_user',
        'zipgy_business_tracking',
        'base44_oauth_redirect',
        'intended_signup_path',
        'base44_oauth_redirect_path',
        'base44_state',
        'base44_code_verifier'
      ];
      
      keysToRemove.forEach(key => {
        try {
          window.localStorage.removeItem(key);
          window.sessionStorage.removeItem(key);
        } catch (_) {}
      });
      
      if (user?.email) {
        try {
          window.localStorage.removeItem('user_profile_ensured_' + user.email);
        } catch (_) {}
      }
      
      window.sessionStorage.clear();
      
      const essentialKeys = ['zipgy_low_bandwidth_mode', 'zipgy_language_preference'];
      const allKeys = Object.keys(localStorage);
      allKeys.forEach(key => {
        if (!essentialKeys.includes(key)) {
          try { window.localStorage.removeItem(key); } catch (_) {}
        }
      });
    } catch (clearError) {
      console.error('[Logout] Error clearing data:', clearError);
    }
    
    window.location.href = '/?logged_out=1&v=' + Date.now();
  };

  const navigateToLogin = (returnUrl) => {
    const nextUrl = returnUrl || window.location.pathname;
    // Use custom signin page instead of BASE44 auth redirect
    window.location.href = `/signin?next=${encodeURIComponent(nextUrl)}`;
  };

  const refreshUser = async () => {
    window.sessionStorage.removeItem('user_profile_ensured_' + (user?.email || ''));
    await checkUserAuth();
  };

  return (
    <AuthContext.Provider value={{
      user,
      isAuthenticated,
      isLoadingAuth,
      isLoadingPublicSettings,
      authError,
      appPublicSettings,
      needsProfileCompletion,
      setNeedsProfileCompletion,
      logout,
      navigateToLogin,
      checkAppState,
      refreshUser,
      getBusinessTracking,
      setBusinessTracking,
      clearBusinessTracking,
    }}>
      {children}
    </AuthContext.Provider>
  );
};

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