import axios, { AxiosRequestConfig } from "axios";

import { getRuntimeConfig } from '@/services/config';

// ----------------------------------------------------------------------

const axiosInstance = axios.create({ baseURL: '' });

// Initialize axios with runtime config
let configInitialized = false;
let initializationPromise: Promise<void> | null = null;

const initializeAxiosConfig = async () => {
  // If already initializing, wait for that promise to complete
  if (initializationPromise) {
    return initializationPromise;
  }

  // If already initialized with a valid baseURL, return
  if (configInitialized && axiosInstance.defaults.baseURL && axiosInstance.defaults.baseURL !== '') {
    return;
  }
  
  // Create initialization promise
  initializationPromise = (async () => {
    try {
      const config = await getRuntimeConfig();
      
      // Only set if we got a valid URL
      if (config.vsnGatewayApiUrl) {
        axiosInstance.defaults.baseURL = config.vsnGatewayApiUrl;
        configInitialized = true;
        console.log('Axios initialized with baseURL:', config.vsnGatewayApiUrl);
      } else {
        console.error('Invalid API gateway URL received from runtime config');
      }
    } catch (error) {
      console.error('Failed to initialize axios config:', error);
    } finally {
      initializationPromise = null;
    }
  })();

  return initializationPromise;
};

// Initialize config immediately
initializeAxiosConfig();

axiosInstance.interceptors.request.use(
  async (config) => {
    // Ensure config is initialized before each request
    await initializeAxiosConfig();

    // Validate that baseURL is set correctly
    if (!axiosInstance.defaults.baseURL || axiosInstance.defaults.baseURL === '') {
      console.error('Axios baseURL is not set, reinitializing...');
      configInitialized = false;
      await initializeAxiosConfig();
    }

    if (axiosInstance.defaults.baseURL) {
      if (config.url && typeof window !== 'undefined') {
        const frontendOrigin = window.location.origin;
        if (config.url.startsWith(frontendOrigin)) {
          const urlObj = new URL(config.url);
          config.url = urlObj.pathname + urlObj.search + urlObj.hash;
        }
      }

      // Ensure config uses the correct baseURL
      config.baseURL = axiosInstance.defaults.baseURL;
    }

    const token = localStorage.getItem('token');
    if (token) {
      config.headers['Authorization'] = `Bearer ${token}`;
    }
    return config;
  },
  (error) => Promise.reject(error)
);

axiosInstance.interceptors.response.use(
  (res) => res,
  (error) => Promise.reject((error.response && error.response.data) || 'Something went wrong')
);

export default axiosInstance;

// ----------------------------------------------------------------------
export const fetcher = async (
  args: string | [string, AxiosRequestConfig],
  method: 'get' | 'post' | 'put' | 'delete' | 'patch',
  data?: any
) => {
  try {
    // Ensure config is initialized before making requests
    await initializeAxiosConfig();

    const [url, config] = Array.isArray(args) ? args : [args];
    const axiosConfig = { ...config, method };

    if (method === 'post' || method === 'put' || method === 'patch') {
      axiosConfig.data = data;
    }
    const res = await axiosInstance(url, axiosConfig);

    return res.data;
  } catch (error) {
    console.error('Failed to fetch:', error);
    throw error;
  }
};
