/**
 * Authentication Context
 * Provides unified authentication interface that works with both:
 * - Backend token exchange (localhost/development)
 * - Auth0 Provider (production)
 */

import { createContext, useContext, useEffect, useState, ReactNode, useRef } from 'react';
import { Auth0Provider, useAuth0 as useAuth0Hook } from '@auth0/auth0-react';
import { TokenManager, isTokenExpired } from '../utils/tokenManager';
import { exchangeCodeForTokens, refreshAccessToken, getCurrentUser, logout as logoutApi, passwordLogin, oktaLogout } from '../services/authApi';
import { tanflowLogout } from '../services/tanflowAuth';
import { getSocket, joinUserRoom } from '../utils/socket';
import { toast } from 'sonner';

interface User {
  userId?: string;
  employeeId?: string;
  email?: string;
  firstName?: string;
  lastName?: string;
  displayName?: string;
  department?: string;
  designation?: string;
  role?: 'USER' | 'MANAGEMENT' | 'ADMIN';
  sub?: string;
  name?: string;
  picture?: string;
  nickname?: string;
}

interface AuthContextType {
  isAuthenticated: boolean;
  isLoading: boolean;
  user: User | null;
  error: Error | null;
  login: () => Promise<void>;
  /** Local dealer login (username TESTREFLOW when ENABLE_LOCAL_DEALER_LOGIN is set) */
  loginWithPassword?: (username: string, password: string) => Promise<void>;
  logout: () => Promise<void>;
  getAccessTokenSilently: () => Promise<string | null>;
  refreshTokenSilently: () => Promise<void>;
}

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

interface AuthProviderProps {
  children: ReactNode;
}

/**
 * Check if running on localhost
 * Note: Function reserved for future use
 * @internal - Reserved for future use
 */
export const _isLocalhost = (): boolean => {
  return (
    window.location.hostname === 'localhost' ||
    window.location.hostname === '127.0.0.1' ||
    window.location.hostname === ''
  );
};

/**
 * Backend-based Auth Provider (for localhost)
 */
function BackendAuthProvider({ children }: { children: ReactNode }) {
  const [isAuthenticated, setIsAuthenticated] = useState(false);
  const [isLoading, setIsLoading] = useState(true);
  const [user, setUser] = useState<User | null>(null);
  const [error, setError] = useState<Error | null>(null);
  const [isLoggingOut, setIsLoggingOut] = useState(false);

  // Check authentication status on mount
  // Only check if we're not in the middle of a logout process
  useEffect(() => {
    // PRIORITY 1: Check for logout flags in sessionStorage (survives page reload during logout)
    const logoutFlag = sessionStorage.getItem('__logout_in_progress__');
    const forceLogout = sessionStorage.getItem('__force_logout__');

    if (logoutFlag === 'true' || forceLogout === 'true') {
      // Remove flags
      sessionStorage.removeItem('__logout_in_progress__');
      sessionStorage.removeItem('__force_logout__');

      // Clear all tokens one more time (aggressive)
      TokenManager.clearAll();

      // Also manually clear everything
      try {
        localStorage.clear();
        sessionStorage.clear();
      } catch (e) {
        console.error('Error clearing storage:', e);
      }

      // Set unauthenticated state
      setIsAuthenticated(false);
      setUser(null);
      setIsLoading(false);
      setError(null);

      return;
    }

    // PRIORITY 2: Check if URL has logout parameter (from redirect)
    // Do NOT treat as logout when we have an OAuth code - we're in the middle of login callback
    const urlParams = new URLSearchParams(window.location.search);
    const hasOAuthCode = urlParams.has('code');
    const storedLogoutType = sessionStorage.getItem('__logout_type__');
    const hasLogoutParam = urlParams.has('logout') || urlParams.has('okta_logged_out') || urlParams.has('tanflow_logged_out') || storedLogoutType;
    if (hasLogoutParam && !hasOAuthCode) {
      console.log('🚪 Logout parameter detected in URL, clearing all tokens and backend session');
      
      // Perform final backend logout cleanup when returning from IdP
      logoutApi().catch(err => console.warn('🚪 Final backend logout cleanup failed:', err));
      
      TokenManager.clearAll();
      sessionStorage.removeItem('__logout_type__');
      sessionStorage.removeItem('auth_provider');
      sessionStorage.removeItem('tanflow_auth_state');
      sessionStorage.removeItem('__logout_in_progress__');
      sessionStorage.removeItem('__force_logout__');
      sessionStorage.removeItem('tanflow_logged_out');
      localStorage.clear();
      setIsAuthenticated(false);
      setUser(null);
      setIsLoading(false);
      // Persist "force re-auth" so that when user clicks "RE Employee Login" we add prompt=login
      // (URL is cleaned below, so we'd otherwise lose the fact we just logged out)
      try {
        sessionStorage.setItem('__force_reauth_after_logout__', 'true');
      } catch (e) {
        console.warn('Could not set force reauth flag:', e);
      }
      // Use a fully clean URL so next load (e.g. after Okta login) does not see logout params and clear again
      window.history.replaceState({}, document.title, '/');
      return;
    }

    // PRIORITY 3: Skip auth check if on callback page - let callback handler process first
    // This is essential for production mode where we need to exchange code for tokens
    // before we can verify session with server
    if (window.location.pathname === '/login/callback' || window.location.pathname === '/login/tanflow/callback') {
      // Don't check auth status here - let the callback handler do its job
      // The callback handler will set isAuthenticated after successful token exchange
      return;
    }

    // PRIORITY 4: Check authentication status
    const token = TokenManager.getAccessToken();
    const refreshToken = TokenManager.getRefreshToken();
    const userData = TokenManager.getUserData();
    const hasAuthData = token || refreshToken || userData;

    // Check if we're in production mode (tokens in httpOnly cookies, not accessible to JS)
    const isProductionMode = import.meta.env.PROD || import.meta.env.MODE === 'production';

    // In production: Always verify with server (cookies are sent automatically)
    // In development: Check local auth data first
    if (isProductionMode) {
      // Prod: Verify session with server via httpOnly cookie
      if (!isLoggingOut) {
        checkAuthStatus();
      } else {
        setIsLoading(false);
      }
    } else {
      // Dev: If no auth data exists, user is not authenticated
      if (!hasAuthData) {
        setIsAuthenticated(false);
        setUser(null);
        setIsLoading(false);
        return;
      }

      // PRIORITY 5: Only check auth status if we have some auth data AND we're not logging out
      if (!isLoggingOut) {
        checkAuthStatus();
      } else {
        setIsLoading(false);
      }
    }
  }, [isLoggingOut]);

  // Silent refresh interval
  useEffect(() => {
    if (!isAuthenticated) return;

    const isProductionMode = import.meta.env.PROD || import.meta.env.MODE === 'production';

    const checkAndRefresh = async () => {
      if (isProductionMode) {
        // In production, proactively refresh the session every 10 minutes
        // The httpOnly cookie will be sent automatically
        try {
          await refreshTokenSilently();
        } catch (error) {
          console.error('Silent refresh failed:', error);
        }
      } else {
        // In development, check token expiration
        const token = TokenManager.getAccessToken();
        if (token && isTokenExpired(token, 5)) {
          // Token expires in less than 5 minutes, refresh it
          try {
            await refreshTokenSilently();
          } catch (error) {
            console.error('Silent refresh failed:', error);
          }
        }
      }
    };

    // Check every 10 minutes in production, 5 minutes in development
    const intervalMs = isProductionMode ? 10 * 60 * 1000 : 5 * 60 * 1000;
    const interval = setInterval(checkAndRefresh, intervalMs);
    return () => clearInterval(interval);
  }, [isAuthenticated]);

  // WebSocket for Reactive Logout (Session Supersession)
  useEffect(() => {
    if (!isAuthenticated || !user?.userId) return;

    const socket = getSocket();

    // Join the user's personal room for real-time notifications
    joinUserRoom(socket, user.userId);

    // Listen for session supersession (concurrent login from another device)
    const handleSessionSuperseded = (data: any) => {
      console.log('📡 [Socket] Session superseded event received:', data);
      
      // Stop background refreshes immediately
      TokenManager.setAuthError('SESSION_SUPERSEDED');
      
      // Notify the user
      toast.error("Session Expired", {
        description: "You have been logged out because another session was started on a different device.",
        duration: 4000,
        id: 'session-superseded-socket'
      });

      // Trigger automatic logout after a short delay (1s) for readability
      setTimeout(() => {
        logout();
      }, 1000);
    };

    socket.on('SESSION_SUPERSEDED', handleSessionSuperseded);

    return () => {
      socket.off('SESSION_SUPERSEDED', handleSessionSuperseded);
    };
  }, [isAuthenticated, user?.userId]);

  // Handle callback from OAuth redirect
  // Use ref to prevent duplicate calls (React StrictMode runs effects twice in dev)
  const callbackProcessedRef = useRef(false);

  useEffect(() => {
    // Skip if already processed or not on callback page
    if (callbackProcessedRef.current || window.location.pathname !== '/login/callback') {
      return;
    }

    const handleCallback = async () => {
      const urlParams = new URLSearchParams(window.location.search);

      // Detect provider FIRST so we don't strip the URL before TanflowCallback can read code/state
      const authProvider = sessionStorage.getItem('auth_provider');
      if (authProvider === 'tanflow') {
        // Tanflow: do not touch URL or process here - TanflowCallback will read code/state and handle exchange
        return;
      }

      // Check if this is a logout redirect (from Tanflow/Okta post-logout redirect)
      // We check for URL params OR sessionStorage flags (needed for clean redirect URIs)
      const storedLogoutType = sessionStorage.getItem('__logout_type__');
      const isLogoutRedirect = (urlParams.has('logout') || urlParams.has('tanflow_logged_out') || urlParams.has('okta_logged_out') || storedLogoutType) && !urlParams.get('code');

      if (isLogoutRedirect) {
        // This is a logout redirect, not a login callback
        // Redirect to home page - the mount useEffect will handle logout cleanup
        console.log('🚪 Logout redirect detected in callback, redirecting to home');
        // Extract the logout flags from current URL
        const logoutFlags = new URLSearchParams();
        if (urlParams.has('tanflow_logged_out') || storedLogoutType === 'tanflow') logoutFlags.set('tanflow_logged_out', 'true');
        if (urlParams.has('okta_logged_out') || storedLogoutType === 'okta') logoutFlags.set('okta_logged_out', 'true');
        if (urlParams.has('logout')) logoutFlags.set('logout', urlParams.get('logout') || Date.now().toString());
        const redirectUrl = logoutFlags.toString() ? `/?${logoutFlags.toString()}` : '/?logout=' + Date.now();
        window.location.replace(redirectUrl);
        return;
      }

      // Mark as processed immediately to prevent duplicate calls (OKTA only)
      callbackProcessedRef.current = true;

      const code = urlParams.get('code');
      const errorParam = urlParams.get('error');

      // Clean URL immediately to prevent re-running on re-renders
      window.history.replaceState({}, document.title, '/login/callback');

      // Handle OKTA callback (default)
      if (errorParam) {
        setError(new Error(`Authentication error: ${errorParam}`));
        setIsLoading(false);
        // Clear provider flag
        sessionStorage.removeItem('auth_provider');
        return;
      }

      if (!code) {
        setIsLoading(false);
        // Clear provider flag
        sessionStorage.removeItem('auth_provider');
        return;
      }

      try {
        setIsLoading(true);
        setIsAuthenticated(false);
        setError(null);

        // IMPORTANT: redirectUri must match the one used in initial Okta authorization request
        // This is the frontend callback URL, NOT the backend URL
        // Backend will use this same URI when exchanging code with Okta
        const redirectUri = `${window.location.origin}/login/callback`;

        const result = await exchangeCodeForTokens(code, redirectUri);

        setUser(result.user);
        setIsAuthenticated(true);
        setError(null);

        // Clear provider flag after successful authentication
        sessionStorage.removeItem('auth_provider');

        // Clean URL after success
        window.history.replaceState({}, document.title, '/');
      } catch (err: any) {
        console.error('❌ Token exchange error in AuthContext:', err);
        setError(err);
        setIsAuthenticated(false);
        setUser(null);
        // Clear provider flag on error
        sessionStorage.removeItem('auth_provider');
        // Reset ref on error so user can retry if needed
        callbackProcessedRef.current = false;
      } finally {
        setIsLoading(false);
      }
    };

    handleCallback();
  }, []); // Empty deps - only run once on mount

  const checkAuthStatus = async () => {
    // Don't check auth status if we're in the middle of logging out
    if (isLoggingOut) {
      setIsLoading(false);
      return;
    }

    const isProductionMode = import.meta.env.PROD || import.meta.env.MODE === 'production';

    try {
      setIsLoading(true);

      // Prod MODE: Verify session via httpOnly cookie
      // The cookie is sent automatically with the request (withCredentials: true)
      if (isProductionMode) {
        const storedUser = TokenManager.getUserData();

        // Try to get current user from server - this validates the httpOnly cookie
        try {
          const userData = await getCurrentUser();
          setUser(userData);
          TokenManager.setUserData(userData);
          setIsAuthenticated(true);
        } catch (error: any) {
          // If 401, try to refresh the token (refresh token is also in httpOnly cookie)
          if (error?.response?.status === 401) {
            try {
              await refreshTokenSilently();
              // Retry getting user after refresh
              const userData = await getCurrentUser();
              setUser(userData);
              TokenManager.setUserData(userData);
              setIsAuthenticated(true);
            } catch {
              // Refresh failed - clear user data and show login
              TokenManager.clearAll();
              setIsAuthenticated(false);
              setUser(null);
            }
          } else if (error?.isConnectionError) {
            // Backend not reachable - use stored user data if available
            if (storedUser) {
              setUser(storedUser);
              setIsAuthenticated(true);
            } else {
              setIsAuthenticated(false);
              setUser(null);
            }
          } else {
            // Other error - clear and show login
            TokenManager.clearAll();
            setIsAuthenticated(false);
            setUser(null);
          }
        }
        return;
      }

      // Dev MODE: Check local token
      const token = TokenManager.getAccessToken();
      const storedUser = TokenManager.getUserData();

      // If no token at all, user is not authenticated
      if (!token) {
        setIsAuthenticated(false);
        setUser(null);
        setIsLoading(false);
        return;
      }

      // Check if token is expired
      if (isTokenExpired(token)) {
        // Token expired, try to refresh
        try {
          await refreshTokenSilently();
          // Refresh succeeded, check again
          const newToken = TokenManager.getAccessToken();
          if (newToken && !isTokenExpired(newToken)) {
            const refreshedUser = TokenManager.getUserData();
            if (refreshedUser) {
              setUser(refreshedUser);
              setIsAuthenticated(true);
            } else {
              // Fetch user data
              try {
                const userData = await getCurrentUser();
                setUser(userData);
                TokenManager.setUserData(userData);
                setIsAuthenticated(true);
              } catch {
                // Token might be invalid, clear everything
                TokenManager.clearAll();
                setIsAuthenticated(false);
                setUser(null);
              }
            }
          } else {
            // Refresh failed, user is logged out
            TokenManager.clearAll();
            setIsAuthenticated(false);
            setUser(null);
          }
        } catch {
          // Refresh failed, clear everything
          TokenManager.clearAll();
          setIsAuthenticated(false);
          setUser(null);
        }
      } else {
        // Token is valid
        if (storedUser) {
          setUser(storedUser);
          setIsAuthenticated(true);
        } else {
          // Fetch user data to ensure token is still valid
          try {
            const userData = await getCurrentUser();
            setUser(userData);
            TokenManager.setUserData(userData);
            setIsAuthenticated(true);
          } catch {
            // Token might be invalid, clear everything
            TokenManager.clearAll();
            setIsAuthenticated(false);
            setUser(null);
          }
        }
      }
    } catch (err: any) {
      console.error('Error checking auth status:', err);
      setError(err);
      TokenManager.clearAll();
      setIsAuthenticated(false);
      setUser(null);
    } finally {
      setIsLoading(false);
    }
  };

  const login = async () => {
    try {
      setError(null);
      // Redirect to Okta login
      const oktaDomain = import.meta.env.VITE_OKTA_DOMAIN || '{{IDP_DOMAIN}}';
      const clientId = import.meta.env.VITE_OKTA_CLIENT_ID || '0oa2jgzvrpdwx2iqd0h8';
      const redirectUri = `${window.location.origin}/login/callback`;
      const responseType = 'code';
      const scope = 'openid profile email';
      const state = Math.random().toString(36).substring(7);

      // Store provider type to identify OKTA callback
      sessionStorage.setItem('auth_provider', 'okta');

      // Check if we're coming from a logout - if so, add prompt=login to force re-authentication
      // (URL may have been cleaned to '/' on mount, so also check persisted flag)
      const urlParams = new URLSearchParams(window.location.search);
      const hasLogoutInUrl = urlParams.has('logout') || urlParams.has('okta_logged_out') || urlParams.has('tanflow_logged_out');
      const forceReauthFlag = sessionStorage.getItem('__force_reauth_after_logout__') === 'true';
      const isAfterLogout = hasLogoutInUrl || forceReauthFlag;

      let authUrl = `${oktaDomain}/oauth2/default/v1/authorize?` +
        `client_id=${clientId}&` +
        `redirect_uri=${encodeURIComponent(redirectUri)}&` +
        `response_type=${responseType}&` +
        `scope=${encodeURIComponent(scope)}&` +
        `state=${state}`;

      // Add prompt=login if coming from logout to force re-authentication
      // This ensures Okta requires login (password) even if an SSO session still exists
      if (isAfterLogout) {
        authUrl += `&prompt=login`;
        sessionStorage.removeItem('__force_reauth_after_logout__');
      }

      window.location.href = authUrl;
    } catch (err: any) {
      setError(err);
      throw err;
    }
  };

  const loginWithPassword = async (username: string, password: string) => {
    setError(null);
    setIsLoading(true);
    try {
      const result = await passwordLogin(username, password);
      setUser(result.user);
      setIsAuthenticated(true);
      window.history.replaceState({}, document.title, '/');
    } catch (err: any) {
      setError(err);
      setIsAuthenticated(false);
      setUser(null);
      throw err;
    } finally {
      setIsLoading(false);
    }
  };

  const logout = async () => {
    try {
      //: Get id_token from TokenManager before clearing anything
      // Needed for both Okta and Tanflow logout endpoints
      const idToken = TokenManager.getIdToken();

      // Detect which provider was used for login (check sessionStorage or user data)
      // If auth_provider is set, use it; otherwise check if we have Tanflow id_token pattern
      const authProvider = sessionStorage.getItem('auth_provider') ||
        (idToken && idToken.includes('tanflow') ? 'tanflow' : null) ||
        'okta'; // Default to OKTA if unknown

      // Set logout flag to prevent auto-authentication after redirect
      // This must be set BEFORE clearing storage so it survives
      sessionStorage.setItem('__logout_in_progress__', 'true');
      sessionStorage.setItem('__force_logout__', 'true');
      setIsLoggingOut(true);

      // Reset auth state FIRST to prevent any re-authentication
      setIsAuthenticated(false);
      setUser(null);
      setError(null);
      setIsLoading(true); // Set loading to prevent checkAuthStatus from running

      // NOTE: Backend logout API is now deferred to the AuthContext mount effect 
      // which handles the redirect return from Okta/Tanflow to ensure IdP-first logout.

      // Preserve logout flags, id_token, and auth_provider BEFORE clearing tokens
      const logoutInProgress = sessionStorage.getItem('__logout_in_progress__');
      const forceLogout = sessionStorage.getItem('__force_logout__');
      const storedAuthProvider = sessionStorage.getItem('auth_provider');

      // Clear all tokens EXCEPT id_token (we need it for provider logout)
      // Note: We'll clear id_token after provider logout
      // Clear tokens (but we'll restore id_token if needed)
      TokenManager.clearAll();

      // Restore logout flags and id_token immediately after clearAll
      if (logoutInProgress) sessionStorage.setItem('__logout_in_progress__', logoutInProgress);
      if (forceLogout) sessionStorage.setItem('__force_logout__', forceLogout);
      if (idToken) {
        TokenManager.setIdToken(idToken); // Restore id_token for provider logout
      }
      if (storedAuthProvider) {
        sessionStorage.setItem('auth_provider', storedAuthProvider); // Restore for logout
      }

      // Small delay to ensure sessionStorage is written before redirect
      await new Promise(resolve => setTimeout(resolve, 100));

      // Handle provider-specific logout
      if (authProvider === 'tanflow' && idToken) {
        console.log('🚪 Initiating Tanflow logout...');
        // Tanflow logout - redirect to Tanflow logout endpoint
        // This will clear Tanflow session and redirect back to our app
        try {
          tanflowLogout(idToken);
          // tanflowLogout will redirect, so we don't need to do anything else here
          return;
        } catch (tanflowLogoutError) {
          console.error('🚪 Tanflow logout error:', tanflowLogoutError);
          // Fall through to default logout flow
        }
      }

      // OKTA logout or fallback: Clear auth_provider and redirect to login page with flags
      console.log('🚪 Using OKTA logout flow or fallback');
      sessionStorage.removeItem('auth_provider');
      // Initiate full Okta logout (OIDC redirect)
      oktaLogout(idToken || undefined);
    } catch (error) {
      console.error('🚪 Logout error:', error);
      // Force redirect even on error - clear everything and redirect to login
      try {
        localStorage.clear();
        sessionStorage.clear();
        sessionStorage.setItem('__logout_in_progress__', 'true');
        const loginUrl = `${window.location.origin}/?okta_logged_out=true&logout=${Date.now()}`;
        window.location.replace(loginUrl);
      } catch {
        // Last resort - redirect to home
        window.location.replace('/?logout=' + Date.now());
      }
    }
  };

  const getAccessTokenSilently = async (): Promise<string | null> => {
    const isProductionMode = import.meta.env.PROD || import.meta.env.MODE === 'production';

    // In production mode, tokens are in httpOnly cookies
    // We can't access them directly, but API calls will include them automatically
    if (isProductionMode) {
      // If user is authenticated, return a placeholder indicating cookies are used
      // The actual token is in httpOnly cookie and sent automatically with requests
      if (isAuthenticated) {
        return 'cookie-based-auth'; // Placeholder - actual auth via cookies
      }

      // Try to refresh the session
      try {
        await refreshTokenSilently();
        return isAuthenticated ? 'cookie-based-auth' : null;
      } catch {
        return null;
      }
    }

    // Dev mode: tokens in localStorage
    const token = TokenManager.getAccessToken();
    if (token && !isTokenExpired(token)) {
      return token;
    }

    // Try to refresh
    try {
      await refreshTokenSilently();
      return TokenManager.getAccessToken();
    } catch {
      return null;
    }
  };

  const refreshTokenSilently = async (): Promise<void> => {
    const isProductionMode = import.meta.env.PROD || import.meta.env.MODE === 'production';

    try {
      const newToken = await refreshAccessToken();

      // In production, refresh might not return token (it's in httpOnly cookie)
      // but if the call succeeded, the session is valid
      if (isProductionMode) {
        // Session refreshed via cookies
        return;
      }

      if (newToken) {
        // Token refreshed successfully (development mode)
        return;
      }
      throw new Error('Failed to refresh token');
    } catch (err) {
      TokenManager.clearAll();
      setIsAuthenticated(false);
      setUser(null);
      throw err;
    }
  };

  const value: AuthContextType = {
    isAuthenticated,
    isLoading,
    user,
    error,
    login,
    loginWithPassword,
    logout,
    getAccessTokenSilently,
    refreshTokenSilently,
  };

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

/**
 * Auth0-based Auth Provider (for production)
 * Note: Reserved for future use when Auth0 integration is needed
 * @internal - Reserved for future use
 */
export function _Auth0AuthProvider({ children }: { children: ReactNode }) {
  return (
    <Auth0Provider
      domain="{{IDP_DOMAIN}}/oauth2/default/v1"
      clientId="0oa2j8slwj5S4bG5k0h8"
      authorizationParams={{
        redirect_uri: window.location.origin + '/login/callback',
      }}
      onRedirectCallback={(_appState) => {
        // Auth0 redirect callback handled
      }}
    >
      <Auth0ContextWrapper>{children}</Auth0ContextWrapper>
    </Auth0Provider>
  );
}


/**
 * Wrapper to convert Auth0 hook to our context format
 */
function Auth0ContextWrapper({ children }: { children: ReactNode }) {
  const {
    isAuthenticated: auth0IsAuthenticated,
    isLoading: auth0IsLoading,
    user: auth0User,
    error: auth0Error,
    loginWithRedirect,
    logout: logoutAuth0,
    getAccessTokenSilently: getAuth0Token,
  } = useAuth0Hook();

  const getAccessTokenSilently = async (): Promise<string | null> => {
    try {
      return await getAuth0Token();
    } catch {
      return null;
    }
  };

  const refreshTokenSilently = async (): Promise<void> => {
    // Auth0 handles refresh automatically
    try {
      await getAuth0Token();
    } catch {
      // Silently fail, Auth0 will handle it
    }
  };

  const value: AuthContextType = {
    isAuthenticated: auth0IsAuthenticated,
    isLoading: auth0IsLoading,
    user: auth0User as User | null,
    error: auth0Error as Error | null,
    login: loginWithRedirect,
    loginWithPassword: undefined,
    logout: logoutAuth0,
    getAccessTokenSilently,
    refreshTokenSilently,
  };

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

/**
 * Main Auth Provider - uses backend for token exchange in all environments
 * Backend handles Okta token exchange securely with client secret
 */
export function AuthProvider({ children }: AuthProviderProps) {
  // Always use BackendAuthProvider so backend handles token exchange
  // This keeps the client secret secure on the server
  return <BackendAuthProvider>{children}</BackendAuthProvider>;
}

/**
 * Hook to use auth context
 */
export function useAuth(): AuthContextType {
  const context = useContext(AuthContext);
  if (context === undefined) {
    throw new Error('useAuth must be used within an AuthProvider');
  }
  return context;
}

/**
 * Helper function to check if user is admin
 */
export function isAdmin(user: User | null): boolean {
  return user?.role === 'ADMIN';
}

/**
 * Helper function to check if user is management
 */
export function isManagement(user: User | null): boolean {
  return user?.role === 'MANAGEMENT';
}

/**
 * Helper function to check if user has management access (MANAGEMENT or ADMIN)
 */
export function hasManagementAccess(user: User | null): boolean {
  return user?.role === 'MANAGEMENT' || user?.role === 'ADMIN';
}

/**
 * Helper function to check if user has admin access (ADMIN only)
 */
export function hasAdminAccess(user: User | null): boolean {
  return user?.role === 'ADMIN';
}

