import { UploadTask } from '@tarojs/taro';

import http from '@/http';
import { API } from '@/http/api';
import { logWithPrefix } from '@/utils/common';

type RegionCode = 'ECN' | 'NCN' | 'SCN' | 'NA' | 'ASG' | '';

interface Config {
  token: string;
  bucket: string;
  path: string;
  uploadUrl?: string;
}

const log = logWithPrefix('qiniu-upload');

// https://github.com/gpake/qiniu-wxapp-sdk
class QiniuUpload {
  // bucket 所在区域。ECN, SCN, NCN, NA, ASG，分别对应七牛云的：华东，华南，华北，北美，新加坡 5 个区域
  private qiniuRegion: RegionCode = 'ECN';

  private config: Config | null = null;

  private getUploadUrl() {
    let uploadURL: string;
    switch (this.qiniuRegion) {
      case 'NCN':
        uploadURL = 'https://up-z1.qiniup.com';
        break;
      case 'SCN':
        uploadURL = 'https://up-z2.qiniup.com';
        break;
      case 'NA':
        uploadURL = 'https://up-na0.qiniup.com';
        break;
      case 'ASG':
        uploadURL = 'https://up-as0.qiniup.com';
        break;
      case 'ECN':
      default:
        uploadURL = 'https://up-z0.qiniup.com';
        break;
    }
    return uploadURL;
  }

  private requestUploadConfig = async () => {
    this.config = await http.post<Config>(API.GET_QI_NIU_TOKEN);
    return this.config;
  };

  private getRandomFileName = (length: number = 32) => {
    const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    let result = '';

    // 结合时间戳
    const timestamp = Date.now().toString(36); // 将时间戳转换为36进制
    result += timestamp;

    // 随机补全到指定长度
    while (result.length < length) {
      const randomIndex = Math.floor(Math.random() * characters.length);
      result += characters[randomIndex];
    }

    // 截取到指定长度
    return result.substring(0, length);
  };

  init = () => {
    this.requestUploadConfig();
  };

  upload = async (filePath: string, onProgress?: UploadTask.OnProgressUpdateCallback, prefixName?: string) => {
    let config = this.config;
    if (!config) {
      config = await this.requestUploadConfig();
    }

    const { token, bucket, path: folderPath } = config;
    const fileName = `${prefixName ? `${prefixName}-` : ''}${this.getRandomFileName()}`;
    const url = config.uploadUrl || this.getUploadUrl();

    const formData = {
      token,
      bucket,
      key: `${folderPath}${fileName}`,
    };

    log('upload fileName', fileName);

    const result = await http.upload<{ hash: string; key: string }>(url, {
      filePath,
      name: 'file',
      formData,
      onProgress,
    });
    log('upload result:', result);
    return result.key;
  };
}

const qiniuUpload = new QiniuUpload();

export default qiniuUpload;
