import { message } from 'antd'
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios'
import React from 'react'

import {
  AuthenticationErrorContent,
  PermissionErrorContent
} from 'components/ErrorMessageContent'
import NetworkErrorContent from 'components/NetworkErrorContent'

// axios client

import auth from './auth'
import { dbaasUrl } from './endpoint'

const client = axios.create({
  timeout: 30 * 1000,
  paramsSerializer: (params) => {
    if (typeof params === 'object') {
      const qs: string[] = []
      Object.keys(params).forEach((k, idx) => {
        if (params[k] === undefined || params[k] === null) {
          return
        }
        if (Array.isArray(params[k])) {
          params[k].forEach((val: any) => {
            qs.push(`${k}=${val}`)
          })
          return
        }
        qs.push(`${k}=${encodeURIComponent(params[k])}`)
      })
      return qs.join('&')
    }
    return params
  }
})

client.interceptors.request.use((request) => {
  if (request.method !== 'options') {
    const token = auth.getAuthToken()

    if (token) {
      request.headers.Authorization = `Bearer ${token}`
    }
  }
  return request
})

client.interceptors.response.use(
  (response) => {
    // const data = response.data
    // reject no data error case
    return response || Promise.reject(response)
  },
  (error) => {
    const status = error.response?.status

    // 401 not authenticated, got to login
    if (status === 401) {
      // duration: 0, won't close automatically
      message.error({
        content: <AuthenticationErrorContent />,
        key: 'authenticationError'
      })
    }

    // 403 forbidden, not authorized
    if (status === 403) {
      message.error({
        content: (
          <PermissionErrorContent
            method={error.config?.method || 'unknown'}
            url={error.config?.url || 'unknown'}
          />
        ),
        key: 'permissinError'
      })
    } else if (error.config?.isShowMessage) {
      message.error(error.response?.data?.message || <NetworkErrorContent />)
    }

    return Promise.reject(error)
  }
)

export default client
