import request from '@/utils/request';
import * as qiniu from 'qiniu-js';

/**
 * 获取存储配置
 * @returns {Promise<{storageType: string, qiniuDomain?: string, qiniuRegion?: string}>}
 */
export async function getStorageConfig() {
  const res = await request({
    url: '/platform/storage/config',
    method: 'get',
  });
  if (res?.code === 200) {
    return res.data || { storageType: 'local' };
  }
  return { storageType: 'local' };
}

/**
 * 获取七牛云上传凭证
 * @returns {Promise}
 */
export async function getQiniuToken() {
  return request({
    url: '/platform/qiniu/token',
    method: 'get',
  });
}

/**
 * 保存文件记录到数据库
 * @param {Object} data 文件信息
 * @returns {Promise}
 */
export async function saveFileRecord(data) {
  return request({
    url: '/platform/qiniu/save',
    method: 'post',
    data,
  });
}

/**
 * 上传文件（自动选择本地或七牛云）
 * @param {File} file 文件对象
 * @param {Object} options 配置选项
 * @param {number} [options.cate] 文件分类
 * @param {Function} [options.onProgress] 进度回调
 * @returns {Promise<{url: string, id: number, name: string, key?: string}>}
 */
export async function smartUpload(file, options = {}) {
  // 获取存储配置
  const config = await getStorageConfig();
  
  if (config.storageType === 'qiniu') {
    // 使用七牛云直传
    return uploadToQiniu(file, options);
  } else {
    // 使用本地上传（通过后端）
    return uploadToLocal(file, options);
  }
}

/**
 * 上传到七牛云（直传）
 * @param {File} file 文件对象
 * @param {Object} options 配置选项
 * @returns {Promise}
 */
export async function uploadToQiniu(file, options = {}) {
  // 1. 获取上传凭证
  const tokenRes = await getQiniuToken();
  if (tokenRes?.code !== 200) {
    throw new Error(tokenRes?.msg || '获取上传凭证失败');
  }
  
  const { token, keyPrefix, domain, region, uploadUrl } = tokenRes.data;
  
  // 2. 生成文件 key
  const ext = file.name.split('.').pop();
  const key = `${keyPrefix}.${ext}`;
  
  // 3. 配置上传参数
  const putExtra = {
    fname: file.name,
    mimeType: file.type || 'application/octet-stream',
  };
  
  // 4. 根据区域代码获取七牛云区域对象
  const qiniuRegion = getQiniuRegion(region);
  
  const config = {
    useCdnDomain: true,
    region: qiniuRegion,
  };
  
  // 5. 创建 observable 对象
  const observable = qiniu.upload(file, key, token, putExtra, config);
  
  // 5. 执行上传
  return new Promise((resolve, reject) => {
    const subscription = observable.subscribe({
      next(res) {
        // 进度回调
        if (options.onProgress) {
          options.onProgress({
            loaded: res.total.loaded,
            total: res.total.size,
            percent: res.total.percent,
          });
        }
      },
      error(err) {
        reject(new Error(err.message || '上传失败'));
      },
      async complete(res) {
        try {
          // 6. 保存文件记录到数据库
          const saveRes = await saveFileRecord({
            key: res.key,
            hash: res.hash,
            size: file.size,
            name: file.name,
            mimeType: file.type,
            cate: options.cate || 0,
          });
          
          if (saveRes?.code === 200 || saveRes?.code === 201) {
            resolve({
              url: saveRes.data.url,
              id: saveRes.data.id,
              name: saveRes.data.name,
              key: saveRes.data.key,
            });
          } else {
            reject(new Error(saveRes?.msg || '保存文件记录失败'));
          }
        } catch (error) {
          reject(error);
        }
      },
    });
  });
}

/**
 * 上传到本地（通过后端中转）
 * @param {File} file 文件对象
 * @param {Object} options 配置选项
 * @returns {Promise}
 */
export async function uploadToLocal(file, options = {}) {
  const formData = new FormData();
  formData.append('file', file);
  
  if (options.cate !== undefined) {
    formData.append('cate', String(options.cate));
  }
  
  const config = {
    url: '/platform/uploadfile',
    method: 'post',
    data: formData,
    timeout: 0, // 不设置超时
  };
  
  if (options.onProgress) {
    config.onUploadProgress = (e) => {
      options.onProgress({
        loaded: e.loaded,
        total: e.total || 0,
        percent: e.total > 0 ? Math.round((e.loaded * 100) / e.total) : 0,
      });
    };
  }
  
  const res = await request(config);
  
  if (res?.code === 200 || res?.code === 201) {
    return {
      url: res.data.url,
      id: res.data.id,
      name: res.data.name,
    };
  } else {
    throw new Error(res?.msg || '上传失败');
  }
}

/**
 * 批量上传文件
 * @param {File[]} files 文件数组
 * @param {Object} options 配置选项
 * @param {Function} [options.onFileProgress] 单个文件进度回调 (file, progress) => void
 * @param {Function} [options.onFileComplete] 单个文件完成回调 (file, result) => void
 * @param {Function} [options.onFileError] 单个文件错误回调 (file, error) => void
 * @returns {Promise<Array>}
 */
export async function batchUpload(files, options = {}) {
  const results = [];
  
  for (const file of files) {
    try {
      const result = await smartUpload(file, {
        ...options,
        onProgress: (progress) => {
          if (options.onFileProgress) {
            options.onFileProgress(file, progress);
          }
        },
      });
      
      results.push({ file, result, success: true });
      
      if (options.onFileComplete) {
        options.onFileComplete(file, result);
      }
    } catch (error) {
      results.push({ file, error, success: false });
      
      if (options.onFileError) {
        options.onFileError(file, error);
      }
    }
  }
  
  return results;
}

/**
 * 根据区域代码获取七牛云区域对象
 * @param {string} regionCode 区域代码 (z0, z1, z2, na0, as0, cn-east-2)
 * @returns {Object} 七牛云区域对象
 */
function getQiniuRegion(regionCode) {
  switch (regionCode) {
    case 'z0':
      return qiniu.region.z0; // 华东
    case 'z1':
      return qiniu.region.z1; // 华北
    case 'z2':
      return qiniu.region.z2; // 华南
    case 'na0':
      return qiniu.region.na0; // 北美
    case 'as0':
      return qiniu.region.as0; // 新加坡
    case 'cn-east-2':
      return qiniu.region.cnEast2; // 华东-浙江2
    default:
      return qiniu.region.z0; // 默认华东
  }
}
