import axios, { AxiosError, AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';

interface ApiService {
  get<T>(url: string, config?: AxiosRequestConfig): Promise<T>;
  post<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T>;
  put<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T>;
  delete<T>(url: string, config?: AxiosRequestConfig): Promise<T>;
}

type RequestOptions = {
  transformRequest?: AxiosRequestConfig['transformRequest'];
  transformResponse?: <T>(response: T, config: AxiosRequestConfig) => T;
}

class HttpService implements ApiService {
  private axiosInstance: AxiosInstance;
  private options?: RequestOptions;

  constructor(baseURL: string, options?: RequestOptions) {
    this.axiosInstance = axios.create({
      baseURL,
      timeout: 5000, // Set your desired timeout value
    });
    this.options = options;
  }

  get<T>(url: string, config?: AxiosRequestConfig): Promise<T> {
    return this.request({ url, method: 'GET', ...config })
  }

  post<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
    return this.request({ url, method: 'POST', data, ...config })
  }

  put<T>(url: string, data?: any, config?: AxiosRequestConfig): Promise<T> {
    return this.request({ url, method: 'PUT', data, ...config })
  }

  delete<T>(url: string, config?: AxiosRequestConfig): Promise<T> {
    return this.request({ url, method: 'DELETE', ...config })
  }

  request<T = any>(config: AxiosRequestConfig): Promise<T> {
    config.headers = {
      ...config.headers,
      Authorization: localStorage.getItem('token') || '',
    }
    
   const { transformResponse } = this.options || {};
    
    return new Promise((resolve, reject) => {
      this.axiosInstance
      .request(config)
      .then((response: AxiosResponse<T>) => {
        if (transformResponse) {
          try {
            const res = transformResponse(response.data, config);
            resolve(res);
          }
          catch (e) {
            reject(e);
          }
        }
        resolve(response.data);
      })
      .catch((e: Error | AxiosError) => {
        reject(e);
      })
    })
  }
}

export default HttpService;