/*
 * Copyright (c) 2018-2999 广州市蓝海创新科技有限公司 All rights reserved.
 *
 * https://www.mall4j.com/
 *
 * 未经允许，不可做商业用途！
 *
 * 版权所有，侵权必究！
 */

import http from '@/utils/http'
import { WKSDK, ConnectStatus } from 'wukongimjssdk'
// #ifdef H5
import ImageCompressor from 'compressorjs'
// #endif

let connectStatusListener = null

// 公共方法集
const util = {
  /**
   * 清除登录信息(请求未授权时)
   */
  clearLoginInfo: () => {
    uni.removeStorageSync('bbcToken_us')
    uni.removeStorageSync('bbcAuthorities')
  },
  /**
   * 选择的图片是否小于2M
   * @param {Array} tempFiles 上传的图片临时文件数组
   * @return {Boolean} 是否小于2M
   */
  lessThan2M: (tempFiles) => {
    let flag = true
    for (let i = 0; i < tempFiles.length; i++) {
      const file = tempFiles[i]
      if (file.size > 1024 * 1024 * 2) {
        uni.showToast({
          title: $t('tuPianDaXiaoBuNengChaoGuo_2m'),
          duration: 2000,
          icon: 'none'
        })
        flag = false
        break
      }
    }
    return flag
  },
  /**
   * 复制文本
   * @param content
   * @param success
   * @param error
   * @returns {*}
   */
  uniCopy: ({ content, success, error }) => {
    if (!content) return error($t('fuZhiDeNeiRongBuNengWeiKong'))
    content = typeof content === 'string' ? content : content.toString() // 复制内容，必须字符串，数字需要转换为字符串
    /**
     * 小程序端 和 app端的复制逻辑
     */
    // #ifndef H5
    uni.setClipboardData({
      data: content,
      success: function () {
        success($t('fuZhiChengGong'))
      },
      fail: function () {
        success($t('fuZhiShiBai'))
      }
    })
    // #endif

    /**
     * H5端的复制逻辑
     */
    // #ifdef H5
    if (!document.queryCommandSupported('copy')) { // 为了兼容有些浏览器 queryCommandSupported 的判断
      // 不支持
      error('浏览器不支持')
    }
    const textarea = document.createElement('textarea')
    textarea.value = content
    textarea.readOnly = 'readOnly'
    document.body.appendChild(textarea)
    textarea.select() // 选择对象
    textarea.setSelectionRange(0, content.length) // 核心
    const result = document.execCommand('copy') // 执行浏览器复制命令
    if (result) {
      success($t('fuZhiChengGong'))
    } else {
      error('复制失败，请检查h5中调用该方法的方式，是不是用户点击的方式调用的，如果不是请改为用户点击的方式触发该方法，因为h5中安全性，不能js直接调用！')
    }
    textarea.remove()
    // #endif
  },

  /**
   * 获取唯一值
   */
  getUuid: () => {
    const s = []
    const hexDigits = '0123456789abcdef'
    for (let i = 0; i < 36; i++) {
      s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1)
    }
    s[14] = '4' // bits 12-15 of the time_hi_and_version field to 0010
    s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1) // bits 6-7 of the clock_seq_hi_and_reserved to 01
    s[8] = s[13] = s[18] = s[23] = '-'

    const uuid = s.join('')
    return uuid
  },
  /**
   * 时间戳转化为年 月 日 时 分 秒
   * number: 传入时间戳
   * format：返回格式，支持自定义，但参数必须与formateArr里保持一致
   */
  tsToDate: (number, format) => {
    const formateArr = ['Y', 'M', 'D', 'h', 'm', 's']
    const returnArr = []

    const date = new Date(number)
    returnArr.push(date.getFullYear())
    returnArr.push(date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1)
    returnArr.push(date.getDate() < 10 ? '0' + date.getDate() : date.getDate())

    returnArr.push(date.getHours() < 10 ? '0' + date.getHours() : date.getHours())
    returnArr.push(date.getMinutes() < 10 ? '0' + date.getMinutes() : date.getMinutes())
    returnArr.push(date.getSeconds() < 10 ? '0' + date.getSeconds() : date.getSeconds())

    for (const i in returnArr) {
      format = format.replace(formateArr[i], returnArr[i])
    }
    return format
  },
  /**
   * 进行相隔时间判断
   *
   * true 删除显示时间
   * false 保留显示时间
   */
  timeBeApart: (uppTime, preTime) => {
    if (!uppTime) {
      return false
    }
    const dateDiff = preTime - uppTime// 时间差的毫秒数
    const dayDiff = Math.floor(dateDiff / (24 * 3600 * 1000))// 计算出相差天数
    const leave1 = dateDiff % (24 * 3600 * 1000) // 计算天数后剩余的毫秒数
    const hours = Math.floor(leave1 / (3600 * 1000))// 计算出小时数
    // 计算相差分钟数
    const leave2 = leave1 % (3600 * 1000) // 计算小时数后剩余的毫秒数
    const minutes = Math.floor(leave2 / (60 * 1000))// 计算相差分钟数
    return !(dayDiff >= 1 || hours >= 1 || minutes > 4)
  },
  /**
   * @param {Array} data 接收数据
   * @param {String} children  子属性名称
   * @returns Array 返回数据
   */
  treeDataTranslate: (data, children = 'children') => {
    const res = []
    list(data, children)

    function list (arr, children) {
      for (let i = 0; i < arr.length; i++) {
        res.push(arr[i])
        if (arr[i][children]) {
          list(arr[i][children], children)
          res[i][children] = null
        }
      }
    }

    return res
  },
  /**
   * @param {Number} x 原价格
   * @returns String 返回数据
   */
  priceAdd0: (x) => {
    const f = parseFloat(x) // 解析一个字符串，返回一个浮点数；
    let s = f.toString() // 把一个逻辑值转换为字符串，并返回结果；
    let rs = s.indexOf('.') // 返回某个指定的字符串值在字符串中首次出现的位置；如果字符串值没有出现，返回-1；

    // 没有小数点时：
    if (rs < 0) {
      rs = s.length
      s += '.'
    }
    while (s.length <= rs + 2) {
      s += '0'
    }
    return s
  },
  /**
   * 获取上的菜单列表 存在本地 shopMenuList
   */
  shopMenuList: () => {
    return new Promise((resolve) => {
      http.request({
        url: '/sys/shopMenu/nav',
        method: 'GET'
      }).then(({ data: res }) => {
        uni.setStorageSync('bbcAuthorities', res.authorities)
        resolve()
      })
    })
  },
  /**
   * @param {*} params  授权表示符
   * @returns {Boolean}  是否访问该页面权限
   *
   */
  isAuthorities: (params) => {
    const authorities = uni.getStorageSync('bbcAuthorities') ? uni.getStorageSync('bbcAuthorities') : []
    return authorities.includes(params)
  },
  /**
   * 文件地址校验
   * @param fileUrl 获取到的文件路径
   */
  checkFileUrl: (fileUrl) => {
    if (!fileUrl) return ''
    if (fileUrl === '/static/images/def.png') return fileUrl
    return fileUrl.indexOf('http') > -1 ? fileUrl : import.meta.env.VITE_APP_RESOURCES_URL + fileUrl
  },
  chooseImage ({ count = 1, sourceType, sizeType, isImFile = false, isCallUpload = true }) {
    return new Promise((resolve) => {
      const resData = []
      const obj = { src: '', quality: 0.2 }
      const appType = uni.getStorageSync('bbcAppType')
      uni[appType === 1 ? 'chooseMedia' : 'chooseImage']({
        count: count || 1,
        sizeType: sizeType || ['compressed'],
        sourceType: sourceType || ['album'],
        success: (res) => {
          let tempFilePaths = res.tempFilePaths
          // #ifdef MP-WEIXIN
          tempFilePaths = res.tempFiles
          // #endif
          tempFilePaths.forEach((item, index) => {
            // 限制图片上传格式
            let _type = res.tempFiles[index].type
            // #ifdef MP-WEIXIN
            _type = item.tempFilePath.split('.')[1]
            // #endif
            // #ifdef APP-PLUS
            obj.src = item
            _type = item.substring(item.lastIndexOf('.') + 1)
            // #endif
            const contentType = _type.indexOf('image/') > -1 ? _type : 'image/' + _type
            if (_type.indexOf('png') === -1 && _type.indexOf('jpg') === -1 && _type.indexOf('jpeg') === -1) {
              uni.showToast({
                title: $t('shangChuanTuPianGeShiBuZhengQueQingZhongXinShangChuan'),
                icon: 'none'
              })
              return
            }

            const getPreSignUrlParams = { fileName: undefined, isImFile }
            const uploadImgParams = { isCallUpload, index, res: JSON.parse(JSON.stringify(res)), resData, contentType }
            // #ifdef MP-WEIXIN
            obj.src = item.tempFilePath
            getPreSignUrlParams.fileName = res.tempFiles[index].tempFilePath
            // #endif
            // #ifdef H5
            obj.src = item
            getPreSignUrlParams.fileName = res.tempFiles[index].name
            // #endif

            uni.showLoading({
              mask: true
            })

            // 压缩图片回调
            util.getCompressedFileInfo(res.tempFiles[index]).then(async (compressFileInfo) => {
              const { filePath, size } = compressFileInfo
              // 更新上传文件的信息
              uploadImgParams.res.tempFiles[index].size = size
              // #ifdef APP-PLUS
              const appFileBuffer = await util.plusIo(filePath)
              getPreSignUrlParams.fileName = res.tempFiles[index].path
              // #endif

              // 上传方法
              const upload = (uploadImgParams, getPreSignUrlRes, uploadFileObj) => {
                util.uploadImg(Object.assign(uploadImgParams, { data: getPreSignUrlRes, requestRes: uploadFileObj })).then(() => {
                  resolve(resData)
                  uni.hideLoading()
                })
              }

              // 请求获取上传文件url
              util.getPreSignUrl(getPreSignUrlParams).then(({ data }) => {
                // #ifdef H5
                uni.request({
                  url: filePath,
                  method: 'GET',
                  responseType: 'arraybuffer',
                  success: (requestRes) => {
                    upload(uploadImgParams, data, requestRes)
                  }
                })
                // #endif

                // #ifdef MP-WEIXIN
                uni.getFileSystemManager().readFile({
                  filePath,
                  success: (requestRes) => {
                    upload(uploadImgParams, data, requestRes)
                  },
                  fail: (readFileFailMsg) => {
                    console.error('readFileFailMsg', readFileFailMsg)
                  }
                })
                // #endif

                // #ifdef APP-PLUS
                const requestRes = { data: appFileBuffer }
                upload(uploadImgParams, data, requestRes)
                // #endif
              })
            }).catch(failMsg => {
              console.error('getCompressedFileInfo failMsg', failMsg)
              uni.hideLoading()
            })
          })
        },
        fail: failMsg => {
          // eslint-disable-next-line no-console
          console.log('选择图片失败', failMsg)
        }
      })
    })
  },
  uploadImg: (params) => {
    const { data, requestRes, res, resData, isCallUpload, index, contentType } = params
    return new Promise((resolve) => {
      uni.request({
        url: data.preSignUrl,
        method: 'PUT',
        header: {
          'Content-Type': contentType
        },
        data: requestRes.data,
        success: function () {
          resData.push({ filePath: data.filePath, fileId: data.fileId, fileSize: res.tempFiles[index].size })
          if (res.tempFiles.length === resData.length) {
            if (isCallUpload) {
              util.uploadSuccess(resData).then(() => {
                resolve(resData)
              })
            } else {
              resolve(resData)
            }
          }
        }
      })
    })
  },
  plusIo: (filePath) => {
    return new Promise((resolve) => {
      plus.io.resolveLocalFileSystemURL(filePath, async function (entry) {
        entry.file(function (file) { // 读取文件
          const reader = new plus.io.FileReader()
          reader.readAsDataURL(file) // 以URL格式读取文件
          reader.onload = function () {
            const base64 = this.result.split(',')[1] // 获取base64字符串
            const buffer = uni.base64ToArrayBuffer(base64) // 转换为arrayBuffer格式
            resolve(buffer)
          }
        })
      })
    })
  },
  uploadSuccess (resData) {
    return http.request({
      url: '/admin/file/uploadSuccess',
      method: 'PUT',
      data: resData
    })
  },
  getPreSignUrl (data) {
    return http.request({
      url: '/admin/file/getPreSignUrl',
      method: 'GET',
      data
    })
  },
  pageBack: () => {
    // #ifdef H5
    history.back()
    // #endif
    // #ifndef H5
    uni.navigateBack({
      delta: 1
    })
    // #endif
  },

  /**
   * tabbar国际化
   */
  transTabbar: () => {
    const tabBarList = [
      {
        index: 0,
        text: $t('dianPuShouYe')
      }, {
        index: 1,
        text: $t('xiaoXiHeZi')
      }, {
        index: 2,
        text: $t('shangPinGaiKuang-0')
      }, {
        index: 3,
        text: $t('dianPuSheZhi')
      }
    ]
    for (let i = 0; i < tabBarList.length; i++) {
      nextTick(() => {
        uni.setTabBarItem({
          index: tabBarList[i].index,
          text: tabBarList[i].text
        })
      })
    }
  },
  /**
   * 压缩图片文件
   * @param {file} file 将要压缩的文件
   * @returns {Promise} 压缩后的文件信息；(H5端返回base64格式图片)
   */
  getCompressedFileInfo: (file) => {
    return new Promise((resolve, reject) => {
      // #ifdef H5
      util.compressImage(file).then((compressFile) => {
        const reader = new FileReader()
        reader.onload = (event) => {
          const filePath = event.target.result // Base64 字符串
          resolve({ filePath, size: compressFile.size })
        }
        reader.onerror = (error) => {
          console.error('转换失败：', error)
          reject(error)
        }
        reader.readAsDataURL(new File([compressFile], file.name, { type: file.type }))
      })
      // #endif

      // #ifdef MP-WEIXIN || APP-PLUS
      const path = file.tempFilePath || file.path
      uni.getImageInfo({
        src: path,
        success: (imgInfo) => {
          uni.compressImage({
            src: path,
            quality: 80,
            compressedWidth: imgInfo.width > 1080 ? 1080 : imgInfo.width,
            success: (compressImageRes) => {
              const filePath = compressImageRes.tempFilePath
              // #ifdef MP-WEIXIN || APP-PLUS
              const uniApi = uni.getStorageSync('bbcAppType') === 1 ? uni.getFileSystemManager().getFileInfo : uni.getFileInfo
              uniApi({
                filePath,
                success: (fileInfoRes) => {
                  resolve({ filePath, size: fileInfoRes.size })
                },
                fail: (error) => {
                  console.error('getFileInfo fail', error)
                  reject(error)
                }
              })
              // #endif
            },
            fail: (compressErrMsg) => {
              console.error('compressErrMsg', compressErrMsg)
              reject(compressErrMsg)
            }
          })
        },
        fail: (error) => {
          console.error('getImgInfo fail', error)
          reject(error)
        }
      })
      // #endif
    })
  },
  /**
   * H5端的压缩图片
   * @param {File} file - 要压缩的图片文件
   * @returns {Promise<File>} - 压缩后的图片文件
   */
  compressImage: async (file) => {
    const isSize = file.size / 1024 < 512
    if (isSize) {
      return file
    }
    // 0.5m~5m，从0.8开始循环。5m~10m，从0.6开始循环。10m以上就直接0.4。
    // 最低使用0.4
    let quality
    if (file.size / 1024 / 1024 < 5) {
      quality = 0.8
    } else if (file.size / 1024 / 1024 < 10) {
      quality = 0.6
    } else {
      quality = 0.4
    }
    try {
      let resultBlob
      let index = true
      while (index) {
        resultBlob = await util.ImageCompressorFn(file, quality)
        if (resultBlob.size / 1024 < 512 || quality <= 0.4) {
          index = false
        } else {
          quality = (quality * 10 - 2) / 10
        }
      }
      return new File([resultBlob], { type: file.type })
    } catch (error) {
      console.error('图片压缩失败:', error)
      // 返回原文件
      return file
    }
  },

  ImageCompressorFn: (file, quality = 0.6) => {
    return new Promise((resolve, reject) => {
      // eslint-disable-next-line no-new
      new ImageCompressor(file, {
        quality,
        convertSize: 512000,
        maxWidth: 1080,
        success (result) {
          resolve(result)
        },
        error (err) {
          reject(err)
        }
      })
    })
  },
  getWuKongIm: () => {
    WKSDK.shared().disconnect()
    const params = {
      url: '/shop/wuKongIm/registerOrLogin',
      method: 'POST'
    }
    http.request(params).then(({ data }) => {
      if (data) {
        const config = WKSDK.shared().config
        config.addr = import.meta.env.VITE_APP_WS_IM_API
        config.uid = data.uid // 用户uid（需要在悟空通讯端注册过）
        config.token = data.token// 用户token （需要在悟空通讯端注册过）
        config.debug = true
        config.deviceFlag = 1
        WKSDK.shared().config = config
        WKSDK.shared().connect()
        WKSDK.shared().connectManager.removeConnectStatusListener(connectStatusListener)
        // 监听连接状态
        connectStatusListener = (status) => {
          getApp().globalData.connectSuccess = status === ConnectStatus.Connected
          if (status === ConnectStatus.Connected) {
            // eslint-disable-next-line no-console
            console.log('连接成功!')
          } else {
            // eslint-disable-next-line no-console
            console.log('连接断开~')
          }
        }
        WKSDK.shared().connectManager.addConnectStatusListener(connectStatusListener)
      }
    })
  }
}

export default util
