import { h, ref } from 'vue'
import axios, { AxiosError } from 'axios'
import config, { defaultRequestInterceptors, defaultResponseInterceptors } from './config'
import { isNotEmpty, isEmpty, isObject } from '@/utils/is'

import { AxiosInstance, InternalAxiosRequestConfig, RequestConfig, AxiosResponse } from './types'
import { ElButton, ElMessage, ElNotification } from 'element-plus'

import { useStorage } from '@/hooks/web/useStorage'
import { resetRouter } from '@/router'
import { useTagsViewStore } from '@/store/modules/tagsView'
import dayjs from 'dayjs'
import FileSaver from 'file-saver'

const { interceptors, baseUrl } = config
export const PATH_URL = baseUrl[import.meta.env.VITE_API_BASE_PATH]

const { requestInterceptors, responseInterceptors } = interceptors

const abortControllerMap: Map<string, AbortController> = new Map()

const axiosInstance: AxiosInstance = axios.create({
  ...config,
  baseURL: PATH_URL,
  withCredentials: true
})

axiosInstance.interceptors.request.use((res: InternalAxiosRequestConfig) => {
  const controller = new AbortController()
  const url = res.url || ''
  res.signal = controller.signal
  abortControllerMap.set(url, controller)
  return res
})

const tagsViewStore = useTagsViewStore()
const { clear } = useStorage()

const statusDesc = {
  403: '服务器拒绝执行此请求[403]',
  404: '您访问的链接丢失了[404]',
  405: '请求的方法不被允许[405]',
  408: '服务器等待请求已超时[408]',
  500: '系统内部发生错误[500]',
  501: '服务器不支持此请求[501]',
  504: '网关超时[504]',
  502: '服务器接收响应无效[502]',
  600: '系统内部发生错误[600]'
}

axiosInstance.interceptors.response.use(
  (res: AxiosResponse) => {
    const url = res.config.url || ''
    abortControllerMap.delete(url)
    // 这里不能做任何处理，否则后面的 interceptors 拿不到完整的上下文了
    return res
  },
  (error: AxiosError) => {
    console.log('err： ' + error) // for debug
    // const status = (error.response && error.response.status && error.response.status) || ''
    // const data: any = (error.response && error.response.data) || {}
    // if (data.message) {
    //   ElMessage(data.message)
    //   return Promise.reject(data.message)
    // } else if (error.code == 'ECONNABORTED' && error.message.indexOf('timeout') != -1) {
    //   ElMessage.error({ message: '您的请求已超时（10秒），请稍后重试', grouping: true })
    //   return Promise.reject('timeout')
    // } else if (status === 401) {
    //   ElMessage.error('登录过期,请重新登录!')

    //   clear()
    //   tagsViewStore.delAllViews()
    //   resetRouter() // 重置静态路由表
    //   location.reload() // 执行刷新

    //   return Promise.reject('登录过期,请重新登录')
    // } else if (status === 404) {
    //   ElMessage.error({ message: statusDesc[status], grouping: true })
    //   return Promise.reject('404')
    // } else if (statusDesc[status]) {
    //   ElMessage.error({ message: statusDesc[status], grouping: true })
    //   return Promise.reject(statusDesc[status])
    // }
    return Promise.reject(error)
  }
)

/**
 * 错误回调
 * @param {Function} error 报错后回调
 * @param {Boolean} override 是否覆盖报错后回调方法
 */
export function onError(
  error: () => void,
  override: boolean,
  responseText?: string | { title?: string; errorMsg?: string }
) {
  if (error && override) {
    error()
  } else {
    if (error) {
      error()
    }
    if (isNotEmpty(responseText)) {
      if (isObject(responseText)) {
        const { title, errorMsg = '' } = responseText
        ElNotification.error({
          title: isEmpty(title?.trim()) ? '服务器响应异常' : title,
          message: errorMsg,
          duration: 0
        })
      } else if (typeof responseText === 'string') {
        if (['timeout', '404'].includes(responseText)) {
          return
        }
        ElNotification.error({
          title: responseText,
          message: '如果您需要帮助，请联系管理员！',
          duration: 0
        })
      }
    } else {
      ElNotification.error({
        title: '服务器响应异常',
        message: '如果您需要帮助，请联系管理员！',
        duration: 0
      })
    }
  }
}

axiosInstance.interceptors.request.use(requestInterceptors || defaultRequestInterceptors)
axiosInstance.interceptors.response.use(responseInterceptors || defaultResponseInterceptors)

const service = {
  request: (config: RequestConfig) => {
    return new Promise((resolve, reject) => {
      if (config.interceptors?.requestInterceptors) {
        config = config.interceptors.requestInterceptors(config as any)
      }

      axiosInstance
        .request(config)
        .then((res) => {
          resolve(res)
        })
        .catch((responseText: any) => {
          if (isNotEmpty(responseText)) {
            if (isObject(responseText)) {
              const { title, errorMsg = '' } = responseText
              ElNotification.error({
                title: isEmpty(title?.trim()) ? '服务器响应异常' : title,
                message: h('p', null, [
                  h('div', null, '如您需要帮助，请将错误下载并反馈给管理员'),
                  h(
                    ElButton,
                    {
                      type: 'primary',
                      link: true,
                      onClick: () => {
                        const blob = new Blob([errorMsg], { type: 'text/plain;charset=utf-8' })
                        FileSaver.saveAs(blob, `error_${dayjs().format('YYYY-MM-DDTHH:mm:ss')}.txt`)
                      }
                    },
                    '点击下载'
                  )
                ]),
                duration: 0
              })
            } else if (typeof responseText === 'string') {
              if (['timeout', '404', '401'].includes(responseText)) {
                return
              }
              ElNotification.error({
                title: responseText,
                message: '如果您需要帮助，请联系管理员！',
                duration: 0
              })
            }
          } else {
            ElNotification.error({
              title: '服务器响应异常',
              message: '如果您需要帮助，请联系管理员！',
              duration: 0
            })
          }
          reject(responseText)
        })
    })
  },
  cancelRequest: (url: string | string[]) => {
    const urlList = Array.isArray(url) ? url : [url]
    for (const _url of urlList) {
      abortControllerMap.get(_url)?.abort()
      abortControllerMap.delete(_url)
    }
  },
  cancelAllRequest() {
    for (const [_, controller] of abortControllerMap) {
      controller.abort()
    }
    abortControllerMap.clear()
  }
}

// export function handleBody<T>(result: { body: any; head: Result<T> }) {
//   if (result.body && result.head) {
//     return { data: result.body, msg: result.head?.msg ?? '' }
//   }
//   return null
// }

export default service
