import axios from 'axios'
import type {
  AxiosError,
  AxiosInstance,
  AxiosRequestConfig,
  AxiosResponse,
} from 'axios'
import { showToast } from 'vant'
import 'vant/es/toast/style'
import { getAppType, getChannelCode } from './app'
import { removeToken, removeUserInfo } from './user'
import { getLocal } from './storage'
import { EnumStorageKey } from '@/enum'
import { DONT_NEED_WECHAT_AUTH_PATHS } from '@/constants'

function removeUrlParameter(url: string, parameter: string): string {
  // 解析传入的URL
  const urlObj = new URL(url)
  const params = new URLSearchParams(urlObj.search)

  // 移除指定的参数
  params.delete(parameter)

  // 构建新的search字符串
  urlObj.search = params.toString()

  // 返回新的URL字符串
  return urlObj.toString()
}

export interface Response<T> {
  data: T
  config: AxiosRequestConfig
}
export interface ResponseData<T = any> {
  code: string
  message: string
  data: T
  ok: boolean
}

const env = import.meta.env

// 这里依旧
export interface IAxiosInstance extends AxiosInstance {
  <D = any>(config: AxiosRequestConfig): Promise<ResponseData<D>>
}

const service: IAxiosInstance = axios.create({
  timeout: 300000,
  // 开发环境需要获取其他环境数据，在config中配置
  // 本地服务器test环境走外网
  // 线上环境，不走外网
  baseURL: env.VITE_NODE_ENV === 'dev' ? '/api' : env.VITE_APP_BASE_API,
})

/* 请求拦截器 */
service.interceptors.request.use(
  (config: any) => {
    if (config.url && env.MODE !== 'development')
      config.url = config.url.replace(/^\/api/, '')

    config.headers = {
      'X-Token': getLocal(EnumStorageKey.token) || '',
      'X-Request-Id': `${Date.now()}${Math.random().toString(36).substring(2)}`,
      'X-Request-By': config.url,
      'X-App-Type': getAppType() || '',
      'X-Channel-Code': getChannelCode() || '',
    }
    return config
  },
  (error: AxiosError) => {
    showToast(error.message)
    return Promise.reject(error)
  },
)

/* 响应拦截器 */
service.interceptors.response.use(
  (response: AxiosResponse<any, Response<ResponseData>>) => {
    const { code, message } = response.data
    if (response.config.responseType === 'stream')
      return response

    if (code === '00000000') {
      return response.data
    }
    else if (code === '00000005') {
      // 处理登录失效
      removeToken()
      removeUserInfo()
      const newUrl = removeUrlParameter(window.location.href, 'code')
      window.history.replaceState(null, '', newUrl)
      const flag = DONT_NEED_WECHAT_AUTH_PATHS.some(item => window.location.pathname.includes(item))
      if (!flag)
        window.location.reload()
    }
    else {
      showToast(message)
      return Promise.reject(new Error(message))
    }
  },
  (error: AxiosError) => {
    showToast('网络请求异常')
    return Promise.reject(error)
  },
)

/* 导出封装的请求方法 */
export const http = {
  get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
    return service.get(url, config)
  },

  post<T = any>(
    url: string,
    data?: object,
    config?: AxiosRequestConfig,
  ): Promise<T> {
    return service.post(url, data, config)
  },

  put<T = any>(
    url: string,
    data?: object,
    config?: AxiosRequestConfig,
  ): Promise<T> {
    return service.put(url, data, config)
  },

  delete<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
    return service.delete(url, config)
  },
}

/* 导出 axios 实例 */
export default service
