'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var _regeneratorRuntime = require('@babel/runtime/regenerator');
var tslib_es6 = require('../../tslib.es6-0d92ef81.js');
var fs_fs = require('../../fs/fs.js');
var tencentCloud_cos_helper = require('./helper.js');
require('../../nodejs/crypto.js');
require('../../nodejs/fs.js');
require('../../nodejs/os.js');
require('../../bite/format-bite.js');
require('../../third-party/cos-nodejs-sdk-v5.js');

function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }

var _regeneratorRuntime__default = /*#__PURE__*/_interopDefaultLegacy(_regeneratorRuntime);

/**
 * 获取腾讯云COS对象的元数据信息（不返回对象内容）
 *
 * @param secretId - 腾讯云API密钥ID
 * @param secretKey - 腾讯云API密钥Key
 * @param bucket - COS存储桶名称
 * @param region - COS存储桶所在区域
 * @param key - 对象键（Object Key），对象在存储桶中的唯一标识
 * @returns Promise对象，成功时返回对象的元数据信息（如大小、修改时间等），失败时返回错误信息
 * @throws 当参数不全时会抛出错误
 * @example
 * ```typescript
 * getCosHeadObject({
 *   secretId: 'your-secret-id',
 *   secretKey: 'your-secret-key',
 *   bucket: 'test-bucket',
 *   region: 'ap-beijing',
 *   key: 'path/to/file.txt'
 * })
 * .then(data => console.log(data))
 * .catch(err => console.error(err));
 * ```
 */
function getCosHeadObject(_ref) {
  var secretId = _ref.secretId,
    secretKey = _ref.secretKey,
    bucket = _ref.bucket,
    region = _ref.region,
    key = _ref.key;
  return new Promise(function (resolve, reject) {
    if (!secretId || !secretKey || !bucket || !region) {
      reject('[Upload COS Error] 参数不全');
      return;
    }
    var cos = tencentCloud_cos_helper.getCOSInstance(secretId, secretKey);
    cos.headObject({
      Bucket: bucket,
      Region: region,
      Key: key
    }, function (err, data) {
      if (data) {
        resolve(data);
        return;
      }
      reject(err || data);
    });
  });
}
/**
 * 下载腾讯云COS对象内容
 *
 * @param secretId - 腾讯云API密钥ID
 * @param secretKey - 腾讯云API密钥Key
 * @param bucket - COS存储桶名称
 * @param region - COS存储桶所在区域
 * @param key - 对象键（Object Key），对象在存储桶中的唯一标识
 * @param output - 输出路径或输出流，可选参数。如果指定，对象内容将写入该路径或流
 * @returns Promise对象，成功时返回对象内容数据，失败时返回错误信息
 * @throws 当参数不全时会抛出错误
 * @example
 * ```typescript
 * // 下载到内存
 * downloadCosObject({
 *   secretId: 'your-secret-id',
 *   secretKey: 'your-secret-key',
 *   bucket: 'test-bucket',
 *   region: 'ap-beijing',
 *   key: 'path/to/file.txt'
 * })
 * .then(data => console.log(data))
 * .catch(err => console.error(err));
 *
 * // 下载到文件
 * downloadCosObject({
 *   secretId: 'your-secret-id',
 *   secretKey: 'your-secret-key',
 *   bucket: 'test-bucket',
 *   region: 'ap-beijing',
 *   key: 'path/to/file.txt',
 *   output: './local/file.txt'
 * })
 * .then(data => console.log('下载成功'))
 * .catch(err => console.error(err));
 * ```
 */
function downloadCosObject(_ref2) {
  var secretId = _ref2.secretId,
    secretKey = _ref2.secretKey,
    bucket = _ref2.bucket,
    region = _ref2.region,
    key = _ref2.key,
    output = _ref2.output;
  return new Promise(function (resolve, reject) {
    if (!secretId || !secretKey || !bucket || !region) {
      reject('[Upload COS Error] 参数不全');
      return;
    }
    var cos = tencentCloud_cos_helper.getCOSInstance(secretId, secretKey);
    cos.getObject({
      Bucket: bucket,
      Region: region,
      Key: key,
      Output: output
    }, function (err, data) {
      if (data) {
        resolve(data);
        return;
      }
      reject(err || data);
    });
  });
}
/**
 * 判断 COS 对象与本地文件是否一致（基于 size 与 ETag/MD5）
 *
 * 实现说明：
 * 1. 先比较文件大小（HEAD 返回的 Content-Length 与本地 stat().size）；不一致直接判定为不同。
 * 2. 大小一致时，再比较 MD5：
 *    - 优先使用 COS 的 `x-cos-meta-md5`（上传时显式设置的元数据，最可靠）；
 *    - 否则使用 ETag（仅当对象为简单上传，即 ETag 不含连字符 `-` 时才视为整体 MD5；分块上传 ETag 不可用于直接比较）。
 *
 * @param secretId  - 腾讯云 API 密钥 ID
 * @param secretKey - 腾讯云 API 密钥 Key
 * @param bucket    - COS 存储桶名称
 * @param region    - COS 存储桶所在区域
 * @param key       - 对象键
 * @param localFilePath - 本地文件路径
 * @returns Promise<boolean> 一致返回 true，否则 false（本地文件不存在或对象不存在也返回 false）
 *
 * @example
 * ```typescript
 * const same = await isCosObjectSameAsLocal({
 *   secretId, secretKey,
 *   bucket: 'test-bucket', region: 'ap-beijing',
 *   key: 'path/to/file.txt',
 *   localFilePath: './local/file.txt',
 * });
 * if (!same) {
 *   // 重新上传
 * }
 * ```
 */
function isCosObjectSameAsLocal(_ref3) {
  var secretId = _ref3.secretId,
    secretKey = _ref3.secretKey,
    bucket = _ref3.bucket,
    region = _ref3.region,
    key = _ref3.key,
    localFilePath = _ref3.localFilePath;
  return tslib_es6.__awaiter(this, void 0, void 0, /*#__PURE__*/_regeneratorRuntime__default["default"].mark(function _callee() {
    var localSize, head, headers, remoteSize, remoteMetaMd5, localMd5, rawETag, etag, _localMd;
    return _regeneratorRuntime__default["default"].wrap(function (_context) {
      while (1) switch (_context.prev = _context.next) {
        case 0:
          localSize = fs_fs.getLocalFileSize(localFilePath);
          if (!(localSize === null)) {
            _context.next = 1;
            break;
          }
          return _context.abrupt("return", false);
        case 1:
          _context.prev = 1;
          _context.next = 2;
          return getCosHeadObject({
            secretId: secretId,
            secretKey: secretKey,
            bucket: bucket,
            region: region,
            key: key
          });
        case 2:
          head = _context.sent;
          _context.next = 4;
          break;
        case 3:
          _context.prev = 3;
          _context["catch"](1);
          return _context.abrupt("return", false);
        case 4:
          headers = (head === null || head === void 0 ? void 0 : head.headers) || {};
          remoteSize = Number(headers['content-length']);
          if (!(!Number.isFinite(remoteSize) || remoteSize !== localSize)) {
            _context.next = 5;
            break;
          }
          return _context.abrupt("return", false);
        case 5:
          // 1. 优先使用 x-cos-meta-md5
          remoteMetaMd5 = headers['x-cos-meta-md5'] || '';
          if (!remoteMetaMd5) {
            _context.next = 6;
            break;
          }
          localMd5 = fs_fs.getLocalFileMd5(localFilePath);
          return _context.abrupt("return", !!localMd5 && localMd5.toLowerCase() === remoteMetaMd5.toLowerCase());
        case 6:
          // 2. 退化到 ETag（仅简单上传可作为 MD5 使用）
          rawETag = (head === null || head === void 0 ? void 0 : head.ETag) || headers.etag || '';
          etag = rawETag.replace(/"/g, '');
          if (!(etag && !etag.includes('-'))) {
            _context.next = 7;
            break;
          }
          _localMd = fs_fs.getLocalFileMd5(localFilePath);
          return _context.abrupt("return", !!_localMd && _localMd.toLowerCase() === etag.toLowerCase());
        case 7:
          return _context.abrupt("return", false);
        case 8:
        case "end":
          return _context.stop();
      }
    }, _callee, null, [[1, 3]]);
  }));
}

exports.downloadCosObject = downloadCosObject;
exports.getCosHeadObject = getCosHeadObject;
exports.isCosObjectSameAsLocal = isCosObjectSameAsLocal;
