import type { Ref } from 'vue'
import type { FetchContext, FetchOptions } from 'ofetch'
import { TYPE_ALERT } from '~/types/enum/enums'
import ApiRequestService from '~/services/data/apiRequestService'
import { usePageStore } from '~/stores/page'
import UnauthorizedError from '~/services/error/UnauthorizedError'
import { useAccessProfileStore } from '~/stores/accessProfile'

/**
 * Retourne une instance de ApiRequestService configurée pour interroger l'api Ap2i
 *
 * @see https://github.com/unjs/ohmyfetch/blob/main/README.md#%EF%B8%8F-create-fetch-with-default-options
 */
let apiRequestServiceClass: null | ApiRequestService = null
export const useAp2iRequestService = () => {
  const runtimeConfig = useRuntimeConfig()

  const baseURL = runtimeConfig.baseUrl ?? runtimeConfig.public.baseUrl

  const pending: Ref<boolean> = ref(false)

  /**
   * Peuple les headers avant l'envoi de la requête
   *
   * @param request
   * @param options
   */
  const onRequest = function ({ request, options }: FetchContext) {
    // @ts-expect-error options is not aware of noXaccessId
    if (options && options.noXaccessId) {
      return
    }

    const accessProfileStore = useAccessProfileStore()

    const headers = new Headers(options.headers)

    headers.set('x-accessid', String(accessProfileStore.id))
    headers.set('Authorization', 'BEARER ' + accessProfileStore.bearer)
    if (accessProfileStore.switchId) {
      headers.set('x-switch-user', String(accessProfileStore.switchId))
    }
    options.headers = headers

    pending.value = true
    console.log('Request : ' + request + ' (SSR: ' + process.server + ')')
  }

  const onRequestError = function (_: FetchContext) {
    pending.value = false
  }

  /**
   * Server responded
   */
  const onResponse = function (_: FetchContext) {
    pending.value = false
  }

  /**
   * Gère les erreurs retournées par l'api
   *
   * @param request
   * @param response
   * @param error
   */
  const onResponseError = function ({ response, error }: FetchContext) {
    pending.value = false

    if (response && response.status === 401) {
      throw new UnauthorizedError('Ap2i - Unauthorized')
    } else if (response && response.status === 403) {
      console.error('! Request error: Forbidden')
      usePageStore().addAlert(TYPE_ALERT.ALERT, ['forbidden'])
    } else if (
      response &&
      (response.status === 400 || response.status >= 404)
    ) {
      // @see https://developer.mozilla.org/fr/docs/Web/HTTP/Status
      let errorMsg
      if (error) {
        errorMsg = error.message
      } else if (response._data && response._data.detail) {
        errorMsg = response._data.detail
      } else if (response.statusText) {
        errorMsg = response.statusText
      } else {
        errorMsg = 'An error occured'
      }

      console.error('! Request error: ' + errorMsg)
      usePageStore().addAlert(TYPE_ALERT.ALERT, [errorMsg])
    }
  }

  const config: FetchOptions = {
    baseURL,
    onRequest,
    onRequestError,
    onResponse,
    onResponseError,
  }

  // Avoid memory leak
  if (apiRequestServiceClass === null) {
    // Utilise la fonction `create` d'ohmyfetch pour générer un fetcher dédié à l'interrogation de Ap2i
    const fetcher = $fetch.create(config)

    apiRequestServiceClass = new ApiRequestService(fetcher)
  }

  return { apiRequestService: apiRequestServiceClass, pending }
}
