/**
 * 阿里云 OSS PostObject 直传（对齐 xk-admin oss-upload.ts）
 *
 * 运维：微信小程序 uploadFile 合法域名需包含 OSS host
 * 例如 https://xiaokang88.oss-cn-hangzhou.aliyuncs.com
 */
import { getBusinessOssSignatureApi, unwrapOssSignature, registerBusinessOssFile } from '@/api/upload.js';
import { checkImage } from '@/common/js/content-security.js';

/**
 * @param {string} filePath 本地临时文件路径
 * @returns {string} xk_upload_YYYYMMDD/uuid_timestamp.ext
 */
export function generateObjectName(filePath) {
  const today = new Date();
  const year = today.getFullYear();
  const month = String(today.getMonth() + 1).padStart(2, '0');
  const day = String(today.getDate()).padStart(2, '0');
  const dateStr = `${year}${month}${day}`;

  const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
    const r = (Math.random() * 16) | 0;
    const v = c === 'x' ? r : (r & 0x3) | 0x8;
    return v.toString(16);
  });

  const timestamp = Math.floor(Date.now() / 1000);
  const pathStr = String(filePath || '');
  const lastDotIndex = pathStr.lastIndexOf('.');
  const extension = lastDotIndex > 0 ? pathStr.substring(lastDotIndex + 1).toLowerCase() : 'jpg';

  return `xk_upload_${dateStr}/${uuid}_${timestamp}.${extension}`;
}

function basenameFromPath(filePath) {
  const pathStr = String(filePath || '');
  const parts = pathStr.split(/[/\\]/);
  return parts[parts.length - 1] || '';
}

/**
 * @returns {Promise<{ accessKeyId, policy, signature, host, bucket, key, expire }>}
 */
export async function getOssSignatureFromBackend() {
  const res = await getBusinessOssSignatureApi();
  const signature = unwrapOssSignature(res);
  if (!signature) {
    throw new Error('获取 OSS 签名失败');
  }
  return signature;
}

/**
 * @param {{ filePath: string, onProgress?: (percent: number) => void }} options
 * @returns {Promise<{ url: string, objectName: string }>}
 */
export async function uploadToOss(options) {
  const { filePath, onProgress, fileSize = 0, fileName = '' } = options || {};
  if (!filePath) {
    throw new Error('文件路径为空');
  }

  await checkImage(filePath, 1);

  const signature = await getOssSignatureFromBackend();
  const objectName = generateObjectName(filePath);

  const formData = {
    key: objectName,
    policy: signature.policy,
    OSSAccessKeyId: signature.accessKeyId,
    signature: signature.signature,
    success_action_status: '200',
    'x-oss-object-acl': 'public-read',
  };

  return new Promise((resolve, reject) => {
    const uploadTask = uni.uploadFile({
      url: signature.host,
      filePath,
      name: 'file',
      formData,
      success: (uploadRes) => {
        const code = uploadRes.statusCode;
        if (code >= 200 && code < 300 || code === 204) {
          const host = String(signature.host).replace(/\/$/, '');
          const url = `${host}/${objectName}`;
          const displayName = fileName || basenameFromPath(filePath);
          registerBusinessOssFile(url, fileSize, displayName).catch((err) => {
            console.warn('OSS 文件登记失败:', err);
          });
          resolve({
            url,
            objectName,
          });
          return;
        }
        reject(new Error(`OSS 上传失败，HTTP ${code}`));
      },
      fail: (err) => {
        reject(err instanceof Error ? err : new Error((err && err.errMsg) || 'OSS 上传失败'));
      },
    });

    if (onProgress && uploadTask && typeof uploadTask.onProgressUpdate === 'function') {
      uploadTask.onProgressUpdate((res) => {
        if (res.totalBytesExpectedToSend > 0) {
          const percent = Math.round((res.totalBytesSent / res.totalBytesExpectedToSend) * 100);
          onProgress(percent);
        }
      });
    }
  });
}
