/**
 * 网络请求工具类
 * 封装统一的网络请求方法
 */

import EnvConfig from '@/common/env.js'
import md5 from 'js-md5'
import ConfigManager from '@/common/config.js'
import { apiWhiteList } from '@/common/config.js'
import RouterManager from '@/common/router.js'
class RequestManager {
  /**
   * 判断URL是否在白名单中
   * @param {String} url 请求地址
   * @returns {Boolean} 是否在白名单中
   */
  static isUrlInWhitelist(url) {
    // let iswx = ConfigManager.GetVersion();
    
    // // 根据版本使用不同的白名单
    // if (!iswx) {
    //   // 非微信版本只允许 login_record
    //   return apiWhiteList.includes('login_record') && url.indexOf('login_record') > -1;
    // }
    
    // 检查URL是否包含白名单中的任一项
    return apiWhiteList.some(whiteItem => url.indexOf(whiteItem) > -1);
  }

  /**
   * 生成唯一的nonce值
   * @returns {String} nonce值
   */
  static generateNonce() {
    return md5(Date.now() + Math.random().toString(36).substring(2, 15));
  }

  /**
   * 发送网络请求
   * @param {Object} param 请求参数
   * @param {String} param.url 请求地址
   * @param {Object} param.data 请求数据
   * @param {Function} param.success 成功回调
   * @param {Function} param.fail 失败回调
   * @param {Function} param.complete 完成回调
   * @param {Boolean} param.Loading 是否显示加载提示
   * @param {String} backpage 返回页面
   * @param {String} backtype 返回类型
   * @returns {Promise} 返回请求Promise
   */
  static request(param, backpage, backtype) {

    return new Promise((resolve, reject) => {
      // 参数检查
      if (!param || typeof param !== 'object') {
        reject(new Error('请求参数错误'))
        return
      }

      uni.getNetworkType({
        success: function (res) {
          if (res.networkType == 'none') {
            uni.showToast({
              title: '网络连接异常，请检查网络',
              icon: 'none'
            })
            reject(new Error('网络连接异常'))
            return
          }
        }
      })

      const url = param.url || ''
      const method = param.method || 'POST'
      const data = param.data || {}
      const Loading = param.Loading || false
      const token = uni.getStorageSync('token')
      let client = ""

      // #ifdef H5
      client = "h5"
      // #endif

      // 获取API基础URL
      const apiBaseUrl = EnvConfig.apiBaseUrl

      // 拼接完整请求地址，确保URL格式正确
      let requestUrl = ''

      if (url.startsWith('http://') || url.startsWith('https://')) {
        // 如果是完整的URL，直接使用
        requestUrl = url
      } else {
        // 否则拼接基础URL和相对路径
        // 确保基础URL以/结尾，而请求路径不以/开头
        const baseUrlWithSlash = apiBaseUrl.endsWith('/') ? apiBaseUrl : apiBaseUrl + '/'
        const path = url.startsWith('/') ? url.substring(1) : url
        requestUrl = baseUrlWithSlash + path
      }

      console.log('请求URL:', requestUrl)

      // 使用正则表达式从URL中提取主机名
      const hostRegex = /^(?:https?:\/\/)?([^\/]+)/i
      const matches = requestUrl.match(hostRegex)
      const host = matches && matches[1] ? matches[1] : 'localhost'

      let header = {}

      // 添加签名和防重放攻击参数
      // 1. 添加时间戳
      data.timestamp = Math.floor(Date.now() / 1000)
      // 2. 添加nonce随机字符串
      data.nonce = RequestManager.generateNonce()

      if (method.toUpperCase() == 'POST') {
        // 按照键名对参数进行排序
        const sortedParams = {}
        Object.keys(data).sort().forEach(key => {
          sortedParams[key] = data[key]
        })

        // 组合参数为字符串
        let signStr = ''
        for (const key in sortedParams) {
          if (typeof sortedParams[key] === 'object') {
            signStr += key + '=' + JSON.stringify(sortedParams[key]) + '&'
          } else {
            signStr += key + '=' + sortedParams[key] + '&'
          }
        }

        // 获取时间戳，组合为密钥
        const timestamp = data.timestamp
        const appSecret = host + timestamp

        // 添加密钥并去除最后的&
        signStr = signStr.substring(0, signStr.length - 1) + appSecret
        console.log('签名字符串:', signStr)

        // 使用MD5生成签名
        const sign = md5(signStr)
        data.sign = sign

        header = {
          'content-type': 'application/x-www-form-urlencoded',
          client: client,
          token: token,
          adid: uni.getStorageSync('_ad_id'),
          clickid: uni.getStorageSync('_click_id')
        }
      } else {
        // GET请求，添加签名
        // 按照键名对参数进行排序
        const sortedParams = {}
        Object.keys(data).sort().forEach(key => {
          sortedParams[key] = data[key]
        })

        // 组合参数为字符串
        let signStr = ''
        for (const key in sortedParams) {
          signStr += key + '=' + sortedParams[key] + '&'
        }

        // 获取时间戳，组合为密钥
        const timestamp = data.timestamp
        const appSecret = host + timestamp

        // 添加密钥并去除最后的&
        signStr = signStr.substring(0, signStr.length - 1) + appSecret
        console.log('签名字符串:', signStr)

        // 使用MD5生成签名
        const sign = md5(signStr)

        // 添加签名到请求参数
        data.sign = sign

        header = {
          'content-type': 'application/json',
          token: token,
          client: client,
        }
      }

      // 显示加载提示
      if (!Loading) {
        uni.showLoading({
          title: '加载中...'
        })
      }

      // 发起网络请求
      uni.request({
        url: requestUrl,
        method: method.toUpperCase(),
        header: header,
        data: data,
        success: res => {
          console.log("res.data.status", res.data.status)
          var pages = getCurrentPages()
          if (res.data.status == 1) {
            // 请求成功
            resolve(res.data)
          } else if (res.data.status == 2222) {
            // 特殊状态码处理
            resolve(res.data)
          } else if (res.data.status == -9) {
            let pages = getCurrentPages()
            console.log(pages[pages.length - 1].route)
            setTimeout(() => {
              uni.showToast({
                title: res.data.msg,
                icon: 'none',
                success() {
                  setTimeout(() => {
                    // #ifdef H5
                    uni.navigateTo({
                      url: '/pages/user/bangdingweb'
                    })
                    // #endif
                    // #ifdef MP-WEIXIN
                    uni.navigateTo({
                      url: '/pages/user/bangding'
                    })
                    // #endif
                  }, 1500)
                }
              })
            }, 100)
            reject(res.data)
          } else if (res.data.status == 0) {
            setTimeout(function () {
              uni.showToast({
                title: res.data.msg,
                icon: 'none'
              })
            }, 100)
            
            reject(res.data)
          } else if (res.data.status < 0) {
            var pages = getCurrentPages()
            // 获取当前页面路径和参数
            var currentPage = pages[pages.length - 1];
            if (currentPage) {
              var currentRoute = currentPage.route;
              var currentParams = currentPage.options || {};
              
              // 只有非登录页面才保存重定向信息
              if (currentRoute && currentRoute !== 'pages/user/login') {
                // 构建完整的重定向URL
                var redirectPath = '/' + currentRoute;
                
                // 如果有参数，拼接参数
                if (Object.keys(currentParams).length > 0) {
                  var paramString = Object.keys(currentParams)
                    .map(key => `${encodeURIComponent(key)}=${encodeURIComponent(currentParams[key])}`)
                    .join('&');
                  redirectPath += '?' + paramString;
                }
                
                // 保存重定向URL到缓存
                console.log('保存重定向URL:', redirectPath);
                uni.setStorageSync('redirect', redirectPath);
              }
            }
            
            console.log(requestUrl);
            if (RequestManager.isUrlInWhitelist(requestUrl)) {
              reject(res.data)
              return;
            }
            setTimeout(() => {
              uni.showToast({
                title: '请先登录',
                icon: 'none'
              })
            }, 100)
            
            // 使用新的路由守卫方法进行跳转
            RouterManager.navigateTo('/pages/user/login', {}, 'navigateTo')
              .catch(err => {
                console.error('登录页面跳转失败:', err);
              });
            
            reject(res.data)
          } else {
            reject(res.data)
          }
          typeof param.success == 'function' && param.success(res.data)
        },
        fail: e => {
          console.error('网络请求失败:', e)
          uni.showToast({
            title: e.errMsg || '请求失败',
            icon: 'none'
          })
          typeof param.fail == 'function' && param.fail(e)
          reject(e)
        },
        complete: () => {
          uni.hideLoading()
          typeof param.complete == 'function' && param.complete()
        }
      })
    })
  }

  /**
   * 发送GET请求
   * @param {String} url 请求地址
   * @param {Object} data 请求参数
   * @param {Boolean} showLoading 是否显示加载提示
   * @returns {Promise} 返回请求Promise
   */
  static get(url, data = {}, showLoading = true) {
    return this.request({
      url,
      data,
      method: 'GET',
      Loading: !showLoading
    })
  }

  /**
   * 发送POST请求
   * @param {String} url 请求地址
   * @param {Object} data 请求参数
   * @param {Boolean} showLoading 是否显示加载提示
   * @returns {Promise} 返回请求Promise
   */
  static post(url, data = {}, showLoading = true) {
    return this.request({
      url,
      data,
      method: 'POST',
      Loading: !showLoading
    })
  }
}

export default RequestManager; 