import React, { createContext, useState, useContext, useEffect } from 'react';
import axios from 'axios';
import api from '../utils/api';
import logger from '../utils/logger';

const AuthContext = createContext();

const API_URL = process.env.REACT_APP_BACKEND_URL || window.location.origin;

// Log environment on module load for debugging
logger.log('[AuthContext] Module initialized with:', {
  REACT_APP_BACKEND_URL: process.env.REACT_APP_BACKEND_URL,
  REACT_APP_BASENAME: process.env.REACT_APP_BASENAME,
  API_URL: API_URL
});

export const AuthProvider = ({ children }) => {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);
  const [token, setToken] = useState(localStorage.getItem('token'));
  const [permissions, setPermissions] = useState([]);

  useEffect(() => {
    const initAuth = async () => {
      const storedToken = localStorage.getItem('token');
      if (storedToken) {
        try {
          const response = await axios.get(`${API_URL}/api/auth/me`, {
            headers: { Authorization: `Bearer ${storedToken}` }
          });
          setUser(response.data);
          setToken(storedToken);

          // Fetch user permissions
          await fetchPermissions(storedToken);
        } catch (error) {
          localStorage.removeItem('token');
          setToken(null);
          setPermissions([]);
        }
      }
      setLoading(false);
    };
    initAuth();
  }, []);

  const fetchPermissions = async (authToken) => {
    try {
      const tokenToUse = authToken || token || localStorage.getItem('token');
      if (!tokenToUse) {
        setPermissions([]);
        return;
      }

      const response = await axios.get(`${API_URL}/api/auth/permissions`, {
        headers: { Authorization: `Bearer ${tokenToUse}` }
      });
      setPermissions(response.data.permissions || []);
    } catch (error) {
      logger.error('Failed to fetch permissions:', error);
      setPermissions([]);
    }
  };

  const login = async (email, password) => {
    try {
      logger.log('[AuthContext] Starting login request...', {
        API_URL: API_URL,
        envBackendUrl: process.env.REACT_APP_BACKEND_URL,
        fullUrl: `${API_URL}/api/auth/login`
      });

      // Use api instance for retry logic
      const response = await api.post(
        '/auth/login',
        { email, password },
        {
          headers: {
            'Content-Type': 'application/json'
          }
        }
      );

      logger.log('[AuthContext] Login response received:', {
        status: response.status,
        hasToken: !!response.data?.access_token,
        hasUser: !!response.data?.user
      });

      const { access_token, user: userData } = response.data;

      if (!access_token || !userData) {
        throw new Error('Invalid response from server - missing token or user data');
      }

      // Store token FIRST and verify it was stored
      localStorage.setItem('token', access_token);
      const storedToken = localStorage.getItem('token');
      if (storedToken !== access_token) {
        throw new Error('Failed to store token in localStorage');
      }
      logger.log('[AuthContext] Token stored and verified in localStorage');

      // Update state in correct order
      setToken(access_token);
      setUser(userData);
      logger.log('[AuthContext] User state updated:', {
        email: userData.email,
        role: userData.role
      });

      // Fetch permissions immediately and WAIT for it (but don't fail login if it fails)
      try {
        logger.log('[AuthContext] Fetching permissions...');
        await fetchPermissions(access_token);
        logger.log('[AuthContext] Permissions fetched successfully');
      } catch (permError) {
        logger.error('[AuthContext] Failed to fetch permissions (non-critical):', {
          message: permError.message,
          response: permError.response?.data,
          status: permError.response?.status
        });
        // Set empty permissions array so hasPermission doesn't break
        setPermissions([]);
        // Don't throw - login succeeded even if permissions failed
      }

      return userData;
    } catch (error) {
      // Enhanced error logging
      logger.error('[AuthContext] Login failed:', {
        message: error.message,
        response: error.response?.data,
        status: error.response?.status,
        code: error.code,
        config: {
          url: error.config?.url,
          method: error.config?.method,
          timeout: error.config?.timeout
        }
      });

      // Clear any partial state
      localStorage.removeItem('token');
      setToken(null);
      setUser(null);
      setPermissions([]);

      // Re-throw to let Login component handle the error
      throw error;
    }
  };

  const logout = () => {
    localStorage.removeItem('token');
    setToken(null);
    setUser(null);
    setPermissions([]);
  };

  const register = async (userData) => {
    await axios.post(`${API_URL}/api/auth/register`, userData);
  };

  const refreshUser = async () => {
    try {
      const currentToken = localStorage.getItem('token');
      if (!currentToken) {
        throw new Error('No token available');
      }

      const response = await axios.get(`${API_URL}/api/auth/me`, {
        headers: { Authorization: `Bearer ${currentToken}` }
      });
      setUser(response.data);
      return response.data;
    } catch (error) {
      logger.error('Failed to refresh user:', error);
      // If token expired, logout
      if (error.response?.status === 401) {
        logout();
      }
      throw error;
    }
  };

  const forgotPassword = async (email) => {
    const response = await axios.post(`${API_URL}/api/auth/forgot-password`, { email });
    return response.data;
  };

  const resetPassword = async (token, newPassword) => {
    const response = await axios.post(`${API_URL}/api/auth/reset-password`, {
      token,
      new_password: newPassword
    });
    return response.data;
  };

  const changePassword = async (currentPassword, newPassword) => {
    const currentToken = localStorage.getItem('token');
    if (!currentToken) {
      throw new Error('Not authenticated');
    }

    const response = await axios.put(
      `${API_URL}/api/users/change-password`,
      {
        current_password: currentPassword,
        new_password: newPassword
      },
      {
        headers: { Authorization: `Bearer ${currentToken}` }
      }
    );

    // Refresh user data to clear force_password_change flag if it was set
    await refreshUser();

    return response.data;
  };

  const resendVerificationEmail = async () => {
    const currentToken = localStorage.getItem('token');
    if (!currentToken) {
      throw new Error('Not authenticated');
    }

    const response = await axios.post(
      `${API_URL}/api/auth/resend-verification-email`,
      {},
      {
        headers: { Authorization: `Bearer ${currentToken}` }
      }
    );

    return response.data;
  };

  const hasPermission = (permissionCode) => {
    if (!user) return false;
    // Superadmin always has all permissions
    if (user.role === 'superadmin') return true;
    return permissions.includes(permissionCode);
  };

  return (
    <AuthContext.Provider value={{
      user,
      token,
      permissions,
      login,
      logout,
      register,
      refreshUser,
      forgotPassword,
      resetPassword,
      changePassword,
      resendVerificationEmail,
      hasPermission,
      loading
    }}>
      {children}
    </AuthContext.Provider>
  );
};

export const useAuth = () => useContext(AuthContext);
