/**
 * PC端Vue项目通用fetch请求工具类
 */
import { removeToken } from '@/utils/auth'
const message = useMessage() // 消息弹窗

class FetchHttp {
  constructor() {
    // 基础配置
    this.baseUrl = import.meta.env.VITE_BASE_URL_APP_LITE
    this.timeout = 30000 // 默认超时时间30秒
    this.headers = {
      'Content-Type': 'application/json'
      // 可以添加其他默认请求头
    }
    this.abortControllers = new Map() // 存储请求的abort controller
    this.requestInterceptors = [] // 请求拦截器
    this.responseInterceptors = [] // 响应拦截器

    // 401处理配置
    this.unauthorizedHandlers = [] // 401处理函数数组
    this.isHandlingUnauthorized = false // 防止重复处理
  }

  /**
   * 设置基础URL
   * @param {String} url - 基础URL
   */
  setBaseUrl(url) {
    this.baseUrl = url
  }

  /**
   * 设置默认请求头
   * @param {Object} headers - 请求头对象
   */
  setHeaders(headers) {
    this.headers = { ...this.headers, ...headers }
  }

  /**
   * 设置超时时间
   * @param {Number} timeout - 超时时间(毫秒)
   */
  setTimeout(timeout) {
    this.timeout = timeout
  }

  /**
   * 添加请求拦截器
   * @param {Function} interceptor - 拦截器函数
   */
  addRequestInterceptor(interceptor) {
    this.requestInterceptors.push(interceptor)
  }

  /**
   * 添加响应拦截器
   * @param {Function} interceptor - 拦截器函数
   */
  addResponseInterceptor(interceptor) {
    this.responseInterceptors.push(interceptor)
  }

  /**
   * 添加401未授权处理函数
   * @param {Function} handler - 处理函数
   */
  addUnauthorizedHandler(handler) {
    this.unauthorizedHandlers.push(handler)
  }

  /**
   * 处理401未授权状态
   */
  async handleUnauthorized() {
    // 防止重复处理
    if (this.isHandlingUnauthorized) {
      return
    }

    this.isHandlingUnauthorized = true

    try {
      // 执行所有注册的401处理函数
      for (const handler of this.unauthorizedHandlers) {
        await handler()
      }

      // 如果没有注册处理函数，使用默认跳转逻辑
      if (this.unauthorizedHandlers.length === 0) {
        this.defaultUnauthorizedHandler()
      }
    } catch (error) {
      console.error('处理401错误时发生异常:', error)
    } finally {
      // 延迟重置状态，避免短时间内重复触发
      setTimeout(() => {
        this.isHandlingUnauthorized = false
      }, 1000)
    }
  }

  /**
   * 默认的401处理逻辑 - 跳转到登录页
   */
  defaultUnauthorizedHandler() {
    // 清除本地存储的token等认证信息
    localStorage.removeItem('token')
    sessionStorage.removeItem('token')

    // 跳转到登录页面
    const loginPath = '/login'
    if (window.location.pathname !== loginPath) {
      // 保存当前页面路径，登录后可以跳转回来
      const redirectUrl = encodeURIComponent(window.location.href)
      window.location.href = `${loginPath}?redirect=${redirectUrl}`
    }
  }

  /**
   * 创建请求URL
   * @param {String} url - 请求URL
   * @returns {String} 完整URL
   */
  createUrl(url) {
    // 如果是完整URL则直接返回，否则拼接baseUrl
    return url.startsWith('http') ? url : `${this.baseUrl}${url}`
  }

  /**
   * 处理请求参数
   * @param {Object} params - 请求参数
   * @param {String} method - 请求方法
   * @returns {Object|String} 处理后的参数
   */
  handleParams(params, method) {
    if (method.toUpperCase() === 'GET') {
      // GET请求参数处理
      if (!params) return ''
      const queryString = Object.entries(params)
        .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
        .join('&')
      return queryString ? `?${queryString}` : ''
    } else {
      // 非GET请求参数处理
      return this.headers['Content-Type'] === 'application/json' ? JSON.stringify(params) : params
    }
  }

  /**
   * 处理响应
   * @param {Response} response - fetch响应对象
   * @returns {Promise} 处理后的响应数据
   */
  async handleResponse(response) {
    // 先检查HTTP状态码
    if (!response.ok) {
      // 401状态码特殊处理
      if (response.status === 401) {
        await this.handleUnauthorized()
        throw new Error('未授权，请重新登录')
      }
      if (response.status == 500) {
        message.error('服务器内部错误')
        throw new Error(`HTTP error! status: ${response.status}`)
      }
      throw new Error(`HTTP error! status: ${response.status}`)
    }

    const contentType = response.headers.get('content-type')
    let data

    if (contentType && contentType.includes('application/json')) {
      data = await response.json()
    } else {
      data = await response.text()
    }

    // 检查响应数据中的业务状态码（如果接口规范中有定义）
    if (data && typeof data === 'object' && data.code !== undefined) {
      // 假设业务代码401也表示未授权
      if (data.code === 401) {
        await this.handleUnauthorized()
        throw new Error(data.message || '未授权，请重新登录')
      }
    }

    return data
  }

  /**
   * 发起请求
   * @param {String} url - 请求URL
   * @param {Object} options - 请求选项
   * @param {String} options.method - 请求方法(GET, POST, PUT, DELETE等)
   * @param {Object} options.params - 请求参数
   * @param {Object} options.headers - 请求头
   * @param {Boolean} options.withCredentials - 是否携带凭证
   * @param {Number} options.timeout - 超时时间
   * @param {String} options.requestId - 请求ID，用于取消请求
   * @returns {Promise} 请求结果
   */
  async request(url, options = {}) {
    try {
      const {
        method = 'GET',
        params = {},
        headers = {},
        withCredentials = false,
        timeout = this.timeout,
        requestId
      } = options

      // 创建完整URL
      const requestUrl = this.createUrl(url)
      // 处理请求参数
      const paramsString = this.handleParams(params, method)
      const finalUrl = method.toUpperCase() === 'GET' ? `${requestUrl}${paramsString}` : requestUrl
      // 合并请求头
      const finalHeaders = { ...this.headers, ...headers }

      // 创建abort controller
      let abortController = null
      if (requestId) {
        abortController = new AbortController()
        this.abortControllers.set(requestId, abortController)
      }

      // 设置fetch选项
      const fetchOptions = {
        method,
        headers: finalHeaders,
        credentials: withCredentials ? 'include' : 'same-origin',
        signal: abortController ? abortController.signal : undefined
      }

      // 非GET请求设置body
      if (method.toUpperCase() !== 'GET') {
        fetchOptions.body = paramsString
      }

      // 应用请求拦截器
      for (const interceptor of this.requestInterceptors) {
        const result = interceptor(fetchOptions, finalUrl)
        if (result) {
          fetchOptions.headers = { ...fetchOptions.headers, ...result.headers }
        }
      }

      // 发送请求并处理响应
      const response = await Promise.race([
        fetch(finalUrl, fetchOptions),
        // 超时处理
        new Promise((_, reject) => {
          setTimeout(() => {
            if (requestId && this.abortControllers.has(requestId)) {
              this.abortControllers.get(requestId).abort()
              this.abortControllers.delete(requestId)
            }
            reject(new Error(`Request timeout after ${timeout}ms`))
          }, timeout)
        })
      ])

      // 处理响应
      let data = await this.handleResponse(response)

      // 应用响应拦截器
      for (const interceptor of this.responseInterceptors) {
        data = interceptor(data, response) || data
      }

      return data
    } catch (error) {
      // 可以在这里添加错误处理逻辑
      throw error
    } finally {
      // 请求完成后移除abort controller
      if (options.requestId) {
        this.abortControllers.delete(options.requestId)
      }
    }
  }

  /**
   * 取消请求
   * @param {String} requestId - 请求ID
   * @returns {Boolean} 是否取消成功
   */
  cancelRequest(requestId) {
    if (this.abortControllers.has(requestId)) {
      this.abortControllers.get(requestId).abort()
      this.abortControllers.delete(requestId)
      return true
    }
    return false
  }

  /**
   * GET请求
   * @param {String} url - 请求URL
   * @param {Object} params - 请求参数
   * @param {Object} options - 其他选项
   * @returns {Promise} 请求结果
   */
  get(url, params = {}, options = {}) {
    return this.request(url, { ...options, method: 'GET', params })
  }

  /**
   * POST请求
   * @param {String} url - 请求URL
   * @param {Object} data - 请求数据
   * @param {Object} options - 其他选项
   * @returns {Promise} 请求结果
   */
  post(url, data = {}, options = {}) {
    return this.request(url, { ...options, method: 'POST', params: data })
  }

  /**
   * PUT请求
   * @param {String} url - 请求URL
   * @param {Object} data - 请求数据
   * @param {Object} options - 其他选项
   * @returns {Promise} 请求结果
   */
  put(url, data = {}, options = {}) {
    return this.request(url, { ...options, method: 'PUT', params: data })
  }

  /**
   * DELETE请求
   * @param {String} url - 请求URL
   * @param {Object} params - 请求参数
   * @param {Object} options - 其他选项
   * @returns {Promise} 请求结果
   */
  delete(url, params = {}, options = {}) {
    return this.request(url, { ...options, method: 'DELETE', params })
  }
}

// 创建实例并导出
const fetchHttp = new FetchHttp()

// 默认添加一个401处理函数（用户可以根据需要覆盖）
fetchHttp.addUnauthorizedHandler(() => {
  // 清除认证信息
  removeToken()
  // 跳转到登录页
  const loginPath = '/login'
  window.location.href = `${loginPath}`
})

export default fetchHttp
