/**
 * HTTP请求封装
 * 基于uni.request进行二次封装
 */

import config from '@/config/api.config.js'

class Request {
  constructor() {
    this.baseURL = config.baseURL
    this.timeout = config.timeout
    this.isRedirecting = false // 防止重复跳转登录页
  }

  /**
   * 核心请求方法
   * @param {Object} options 请求配置
   * @returns {Promise}
   */
  request(options) {
    // 显示loading
    if (options.loading !== false) {
      uni.showLoading({
        title: options.loadingText || '加载中...',
        mask: true
      })
    }

    // 打印请求信息（仅POST请求）
    if (options.method === 'POST') {
      console.log('=== HTTP POST 请求 ===')
      console.log('URL:', this.baseURL + options.url)
      console.log('Method:', options.method)
      console.log('请求数据:', options.data)
      console.log('请求头:', this.getHeaders(options.header))
    }

    return new Promise((resolve, reject) => {
      uni.request({
        url: this.baseURL + options.url,
        method: options.method || 'GET',
        data: options.data || {},
        header: this.getHeaders(options.header),
        timeout: options.timeout || this.timeout,
        success: (res) => {
          // 隐藏loading
          if (options.loading !== false) {
            uni.hideLoading()
          }

          console.log('=== HTTP 响应 ===')
          console.log('状态码:', res.statusCode)
          console.log('响应数据:', res.data)

          // 处理响应
          this.handleResponse(res, resolve, reject)
        },
        fail: (err) => {
          // 隐藏loading
          if (options.loading !== false) {
            uni.hideLoading()
          }

          console.log('=== HTTP 请求失败 ===')
          console.log('错误信息:', err)

          // 处理错误
          this.handleError(err, reject)
        }
      })
    })
  }

  /**
   * 获取请求头
   * @param {Object} customHeader 自定义请求头
   * @returns {Object}
   */
  getHeaders(customHeader = {}) {
    // 获取token - 使用access_token作为key
    const token = uni.getStorageSync('access_token') || ''

    return {
      'Content-Type': 'application/json',
      'Blade-Auth': token ? `bearer ${token}` : '',
      'Tenant-Id': '000000',
      ...customHeader
    }
  }

  /**
   * 处理响应数据
   * @param {Object} res 响应对象
   * @param {Function} resolve Promise resolve
   * @param {Function} reject Promise reject
   */
  handleResponse(res, resolve, reject) {
    const data = res.data

    // 判断HTTP状态码 - 特别处理401
    if (res.statusCode === 401) {
      this.handleTokenExpired()
      reject({
        statusCode: 401,
        code: 401,
        message: '未登录或登录已过期'
      })
      return
    }

    // 其他HTTP错误状态码
    if (res.statusCode < 200 || (res.statusCode >= 300 && res.statusCode !== 304)) {
      this.showError('网络请求失败')
      reject({
        statusCode: res.statusCode,
        code: res.statusCode,
        message: '网络请求失败'
      })
      return
    }

    // 特殊处理：OAuth2 token接口直接返回数据（有access_token字段）
    if (data.access_token) {
      resolve(data)
      return
    }

    // 判断业务状态码
    if (data.code === 200 || data.success === true) {
      // 请求成功，返回数据
      resolve(data.data)
    } else {
      // 业务错误处理
      const errorMsg = data.msg || data.message || data.error_description || '请求失败'

      // 特殊错误码处理
      if (data.code === 401 || data.code === 403) {
        // token过期或无权限
        this.handleTokenExpired()
      }

      this.showError(errorMsg)
      reject({
        statusCode: res.statusCode,
        code: data.code,
        message: errorMsg,
        data: data.data
      })
    }
  }

  /**
   * 处理请求错误
   * @param {Object} err 错误对象
   * @param {Function} reject Promise reject
   */
  handleError(err, reject) {
    console.error('请求失败:', err)
    console.error('请求URL:', this.baseURL)

    let message = '网络请求失败'

    if (err.errMsg) {
      if (err.errMsg.includes('timeout')) {
        message = '请求超时，请检查网络'
      } else if (err.errMsg.includes('fail')) {
        message = '网络连接失败，请检查服务器地址'
      }
    }

    this.showError(message)
    reject({
      code: undefined,
      message: '请求失败',
      data: undefined,
      error: err,
      url: this.baseURL
    })
  }

  /**
   * 显示错误提示
   * @param {String} message 错误信息
   */
  showError(message) {
    uni.showToast({
      title: message,
      icon: 'none',
      duration: 2000
    })
  }

  /**
   * 处理token过期
   */
  handleTokenExpired() {
    console.log('=== handleTokenExpired 被调用 ===')
    console.log('isRedirecting:', this.isRedirecting)

    // 防止重复跳转
    if (this.isRedirecting) {
      console.log('已经在跳转中，跳过')
      return
    }
    this.isRedirecting = true

    console.log('开始清除认证信息')
    // 清除所有认证信息
    uni.removeStorageSync('access_token')
    uni.removeStorageSync('refresh_token')
    uni.removeStorageSync('userInfo')
    console.log('认证信息已清除')

    // 提示用户
    console.log('显示Toast提示')
    uni.showToast({
      title: '登录已过期，请重新登录',
      icon: 'none',
      duration: 1500
    })

    // 立即跳转，不等待Toast
    console.log('准备跳转到登录页')

    // 获取当前页面路径
    const pages = getCurrentPages()
    console.log('当前页面栈:', pages)
    const currentPage = pages[pages.length - 1]
    const currentRoute = currentPage ? currentPage.route : ''

    console.log('当前页面路由:', currentRoute)

    // 如果当前不在登录页，才跳转
    if (currentRoute !== 'pages/login/login') {
      console.log('开始执行跳转...')

      // 使用 setTimeout 确保在下一个事件循环执行
      setTimeout(() => {
        this.isRedirecting = false

        uni.reLaunch({
          url: '/pages/login/login',
          success: () => {
            console.log('✅ reLaunch 跳转成功')
          },
          fail: (err) => {
            console.error('❌ reLaunch 失败:', err)
            // 如果reLaunch失败，尝试使用redirectTo
            uni.redirectTo({
              url: '/pages/login/login',
              success: () => {
                console.log('✅ redirectTo 跳转成功')
              },
              fail: (err2) => {
                console.error('❌ redirectTo 也失败:', err2)
                // 最后尝试navigateTo
                uni.navigateTo({
                  url: '/pages/login/login',
                  success: () => {
                    console.log('✅ navigateTo 跳转成功')
                  },
                  fail: (err3) => {
                    console.error('❌ navigateTo 也失败:', err3)
                    console.error('所有跳转方式都失败了！')
                  }
                })
              }
            })
          }
        })
      }, 100)
    } else {
      console.log('当前已在登录页，不需要跳转')
      this.isRedirecting = false
    }
  }

  /**
   * GET请求
   * @param {String} url 请求地址
   * @param {Object} data 请求参数
   * @param {Object} options 额外配置
   * @returns {Promise}
   */
  get(url, data = {}, options = {}) {
    return this.request({
      url,
      method: 'GET',
      data,
      ...options
    })
  }

  /**
   * POST请求
   * @param {String} url 请求地址
   * @param {Object|String} data 请求参数（可以是对象或字符串）
   * @param {Object} options 额外配置
   * @returns {Promise}
   */
  post(url, data = {}, options = {}) {
    return this.request({
      url,
      method: 'POST',
      data,
      ...options
    })
  }

  /**
   * PUT请求
   * @param {String} url 请求��址
   * @param {Object} data 请求参数
   * @param {Object} options 额外配置
   * @returns {Promise}
   */
  put(url, data = {}, options = {}) {
    return this.request({
      url,
      method: 'PUT',
      data,
      ...options
    })
  }

  /**
   * DELETE请求
   * @param {String} url 请求地址
   * @param {Object} data 请求参数
   * @param {Object} options 额外配置
   * @returns {Promise}
   */
  delete(url, data = {}, options = {}) {
    return this.request({
      url,
      method: 'DELETE',
      data,
      ...options
    })
  }

  /**
   * 文件上传
   * @param {String} url 上传地址
   * @param {String} filePath 文件路径
   * @param {Object} formData 额外数据
   * @returns {Promise}
   */
  upload(url, filePath, formData = {}) {
    uni.showLoading({
      title: '上传中...',
      mask: true
    })

    return new Promise((resolve, reject) => {
      uni.uploadFile({
        url: this.baseURL + url,
        filePath,
        name: 'file',
        formData,
        header: this.getHeaders(),
        success: (res) => {
          uni.hideLoading()

          const data = JSON.parse(res.data)
          if (data.code === 200) {
            resolve(data.data)
          } else {
            this.showError(data.msg || '上传失败')
            reject(data)
          }
        },
        fail: (err) => {
          uni.hideLoading()
          this.showError('上传失败')
          reject(err)
        }
      })
    })
  }
}

// 导出实例
export default new Request()
