import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';
import { API_CONFIG } from './config';

// Define types for tokens and responses
interface TokenResponse {
  access_token: string;
  refresh_token: string;
}

interface APIResponse<T = any> {
  success: boolean;
  result: T;
}

// Utility functions to manage tokens
const getAccessToken = (): string | null => localStorage.getItem('access_token');
const getRefreshToken = (): string | null => localStorage.getItem('refresh_token');

// Token refresh logic
let isRefreshing = false;

// Function to create Axios instances
const createAxiosInstance = (baseURL: string, defaultHeaders: Record<string, string> = {}): AxiosInstance => {
  return axios.create({
    baseURL,
    timeout: API_CONFIG.TIMEOUT,
    headers: defaultHeaders,
  });
};

// Primary axios instance
export const axiosInstance: AxiosInstance = createAxiosInstance(API_CONFIG.BASE_URL);

// Request interceptor
axiosInstance.interceptors.request.use(
  (config: AxiosRequestConfig): AxiosRequestConfig => {
    const token = getAccessToken();
    if (token) {
      config.headers = {
        ...config.headers,
        Authorization: `Bearer ${token}`,
      };
    }
    return config;
  },
  (error: AxiosError): Promise<AxiosError> => Promise.reject(error)
);

// Response interceptor
axiosInstance.interceptors.response.use(
  (response: AxiosResponse): AxiosResponse => response,
  async (error: AxiosError): Promise<AxiosResponse | void> => {
    const originalRequest = error.config;

    if (error.response?.status === 403) {
      try {
        await axios.get(`${API_CONFIG.BASE_URL}/users/logout`, {
          headers: {
            Authorization: `Bearer ${getAccessToken()}`,
            'Content-Type': 'application/json',
          },
        });
      } catch (logoutError) {
        console.error('Logout failed:', logoutError);
      }
      return Promise.reject(error);
    }

    if (error.response?.status === 401 && !originalRequest._retry) {
      originalRequest._retry = true;

      if (!isRefreshing) {
        isRefreshing = true;
        try {
          const response = await axios.get<APIResponse<TokenResponse>>(`${API_CONFIG.BASE_URL}/users/refresh-token`, {
            headers: {
              refresh_token: getRefreshToken() || '',
              'Content-Type': 'application/json',
            },
          });
          const { access_token, refresh_token } = response.data.result;

          localStorage.setItem('access_token', access_token);
          localStorage.setItem('refresh_token', refresh_token);

          isRefreshing = false;

          originalRequest.headers = {
            ...originalRequest.headers,
            Authorization: `Bearer ${access_token}`,
          };
          return axiosInstance(originalRequest);
        } catch (refreshError) {
          isRefreshing = false;
          return Promise.reject(refreshError);
        }
      }
    }

    return Promise.reject(error);
  }
);