// src/contexts/AuthContext.tsx
import React, { createContext, useState, useEffect, useContext, useMemo, useCallback } from 'react';
import { Platform, ActivityIndicator, View, StyleSheet } from 'react-native'; // Import Platform
import * as SecureStore from 'expo-secure-store';
import AsyncStorage from '@react-native-async-storage/async-storage'; // Use AsyncStorage for web localStorage
import apiClient from '../api/client';
import { useTheme } from 'react-native-paper';

const TOKEN_KEY = 'maia_access_token'; // Use the same key

interface AuthContextData {
  authToken: string | null;
  isAuthenticated: boolean;
  isLoading: boolean;
  login: (username: string, password: string) => Promise<void>;
  logout: () => Promise<void>;
}

const AuthContext = createContext<AuthContextData>({
  authToken: null,
  isAuthenticated: false,
  isLoading: true,
  login: async () => { throw new Error('AuthContext not initialized'); },
  logout: async () => { throw new Error('AuthContext not initialized'); },
});

interface AuthProviderProps {
  children: React.ReactNode;
}

// Helper functions for platform-specific storage
const storeToken = async (token: string) => {
  if (Platform.OS === 'web') {
    try {
        // Use AsyncStorage for web (polyfilled to localStorage)
        await AsyncStorage.setItem(TOKEN_KEY, token);
    } catch (e) {
        console.error("Failed to save token to web storage", e);
    }
  } else {
    await SecureStore.setItemAsync(TOKEN_KEY, token);
  }
};

const getToken = async (): Promise<string | null> => {
  if (Platform.OS === 'web') {
     try {
        return await AsyncStorage.getItem(TOKEN_KEY);
     } catch (e) {
        console.error("Failed to get token from web storage", e);
        return null;
     }
  } else {
    // SecureStore might throw if not available, handle gracefully
    try {
        return await SecureStore.getItemAsync(TOKEN_KEY);
    } catch (e) {
        console.error("Failed to get token from secure store", e);
        // If SecureStore fails on native, treat as no token found
        return null;
    }
  }
};

const deleteToken = async () => {
  if (Platform.OS === 'web') {
     try {
        await AsyncStorage.removeItem(TOKEN_KEY);
     } catch (e) {
        console.error("Failed to remove token from web storage", e);
     }
  } else {
    // Avoid potential crash if SecureStore is unavailable
    try {
       await SecureStore.deleteItemAsync(TOKEN_KEY);
    } catch (e) {
        console.error("Failed to delete token from secure store", e);
    }
  }
};


export const AuthProvider: React.FC<AuthProviderProps> = ({ children }) => {
  const [authToken, setAuthToken] = useState<string | null>(null);
  const [isLoading, setIsLoading] = useState<boolean>(true);

  const loadToken = useCallback(async () => {
    console.log("[AuthContext] loadToken: Starting..."); // Log: Start
    setIsLoading(true);
    try {
      console.log("[AuthContext] loadToken: Calling getToken()..."); // Log: Before await
      const storedToken = await getToken(); // Use helper
      console.log("[AuthContext] loadToken: getToken() returned:", storedToken); // Log: After await

      if (storedToken) {
        console.log('[AuthContext] loadToken: Token found. Setting state and headers.'); // Log: Token Found Path
        setAuthToken(storedToken);
        apiClient.defaults.headers.common['Authorization'] = `Bearer ${storedToken}`;
      } else {
        console.log('[AuthContext] loadToken: No token found. Clearing state and headers.'); // Log: No Token Path
        setAuthToken(null);
        delete apiClient.defaults.headers.common['Authorization'];
      }
      console.log('[AuthContext] loadToken: Try block finished successfully.'); // Log: Try Success
    } catch (error) {
      // **Log the actual error object**
      console.error("[AuthContext] loadToken: Caught error:", error); // Log: Catch Block
      setAuthToken(null); // Ensure logged out state on error
      delete apiClient.defaults.headers.common['Authorization'];
    } finally {
      console.log("[AuthContext] loadToken: Entering finally block."); // Log: Finally Start
      setIsLoading(false);
      console.log("[AuthContext] loadToken: setIsLoading(false) called."); // Log: Finally End
    }
  }, []);

  useEffect(() => {
    console.log("[AuthContext] useEffect: Component mounted, calling loadToken."); // Log: useEffect call
    loadToken();
  }, [loadToken]);

  const login = useCallback(async (username: string, password: string) => {
    console.log("[AuthContext] login: Function called with:", username); // Log: Function entry
    try {
      console.log("[AuthContext] login: Preparing to call apiClient.post for /auth/login");
      console.log("[AuthContext] login: Data being sent:", { username: username, password: password });

      // const response = await apiClient.post(`/auth/login?grant_type=password&username=${username}&password=${password}`);
      const response = await apiClient.post(
        '/auth/login',
        'grant_type=password&username=' + encodeURIComponent(username) + '&password=' + encodeURIComponent(password) + '&scope=&client_id=&client_secret=',
        {
          headers: {
            'accept': 'application/json',
            'Content-Type': 'application/x-www-form-urlencoded',
          },
        }
      );

      console.log("[AuthContext] login: apiClient.post successful, response status:", response?.status); // Log success

      const { access_token } = response.data;

      if (!access_token || typeof access_token !== 'string') {
         console.error("[AuthContext] login: Invalid token structure received:", response.data);
         throw new Error('Invalid token received from server.');
      }

      console.log('[AuthContext] login: Login successful, received token.');
      setAuthToken(access_token);
      apiClient.defaults.headers.common['Authorization'] = `Bearer ${access_token}`;
      await storeToken(access_token); // Use helper

    } catch (error: any) {
      // --- Log the error object *itself* ---
      console.error("[AuthContext] login: Caught Error Object:", error);

      // --- Check if it's an Axios error with config details ---
      if (error.isAxiosError) {
          console.error("[AuthContext] login: Axios Error Details:");
          console.error("  Request Config:", error.config);
          console.error("  Response:", error.response); // This will likely still be undefined
          console.error("  Message:", error.message);
      }

      // Original logging (might be redundant now but keep for context)
      console.error("Login failed:", error.response?.data || error.message);
      throw error; // Re-throw
    }
  }, []);

  const logout = useCallback(async () => {
    console.log('Logging out.');
    setAuthToken(null);
    delete apiClient.defaults.headers.common['Authorization'];
    await deleteToken(); // Use helper
    await apiClient.post("/auth/logout");
  }, []);

  const contextValue = useMemo(() => ({
    authToken,
    isAuthenticated: !!authToken,
    isLoading,
    login,
    logout,
  }), [authToken, isLoading, login, logout]);

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

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

export const AuthLoadingScreen: React.FC = () => {
    const theme = useTheme();
    const styles = StyleSheet.create({
        container: { flex: 1, justifyContent: 'center', alignItems: 'center', backgroundColor: theme.colors.background }
    });
    return (<View style={styles.container}><ActivityIndicator size="large" color={theme.colors.primary} /></View>);
}