import axios, { AxiosInstance, AxiosRequestConfig } from 'axios'

type HttpClientFactoryOptions = {
  config?: AxiosRequestConfig
  getSocketId?: () => string
  authenticate?: () => Promise<unknown>
}

export const HttpClientFactory = ({
  config,
  getSocketId,
  authenticate,
}: HttpClientFactoryOptions): AxiosInstance => {
  const instance = axios.create(config)

  instance.interceptors.request.use(
    function(config) {
      config.headers['X-Site'] = process.env.PROJECT_NAME

      if (getSocketId) {
        config.headers['X-Socket-Id'] = getSocketId()
      }

      return config
    },
    function(error) {
      return Promise.reject(error)
    }
  )

  instance.interceptors.response.use(
    r => r,
    async error => {
      if (!authenticate || error.response.status !== 401) {
        throw error
      }

      if (error.config.retry) {
        throw error
      }

      await authenticate()

      const retryRequest = {
        ...error.config,
        retry: true,
      }

      return instance(retryRequest)
    }
  )

  return instance
}
