import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
import _regeneratorRuntime from '@babel/runtime/regenerator';
import { _ as __awaiter } from '../tslib.es6-848120af.js';
import axios from 'axios';
import { getChildProcess } from '../nodejs/child_process.mjs';

/**
 * 判断包是否是腾讯内网包（@tencent 开头）
 * @param name 包名
 * @returns 是否是 @tencent/xxx 风格的内网包
 */
function isTencentInternalPackage(name) {
  return typeof name === 'string' && name.startsWith('@tencent/');
}
/**
 * 解析 npm 包详情页地址。
 * - `@tencent/xxx`：腾讯内网镜像 detail 页（mirrors.tencent.com 私有 npm，repo_id=537）
 * - 其他：npmjs.com 公网详情页
 *
 * @param name 包名
 * @returns 完整 URL
 * @example
 *
 * resolveNpmLink('t-comm')
 * // 'https://mirrors.tencent.com/#/private/npm/detail?repo_id=537&project_name=%40tencent%2Ft-comm'
 *
 * resolveNpmLink('lodash')
 * // 'https://npmjs.com/package/lodash'
 */
function resolveNpmLink(name) {
  if (!name) return '';
  if (isTencentInternalPackage(name)) {
    return "https://mirrors.tencent.com/#/private/npm/detail?repo_id=537&project_name=".concat(encodeURIComponent(name));
  }
  return "https://npmjs.com/package/".concat(name);
}
/**
 * 通过 `npm view <name> time --json` 拿到所有版本的发布时间，
 * 按时间倒序返回最近的 N 个版本号（跳过 created/modified 两个非版本号 key）。
 *
 * 这样做的原因：
 *   - version-tip 是在「发布完成后」调用的，registry 上已经存在新版本；
 *   - `time` 字段记录每个版本的 ISO 发布时间，倒序就能依次拿到「新版本」「上一个版本」。
 *
 * @param {string} name 包名
 * @param {number} limit 取最近的几个版本，默认 2（新、旧各一个）
 * @returns {string[]} 版本号数组，按时间倒序；失败返回空数组
 */
function getRecentVersions(name) {
  var limit = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2;
  try {
    var _getChildProcess = getChildProcess(),
      execSync = _getChildProcess.execSync;
    var out = execSync("npm view ".concat(name, " time --json"), {
      encoding: 'utf-8',
      stdio: ['ignore', 'pipe', 'pipe'],
      maxBuffer: 16 * 1024 * 1024
    });
    var time = JSON.parse(String(out).trim() || '{}');
    return Object.keys(time).filter(function (v) {
      return v !== 'created' && v !== 'modified';
    }).sort(function (a, b) {
      return new Date(time[b]).getTime() - new Date(time[a]).getTime();
    }).slice(0, limit);
  } catch (e) {
    console.warn("[version-tip] \u83B7\u53D6\u5386\u53F2\u7248\u672C\u5931\u8D25\uFF1A".concat((e === null || e === void 0 ? void 0 : e.message) || e));
    return [];
  }
}
/**
 * 通过 `npm pack --dry-run --json` 获取「即将发布」的新包体积。
 *
 * 注意事项：
 * - 必须在项目根目录或正确的 cwd 下执行，否则会发错包。
 * - 文件多时输出会撑爆默认 `maxBuffer`（1MB），这里设为 64MB。
 * - `--loglevel=error` 用于压住 npm 警告，进一步减少缓冲区占用。
 *
 * @param options.cwd 工作目录，默认 `process.cwd()`
 * @returns 新包体积。失败时返回全 0。
 */
function getNewPackageSize() {
  var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  var _a, _b, _c, _d, _e;
  var empty = {
    tarballSize: 0,
    unpackedSize: 0,
    fileCount: 0
  };
  try {
    var _getChildProcess2 = getChildProcess(),
      execSync = _getChildProcess2.execSync;
    var out = execSync('npm pack --dry-run --json --loglevel=error', {
      cwd: options.cwd || process.cwd(),
      encoding: 'utf-8',
      stdio: ['ignore', 'pipe', 'pipe'],
      maxBuffer: 64 * 1024 * 1024
    });
    var arr = JSON.parse(String(out).trim());
    var info = Array.isArray(arr) ? arr[0] : arr;
    return {
      tarballSize: (_a = info === null || info === void 0 ? void 0 : info.size) !== null && _a !== void 0 ? _a : 0,
      unpackedSize: (_b = info === null || info === void 0 ? void 0 : info.unpackedSize) !== null && _b !== void 0 ? _b : 0,
      fileCount: (_e = (_c = info === null || info === void 0 ? void 0 : info.entryCount) !== null && _c !== void 0 ? _c : (_d = info === null || info === void 0 ? void 0 : info.files) === null || _d === void 0 ? void 0 : _d.length) !== null && _e !== void 0 ? _e : 0
    };
  } catch (e) {
    console.warn("[GEN VERSION TIP] \u83B7\u53D6\u65B0\u5305\u4F53\u79EF\u5931\u8D25\uFF1A".concat((e === null || e === void 0 ? void 0 : e.message) || e));
    return empty;
  }
}
/**
 * 选择 registry：内网包走腾讯源，公网包走 npmjs.org
 */
function pickRegistry(name) {
  var registry = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '';
  if (registry) return registry.replace(/\/$/, '');
  return isTencentInternalPackage(name) ? 'https://mirrors.tencent.com/npm' : 'https://registry.npmjs.org';
}
/**
 * 把 scoped 包名编码为 registry 路径片段
 * `@tencent/foo` -> `@tencent/foo`（斜杠不编码，scope/name 各自 encode）
 */
function encodePackageName() {
  var name = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : '';
  if (name.startsWith('@')) {
    var _name$slice$split = name.slice(1).split('/'),
      _name$slice$split2 = _slicedToArray(_name$slice$split, 2),
      scope = _name$slice$split2[0],
      _name$slice$split2$ = _name$slice$split2[1],
      sub = _name$slice$split2$ === void 0 ? '' : _name$slice$split2$;
    return "@".concat(encodeURIComponent(scope), "/").concat(encodeURIComponent(sub));
  }
  return encodeURIComponent(name);
}
/**
 * 通过 registry 接口拿指定版本的包体积。
 * 兼容字段：
 *   - 腾讯源 mirrors.tencent.com：`dist.packageSize`（tarball 字节，可能无 unpackedSize）
 *   - 公网 npm：`dist.size`（tarball） + `dist.unpackedSize`（解包大小） + `dist.fileCount`
 */
function getPackageSizeByVersion(name, version) {
  var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
  var _a, _b, _c, _d, _e, _f, _g;
  return __awaiter(this, void 0, void 0, /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
    var empty, registry, url, _yield$axios$get, data, dist, _t;
    return _regeneratorRuntime.wrap(function (_context) {
      while (1) switch (_context.prev = _context.next) {
        case 0:
          empty = {
            tarballSize: 0,
            unpackedSize: 0,
            fileCount: 0
          };
          if (!(!name || !version)) {
            _context.next = 1;
            break;
          }
          return _context.abrupt("return", empty);
        case 1:
          registry = pickRegistry(name, options.registry);
          url = "".concat(registry, "/").concat(encodePackageName(name), "/").concat(encodeURIComponent(version));
          _context.prev = 2;
          _context.next = 3;
          return axios.get(url, {
            responseType: 'json',
            timeout: (_a = options.timeout) !== null && _a !== void 0 ? _a : 15000
          });
        case 3:
          _yield$axios$get = _context.sent;
          data = _yield$axios$get.data;
          dist = (_b = data === null || data === void 0 ? void 0 : data.dist) !== null && _b !== void 0 ? _b : {};
          return _context.abrupt("return", {
            tarballSize: (_e = (_d = (_c = dist.packageSize) !== null && _c !== void 0 ? _c : dist.size) !== null && _d !== void 0 ? _d : dist.contentLength) !== null && _e !== void 0 ? _e : 0,
            unpackedSize: (_f = dist.unpackedSize) !== null && _f !== void 0 ? _f : 0,
            fileCount: (_g = dist.fileCount) !== null && _g !== void 0 ? _g : 0
          });
        case 4:
          _context.prev = 4;
          _t = _context["catch"](2);
          console.warn("[version-tip] \u83B7\u53D6 ".concat(name, "@").concat(version, " \u4F53\u79EF\u5931\u8D25\uFF1A").concat((_t === null || _t === void 0 ? void 0 : _t.message) || _t));
          return _context.abrupt("return", empty);
        case 5:
        case "end":
          return _context.stop();
      }
    }, _callee, null, [[2, 4]]);
  }));
}
/**
 * 收集 `PackageSizeInfo`：
 *   - 从 `npm view <name> time` 拿到最近两个版本（新、旧）
 *   - 分别请求 registry 拿两个版本的体积，对比生成 PackageSizeInfo
 *
 * 注意：本方法依赖「发布完成后」调用，新版本必须已经在 registry 上。
 *
 * @param {object} appInfo package.json 内容，至少包含 name
 * @param {object} [options]
 * @param {string} [options.registry] 自定义 registry
 * @returns {Promise<import('t-comm').PackageSizeInfo>}
 */
function collectPackageSize(appInfo) {
  var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
  return __awaiter(this, void 0, void 0, /*#__PURE__*/_regeneratorRuntime.mark(function _callee2() {
    var name, _getRecentVersions, _getRecentVersions2, newVersion, oldVersion, _yield$Promise$all, _yield$Promise$all2, newPkg, oldPkg;
    return _regeneratorRuntime.wrap(function (_context2) {
      while (1) switch (_context2.prev = _context2.next) {
        case 0:
          name = appInfo === null || appInfo === void 0 ? void 0 : appInfo.name;
          if (name) {
            _context2.next = 1;
            break;
          }
          return _context2.abrupt("return", {
            newSize: 0
          });
        case 1:
          _getRecentVersions = getRecentVersions(name, 2), _getRecentVersions2 = _slicedToArray(_getRecentVersions, 2), newVersion = _getRecentVersions2[0], oldVersion = _getRecentVersions2[1];
          console.log("[version-tip] ".concat(name, " new=").concat(newVersion || '(none)', " old=").concat(oldVersion || '(none)'));
          if (newVersion) {
            _context2.next = 2;
            break;
          }
          return _context2.abrupt("return", {
            newSize: 0
          });
        case 2:
          _context2.next = 3;
          return Promise.all([getPackageSizeByVersion(name, newVersion, {
            registry: options.registry
          }), oldVersion ? getPackageSizeByVersion(name, oldVersion, {
            registry: options.registry
          }) : Promise.resolve({
            tarballSize: 0,
            unpackedSize: 0,
            fileCount: 0
          })]);
        case 3:
          _yield$Promise$all = _context2.sent;
          _yield$Promise$all2 = _slicedToArray(_yield$Promise$all, 2);
          newPkg = _yield$Promise$all2[0];
          oldPkg = _yield$Promise$all2[1];
          return _context2.abrupt("return", {
            oldSize: oldPkg.tarballSize,
            newSize: newPkg.tarballSize,
            oldUnpacked: oldPkg.unpackedSize,
            newUnpacked: newPkg.unpackedSize,
            fileCount: newPkg.fileCount
          });
        case 4:
        case "end":
          return _context2.stop();
      }
    }, _callee2);
  }));
}

export { collectPackageSize, getNewPackageSize, getPackageSizeByVersion, getRecentVersions, isTencentInternalPackage, resolveNpmLink };
