import axios, { AxiosResponse, ResponseType } from 'axios';
import { useApiLogStore } from './apiLogStore';

// Clean server path, removing trailing slash if present
const rawBaseUrl = import.meta.env.VITE_API_BASE_URL || '';
const serverPath = rawBaseUrl.replace(/\/$/, '');

type THttpMethod = 'get' | 'put' | 'post' | 'delete';

const DEFAULT_TIMEOUT = 60;

export type ApiResponse<T> = {
  [x: string]: any;
  data: T;
  status: number;
};

export async function api<T = any>(
  method: THttpMethod,
  url: string,
  data?: any,
  params?: any,
  responseType: ResponseType = 'json',
  timeoutInSeconds: number = DEFAULT_TIMEOUT,
  skipAuth: boolean = false
): Promise<ApiResponse<T>> {
  const user = JSON.parse(localStorage.getItem('user') || '{}');
  const token = user?.token || '';

  const headers: Record<string, string> = {
    'Content-Type': 'application/json',
  };

  if (!skipAuth && token) {
    headers['Authorization'] = `Bearer ${token}`;
  }

  const axiosInstance = axios.create({
    baseURL: serverPath,
    timeout: timeoutInSeconds * 1000,
    headers,
    withCredentials: !skipAuth,
    responseType,
  });

  const logApiCall = useApiLogStore.getState().logApiCall;

  try {
    const requestOptions: any = {
      method,
      url,
      data,
      params,
    };

    const start = performance.now();
    const response: AxiosResponse<T> = await axiosInstance.request(requestOptions);
    const end = performance.now();

    const apiResponse: ApiResponse<T> = {
      data: response.data,
      status: response.status,
    };

    logApiCall({
      method,
      url,
      status: response.status,
      responseTime: end - start,
      timestamp: new Date().toISOString(),
    });

    return apiResponse;
  } catch (error: any) {
    console.error('API Error:', {
      url,
      method,
      error: error.response?.data || error.message,
      status: error.response?.status,
    });

    logApiCall({
      method,
      url,
      status: error.response?.status || 500,
      responseTime: 0,
      timestamp: new Date().toISOString(),
    });

    throw error;
  }
}
