import type { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
import axios from 'axios'
import { AxiosCanceler } from './cancel'
import router from '@/router'
import { toast } from 'vue-sonner'
// import { HiAesUtil } from './HiAesUtil.ts'
// const encryptionKey = 'c0qhq99a-nq8h-ropg-wrlc-ezj4dlkxqpzx'
function redirectLogin() {
  localStorage.removeItem('Authorization')
  router.push({ path: '/', query: { login: 'true' } })
}
export interface ExtraConfig {
  /**
   * 默认值 1 错误等级 0-忽略，1-warning，2-error
   */
  errorLevel?: 0 | 1 | 2
  /**
   * 默认true 是否携带token
   */
  withToken?: boolean
  /**
   * 默认true 是否处理响应
   */
  handleResponse?: boolean
  /**
   * 默认false 是否取消重复请求
   */
  cancelRepetition?: boolean
  /**
   * 默认false 是否返回axios完整响应
   */
  originResponseData?: boolean
  /**
   * 默认token 存储key
   */
  tokenKey?: string
  /**
   * 获取token的方法
   */
  getToken?: () => string
  /**
   * 自定义header方法，此方法返回的header会覆盖默认的header
   */
  formatHeader?: (header: Record<string, string>) => Record<string, string>
}

export interface RequestConfig extends AxiosRequestConfig {
  extraConfig?: ExtraConfig
}

interface ResponseType extends AxiosResponse {
  config: RequestConfig
}

const ERROR_MESSAGES: Record<number | string, string> = {
  '200': '成功',
  '500': '内部服务器错误',
  '10001': '数据库查询错误',
  '10002': '数据库更新错误',
  '10003': '数据库插入错误',
  '10004': '数据库删除错误',
  '20001': '用户已存在',
  '20002': '用户不存在',
  '20003': '用户密码错误',
  '20004': '用户已禁用',
  '20005': '余额不足',
  '20006': '停止注册',
  '20007': '未绑定Telegram',
  '20008': '用户未绑定OAuth方式',
  '20009': '邀请码错误',
  '30001': '节点已存在',
  '30002': '节点不存在',
  '30003': '节点组已存在',
  '30004': '节点组不存在',
  '30005': '节点组不为空',
  '400': '参数错误',
  '40002': '用户令牌为空',
  '40003': '用户令牌无效',
  '40004': '用户令牌已过期',
  '40005': '您还没有登录',
  '401': '请求过多',
  '50001': '优惠券不存在',
  '50002': '优惠券已被使用',
  '50003': '优惠券不匹配',
  '60001': '订阅已过期',
  '60002': '订阅不可用',
  '60003': '用户已有订阅',
  '60004': '订阅已被使用',
  '60005': '单一订阅模式超出限制',
  '60006': '订阅配额限制',
  '70001': '验证码错误',
  '80001': '队列入队错误',
  '90001': '调试模式已启用',
  '90002': '发送短信错误',
  '90003': '短信功能未启用',
  '90004': '电子邮件功能未启用',
  '90005': '不支持的登录方式',
  '90006': '身份验证器不支持此方式',
  '90007': '电话区号为空',
  '90008': '密码为空',
  '90009': '区号为空',
  '90010': '需要密码或验证码',
  '90011': '电子邮件已存在',
  '90012': '电话号码已存在',
  '90013': '设备已存在',
  '90014': '电话号码错误',
  '90015': '此账户今日已达到发送次数限制',
  '90017': '设备不存在',
  '90018': '用户 ID 不匹配',
  '61001': '订单不存在',
  '61002': '支付方式未找到',
  '61003': '订单状态错误',
  '61004': '重置周期不足',
  '61005': '存在没用完的流量',
}

export default class Request {
  public axiosInstance: AxiosInstance

  private config: RequestConfig

  constructor(config: RequestConfig) {
    this.config = config
    this.axiosInstance = axios.create(config)
    this.init()
  }

  static defaultConfig: Required<ExtraConfig> = {
    errorLevel: 2,
    withToken: true,
    handleResponse: true,
    cancelRepetition: false,
    originResponseData: false,
    tokenKey: 'token',
    formatHeader: (headers) => {
      return headers
    },
    getToken: () => '',
  }

  private errorReport(lv: number, message: string) {
    toast(message)
  }

  private init() {
    const axiosCanceler = new AxiosCanceler()

    this.axiosInstance.interceptors.request.use(
      (config: RequestConfig) => {
        const mergeExtraConfig = {
          ...Request.defaultConfig,
          ...this.config.extraConfig,
          ...config.extraConfig,
        }

        // if (config.data && !(config.data instanceof FormData)) {
        //   const plainText = JSON.stringify(config.data)
        //   config.data = HiAesUtil.encryptData(plainText, encryptionKey)
        // }
        //
        // if (config.method?.toLowerCase() === 'get' || config.params) {
        //   const paramsToEncrypt = config.params || {}
        //   // console.log('paramsToEncrypt', paramsToEncrypt)
        //   const plainParamsText = JSON.stringify(paramsToEncrypt)
        //   const encryptedParams = HiAesUtil.encryptData(plainParamsText, encryptionKey)
        //
        //   config.params = {
        //     data: encryptedParams.data,
        //     time: encryptedParams.time,
        //   }
        // }

        config.headers = mergeExtraConfig.formatHeader({
          ...this.config.headers,
          ...config.headers,
          lang: 'zh_CN',
          // 'login-type': 'device',
          ...(mergeExtraConfig.withToken && {
            [mergeExtraConfig.tokenKey]: mergeExtraConfig.getToken(),
          }),
        } as any)
        config.extraConfig = mergeExtraConfig
        if (mergeExtraConfig.cancelRepetition) {
          axiosCanceler.addPending(config)
        }
        return config
      },
      (error) => {
        this.errorReport(error?.config.extraConfig.errorLevel, error)
        return Promise.reject(error)
      },
    )

    this.axiosInstance.interceptors.response.use(
      (response: ResponseType) => {
        const { data, config } = response
        const responseData = response.data.data

        // if (responseData && responseData.data && responseData.time) {
        //   try {
        //     const decryptedStr = HiAesUtil.decryptData(
        //       responseData.data,
        //       responseData.time,
        //       encryptionKey,
        //     )
        //     // console.log('decryptedStr', JSON.parse(decryptedStr))
        //     responseData = JSON.parse(decryptedStr)
        //   } catch (e) {
        //     console.error('解密失败:', e)
        //     return Promise.reject({ message: '数据解密异常' })
        //   }
        // }
        axiosCanceler.removePending(config)

        if (data.code !== 200) {
          const msg = ERROR_MESSAGES[data.code] || response.data?.msg || data?.error || '未知错误'

          if (data.code == 40004 || data.code == 40003 || data.code == 40005) {
            toast.error(msg)
            redirectLogin()
            return
          }

          if (config.extraConfig?.handleResponse) {
            this.errorReport(config.extraConfig.errorLevel ?? 2, msg)
            return Promise.reject({
              ...data,
              message: msg,
            })
          }
        }

        return config.extraConfig?.originResponseData ? response : responseData
      },
      (error) => {
        const status = error?.response?.status
        const code = error?.code
        let message = error?.message
        if (status === 401) {
          redirectLogin()
          return
        }
        if (code === 'ECONNABORTED') {
          message = '网络环境太差，请求超时'
        } else if (code === 'Network Error' || message === 'Network Error') {
          if (error.response) {
            message = `${error.response.status}:network连接失败，请求中断`
          } else {
            message = '网络好像出现问题了'
          }
        }
        if (error.__CANCEL__) {
          console.warn('request canceled', error?.message)
        } else {
          this.errorReport(error?.config?.extraConfig?.errorLevel, message)
        }
        return Promise.reject(error)
      },
    )
  }

  public get<T>(url: string, params?: Record<string, unknown>, config?: RequestConfig): Promise<T> {
    return this.axiosInstance.get(url, { ...config, params })
  }

  public post<D, T>(url: string, data?: D, config?: RequestConfig): Promise<T> {
    return this.axiosInstance.post(url, data, { ...config })
  }

  public put<D, T>(url: string, data?: D, config?: RequestConfig): Promise<T> {
    return this.axiosInstance.put(url, data, { ...config })
  }

  public patch<D, T>(url: string, data?: D, config?: RequestConfig): Promise<T> {
    return this.axiosInstance.patch(url, data, { ...config })
  }

  public delete<D, T>(url: string, params?: D, config?: RequestConfig): Promise<T> {
    return this.axiosInstance.delete(url, { ...config, params })
  }
}
