import { LOGIN_KEY } from '@utils/enum'
import axios from 'axios'
import { Helpers } from '../utils/helper'
import { refreshToken } from './auth'

const protocol = axios.create({
  baseURL: '/',
})

const forceLogout = () => {
  Helpers.clearStorage()
  window.location.href = '/login'
}

protocol.interceptors.request.use(async (config) => {
  config.headers.set(
    'Content-Type',
    config.headers.get('Content-Type') ?? 'application/json',
  )

  if (
    config.url.indexOf('/login') >= 0 ||
    config.url.indexOf('/refresh') >= 0
  ) {
    return config
  }

  const { accessToken, exp } = await JSON.parse(
    Helpers.decrypt(localStorage.getItem(LOGIN_KEY)),
  )
  if (accessToken && !Helpers.checkTokenExpired(exp)) {
    config.headers.set('Authorization', `Bearer ${accessToken}`)
  }

  return config
})

protocol.interceptors.response.use(
  (response) => {
    return response.data || {}
  },
  async (error) => {
    const {
      response: { status, data },
      config,
    } = error

    if (
      config.url.indexOf('/login') >= 0 ||
      config.url.indexOf('/refresh') >= 0
    ) {
      return Promise.reject(data)
    }

    if (status === 401 && !config._retry) {
      config._retry = true
      try {
        // call refresh token
        const resp = await refreshToken()
        if (resp.status === 200) {
          const { data } = resp
          localStorage.setItem(LOGIN_KEY, Helpers.encrypt(JSON.stringify(data)))

          config.headers['Authorization'] = `Bearer ${data.accessToken}`
          return protocol(config)
        }
      } catch (error) {
        forceLogout()
        return Promise.reject(error)
      }
    }
    if (status === 403) {
      forceLogout()
    }

    return Promise.reject(data)
  },
)

export { protocol }
