// @ts-ignore
const baseUrl = import.meta.env.VITE_BASE_URL
// @ts-ignore
const assetsUrl = import.meta.env.VITE_ASSETSURL

interface StorageInfo {
  keys: string[]
  currentSize: number
  limitSize: number
}

/**
 * 工具类 - 提供常用的工具方法
 * @class Tool
 */
class Tool {
  ICON_TYPES: { [key: string]: number }
  loadedFonts: Set<string>

  constructor() {
    // 图标类型映射
    this.ICON_TYPES = {
      NONE: 0,
      SUCCESS: 1,
      LOADING: 2,
    }

    // 字体加载状态缓存
    this.loadedFonts = new Set()
  }

  /**
   * 文字轻提示
   * @param {string} str 提示文字
   * @param {number} [icon=0] 提示icon (0: none, 1: success, 2: loading)
   * @param {number} [duration=1500] 提示时间(毫秒)
   */
  alert(str: string, icon: number = this.ICON_TYPES.NONE, duration: number = 1500): Promise<void> {
    return new Promise((resolve, reject) => {
      if (!str && str !== '0') {
        console.warn('alert方法需要提供提示文字')
        return
      }

      const iconMap: { [key: number]: string } = {
        [this.ICON_TYPES.NONE]: 'none',
        [this.ICON_TYPES.SUCCESS]: 'success',
        [this.ICON_TYPES.LOADING]: 'loading',
      }

      // @ts-ignore
      uni.showToast({
        title: String(str),
        // @ts-ignore
        icon: iconMap[icon] || 'none',
        mask: true,
        duration,
        success: () => {
          setTimeout(resolve, duration)
        },
        fail: reject,
      })
    })
  }

  /**
   * 显示loading加载
   * @param {string} [title=' '] 加载文案
   * @param {boolean} [mask=true] 是否显示遮罩
   */
  loading(title: string = ' ', mask: boolean = true): void {
    // @ts-ignore
    uni.showLoading({ title, mask })
  }

  /**
   * 关闭loading提示框
   */
  hideLoading(): void {
    // @ts-ignore
    uni.hideLoading()
  }

  /**
   * 统一处理URL格式，确保以/开头
   * @param {string} url 页面地址
   * @returns {string} 格式化后的URL
   * @private
   */
  _formatUrl(url: string): string {
    if (!url || typeof url !== 'string') {
      throw new Error('URL必须是字符串')
    }

    return url.startsWith('/') ? url : `/${url}`
  }

  /**
   * 可返回跳转（导航到新页面）
   * @param {string} url 页面地址
   */
  navigateTo(url: string): void {
    const formattedUrl = this._formatUrl(url)

    // @ts-ignore
    uni.navigateTo({
      url: formattedUrl,
      fail: (err: any) => {
        console.warn('navigateTo失败，尝试switchTab:', err)
        // @ts-ignore
        uni.switchTab({ url: formattedUrl })
      },
    })
  }

  /**
   * 不可返回跳转（重定向到新页面）
   * @param {string} url 页面地址
   */
  redirectTo(url: string): void {
    // @ts-ignore
    uni.redirectTo({ url: this._formatUrl(url) })
  }

  /**
   * 清除页面栈跳转（重新启动到新页面）
   * @param {string} url 页面地址
   */
  reLaunch(url: string): void {
    // @ts-ignore
    uni.reLaunch({ url: this._formatUrl(url) })
  }

  /**
   * 跳转tabBar页
   * @param {string} url 页面地址
   */
  switchTab(url: string): void {
    // @ts-ignore
    uni.switchTab({ url: this._formatUrl(url) })
  }

  /**
   * 返回上一页面或指定页面
   * @param {number} [delta=1] 返回的页面数
   * @param {string} [fallbackUrl='/pages/index/index'] 无上一页时的回退地址
   */
  navigateBack(delta: number = 1, fallbackUrl: string = '/pages/index/index'): void {
    // @ts-ignore
    const pages = getCurrentPages()

    if (pages.length <= 1) {
      console.warn('无上一页，使用回退地址')
      // @ts-ignore
      uni.reLaunch({ url: fallbackUrl })
    } else {
      // @ts-ignore
      uni.navigateBack({ delta })
    }
  }

  /**
   * 操作本地缓存
   * @param {string} key 缓存键值
   * @param {any} [value] 缓存数据，不传则为读取
   * @returns {any|undefined} 读取操作时返回数据
   */
  storage(key: string, value?: any): any {
    if (typeof key !== 'string') {
      throw new Error('key必须是字符串')
    }

    // 设置操作
    if (value !== undefined && value !== null) {
      // @ts-ignore
      uni.setStorageSync(key, value)
      return
    }

    // 读取操作
    if (key !== '#') {
      // @ts-ignore
      return uni.getStorageSync(key)
    }

    // 特殊操作
    if (key === '#') {
      // @ts-ignore
      uni.clearStorageSync()
    }
  }

  /**
   * 删除指定缓存
   * @param {string} key 要删除的缓存键
   */
  removeStorage(key: string): void {
    if (typeof key !== 'string') {
      throw new Error('key必须是字符串')
    }

    // @ts-ignore
    uni.removeStorageSync(key)
  }

  /**
   * 获取缓存信息
   * @returns {Object} 缓存信息
   */
  getStorageInfo(): StorageInfo {
    // @ts-ignore
    return uni.getStorageInfoSync()
  }

  /**
   * 复制文本到剪贴板
   * @param {string} data 要复制的文本
   * @returns {Promise<boolean>} 复制是否成功
   */
  async copy(data: string): Promise<boolean> {
    if (!data && data !== '0') {
      this.alert('暂无内容')
      return false
    }

    try {
      await new Promise((resolve, reject) => {
        // @ts-ignore
        uni.setClipboardData({
          data: String(data),
          success: resolve,
          fail: reject,
        })
      })

      this.alert('复制成功')
      return true
    } catch (error) {
      console.error('复制失败:', error)
      this.alert('复制失败，请重试')
      return false
    }
  }

  /**
   * 导入外部字体
   * @param {string} fontName 字体文件名（不含路径）
   * @returns {Promise<boolean>} 字体加载是否成功
   */
  async loadFont(fontName: string): Promise<boolean> {
    if (!fontName || typeof fontName !== 'string') {
      throw new Error('字体名称必须是字符串')
    }

    // 检查是否已加载过
    if (this.loadedFonts.has(fontName)) {
      return true
    }

    try {
      const fontFamily = fontName.replace(/\.[^/.]+$/, '') // 移除文件扩展名

      await new Promise((resolve, reject) => {
        // @ts-ignore
        uni.loadFontFace({
          family: fontFamily,
          source: `url(${assetsUrl}${fontName})`,
          global: true,
          success: resolve,
          fail: reject,
        })
      })

      this.loadedFonts.add(fontName)
      return true
    } catch (error) {
      console.error(`字体加载失败: ${fontName}`, error)
      return false
    }
  }

  /**
   * 保存图片到相册
   * @param {string} url 图片URL
   * @returns {Promise<boolean>} 保存是否成功
   */
  async saveImageToPhotos(url: string): Promise<boolean> {
    if (!url) {
      this.alert('图片地址不能为空')
      return false
    }

    try {
      // 检查权限
      const { authSetting } = await new Promise((resolve, reject) => {
        // @ts-ignore
        uni.getSetting({
          success: resolve,
          fail: reject,
        })
      }) as any

      if (!authSetting['scope.writePhotosAlbum']) {
        // 请求权限
        await new Promise((resolve, reject) => {
          // @ts-ignore
          uni.authorize({
            scope: 'scope.writePhotosAlbum',
            success: resolve,
            fail: reject,
          })
        })
      }

      // 获取图片信息
      const { path } = await new Promise((resolve, reject) => {
        // @ts-ignore
        uni.getImageInfo({
          src: url,
          success: resolve,
          fail: reject,
        })
      }) as any

      // 保存到相册
      await new Promise((resolve, reject) => {
        // @ts-ignore
        uni.saveImageToPhotosAlbum({
          filePath: path,
          success: resolve,
          fail: reject,
        })
      })

      this.alert('已保存到相册')
      return true
    } catch (error: any) {
      console.error('保存图片失败:', error)

      if (error.errMsg && error.errMsg.includes('auth')) {
        // 权限相关错误
        await new Promise(resolve => {
          // @ts-ignore
          uni.showModal({
            title: '保存失败',
            content: '请开启访问手机相册权限',
            showCancel: false,
            success: resolve,
          })
        })

        // @ts-ignore
        uni.openSetting()
      } else {
        this.alert('保存失败，请重试')
      }

      return false
    }
  }

  /**
   * 微信支付
   * @param {Object} paymentData 支付参数
   * @returns {Promise<Object>} 支付结果
   */
  requestPayment(paymentData: any): Promise<any> {
    return new Promise((resolve, reject) => {
      // @ts-ignore
      uni.requestPayment({
        provider: 'wxpay',
        ...paymentData,
        success: resolve,
        fail: reject,
      })
    })
  }
  
  upload(filePath: string): Promise<any> {
    return new Promise((resolve, reject) => {
      // @ts-ignore
      uni.uploadFile({
        url: `${baseUrl}file/upload`,
        fileType: 'image',
        header: {
          Authorization: `Bearer ${this.storage('token')}`,
        },
        filePath,
        name: 'file',
        success: ({ data }: any) => {
          resolve(JSON.parse(data))
        },
        fail: (error: any) => {
          reject(error)
        },
      })
    })
  }
}

// 创建单例并导出
export default new Tool()