'use strict';

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

var _toConsumableArray = require('@babel/runtime/helpers/toConsumableArray');
var _defineProperty = require('@babel/runtime/helpers/defineProperty');
var _slicedToArray = require('@babel/runtime/helpers/slicedToArray');
var _regeneratorRuntime = require('@babel/runtime/regenerator');
var tslib_es6 = require('../tslib.es6-0d92ef81.js');
var fs_fs = require('../fs/fs.js');
var node_nodeCommand = require('../node/node-command.js');
var nodejs_fs = require('../nodejs/fs.js');
var nodejs_path = require('../nodejs/path.js');
var tgit_helper = require('../tgit/helper.js');
var tgit_mr = require('../tgit/mr.js');
var time_time = require('../time/time.js');
var wecomRobot_batchSend = require('../wecom-robot/batch-send.js');
var lint_config = require('./config.js');
var lint_git = require('./git.js');
var lint_helper = require('./helper.js');
var lint_message = require('./message.js');
require('../nodejs/crypto.js');
require('../nodejs/os.js');
require('@babel/runtime/helpers/typeof');
require('../nodejs/child_process.js');
require('axios');
require('../tgit/user.js');
require('../wecom-robot/base.js');
require('../wecom-robot/helper.js');
require('../wecom-robot/send-img.js');
require('../node-img/img.js');
require('../nodejs/request.js');
require('../git/submodule.js');
require('../git/git.js');
require('../validate/validate.js');

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

var _toConsumableArray__default = /*#__PURE__*/_interopDefaultLegacy(_toConsumableArray);
var _defineProperty__default = /*#__PURE__*/_interopDefaultLegacy(_defineProperty);
var _slicedToArray__default = /*#__PURE__*/_interopDefaultLegacy(_slicedToArray);
var _regeneratorRuntime__default = /*#__PURE__*/_interopDefaultLegacy(_regeneratorRuntime);

function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t["return"] || t["return"](); } finally { if (u) throw o; } } }; }
function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
var ESLINT_CONFIG_FILE = '.eslintrc.js';
/**
 * 临时移除 .eslintrc.js 中的 parserOptions.project 配置。
 *
 * 背景：lint vue 文件时，如果 tsconfig.json 的 include 不包含 .vue，
 * @typescript-eslint/parser 会抛 parsing error 导致整个 lint 流程中断；
 * 但对于 ts/tsx 文件，parserOptions.project 是开启类型感知规则的关键配置，
 * 不能永久删除。因此本函数返回一个 restore 函数，调用方应在 lint 完成后
 * （建议放在 finally 中）调用它来还原配置文件。
 *
 * 同时注册了进程退出钩子，作为异常崩溃时的兜底恢复。
 *
 * @returns restore 函数，用于恢复 .eslintrc.js 原始内容；若未发生修改则为 no-op
 */
function removeParserOptionsProject(workspace) {
  var noop = function noop() {};
  var configFile = nodejs_path.getPath().resolve(workspace, ESLINT_CONFIG_FILE);
  if (!nodejs_fs.getFs().existsSync(configFile)) {
    console.log('不存在配置文件');
    return noop;
  }
  var content = fs_fs.readFileSync(configFile);
  var reg = /\s+project:\s+'[^']+json',/;
  var newContent = content.replace(reg, '');
  if (!newContent || newContent === content) {
    return noop;
  }
  console.log('已删除 parserOptions.project');
  fs_fs.writeFileSync(configFile, newContent);
  // 进程异常退出兜底：避免 lint 崩溃后 .eslintrc.js 永久残缺
  var restored = false;
  var restore = function restore() {
    if (restored) return;
    restored = true;
    try {
      fs_fs.writeFileSync(configFile, content);
      console.log('已恢复 parserOptions.project');
    } catch (err) {
      console.log('[restoreParserOptionsProject] error: ', err);
    } finally {
      process.off('exit', onProcessExit);
      process.off('SIGINT', onSignal);
      process.off('SIGTERM', onSignal);
      process.off('uncaughtException', onSignal);
    }
  };
  var onProcessExit = function onProcessExit() {
    return restore();
  };
  var onSignal = function onSignal() {
    return restore();
  };
  process.on('exit', onProcessExit);
  process.on('SIGINT', onSignal);
  process.on('SIGTERM', onSignal);
  process.on('uncaughtException', onSignal);
  return restore;
}
function parseScssFiles(scssErrorFiles, workspace) {
  if (!(scssErrorFiles === null || scssErrorFiles === void 0 ? void 0 : scssErrorFiles.length)) {
    return [];
  }
  var parsedFiles = scssErrorFiles.reduce(function (acc, item) {
    var _a;
    (_a = item.warnings) === null || _a === void 0 ? void 0 : _a.forEach(function (messageItem) {
      acc.push(Object.assign(Object.assign({
        filePath: item.source,
        parsedFilePath: nodejs_path.getPath().relative(workspace, item.source)
      }, messageItem), {
        message: messageItem.text,
        ruleId: messageItem.rule
      }));
    });
    return acc;
  }, []);
  return parsedFiles;
}
function parseJSFiles(jsErrorFiles, workspace) {
  if (!(jsErrorFiles === null || jsErrorFiles === void 0 ? void 0 : jsErrorFiles.length)) {
    return [];
  }
  var parsedFiles = jsErrorFiles.reduce(function (acc, item) {
    var _a;
    (_a = item.messages) === null || _a === void 0 ? void 0 : _a.forEach(function (messageItem) {
      acc.push(Object.assign({
        filePath: item.filePath,
        parsedFilePath: nodejs_path.getPath().relative(workspace, item.filePath)
      }, messageItem));
    });
    return acc;
  }, []);
  return parsedFiles;
}
function tryCreateMRNote(_ref) {
  var privateToken = _ref.privateToken,
    _ref$gitApiPrefix = _ref.gitApiPrefix,
    gitApiPrefix = _ref$gitApiPrefix === void 0 ? tgit_helper.T_GIT_BASE_URL : _ref$gitApiPrefix,
    errorFiles = _ref.errorFiles,
    projectName = _ref.projectName,
    mrId = _ref.mrId,
    workspace = _ref.workspace,
    isScss = _ref.isScss;
  return tslib_es6.__awaiter(this, void 0, void 0, /*#__PURE__*/_regeneratorRuntime__default["default"].mark(function _callee() {
    var parsedFiles, _iterator, _step, file, _t;
    return _regeneratorRuntime__default["default"].wrap(function (_context) {
      while (1) switch (_context.prev = _context.next) {
        case 0:
          parsedFiles = isScss ? parseScssFiles(errorFiles, workspace) : parseJSFiles(errorFiles, workspace);
          console.log('[isScss]', isScss);
          console.log('[parsedFiles]', parsedFiles);
          if (parsedFiles === null || parsedFiles === void 0 ? void 0 : parsedFiles.length) {
            _context.next = 1;
            break;
          }
          return _context.abrupt("return");
        case 1:
          _iterator = _createForOfIteratorHelper(parsedFiles);
          _context.prev = 2;
          _iterator.s();
        case 3:
          if ((_step = _iterator.n()).done) {
            _context.next = 5;
            break;
          }
          file = _step.value;
          _context.next = 4;
          return lint_git.createMRNote({
            projectName: projectName,
            mrId: mrId,
            body: "".concat(file.message, "\n\n [").concat(file.ruleId, "]") || '格式错误',
            line: file.line,
            path: file.parsedFilePath,
            privateToken: privateToken,
            gitApiPrefix: gitApiPrefix
          });
        case 4:
          _context.next = 3;
          break;
        case 5:
          _context.next = 7;
          break;
        case 6:
          _context.prev = 6;
          _t = _context["catch"](2);
          _iterator.e(_t);
        case 7:
          _context.prev = 7;
          _iterator.f();
          return _context.finish(7);
        case 8:
        case "end":
          return _context.stop();
      }
    }, _callee, null, [[2, 6, 7, 8]]);
  }));
}
/**
 * 生成修复分支名：feature/fix-eslint-{yyyyMMddhhmmss} 或 feature/fix-stylelint-{yyyyMMddhhmmss}
 * @example
 * ```ts
 * genFixBranchName('eslint', new Date('2025-01-02 03:04:05').getTime());
 * // 'feature/fix-eslint-20250102030405'
 *
 * genFixBranchName('stylelint');
 * // 'feature/fix-stylelint-{当前时间}'
 * ```
 */
function genFixBranchName() {
  var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'eslint';
  var timestamp = arguments.length > 1 ? arguments[1] : undefined;
  var ts = timestamp || Date.now();
  var timeStr = time_time.timeStampFormat(ts, 'yyyyMMddhhmmss');
  return "feature/fix-".concat(type, "-").concat(timeStr);
}
/**
 * 应在 git add 时排除的文件模式：
 * - lint 产出的 JSON 报告文件
 * - ignoreSubmodule 可能修改的 ignore 文件
 */
var GIT_ADD_EXCLUDE_PATTERNS = ['lint-*.json', 'lint-merged-*.json', '.eslintignore', '.stylelintignore'];
/**
 * 在 fix 分支上执行 git add，排除 lint 产出文件和 ignore 文件变更
 */
function gitAddExcludingLintOutputs(workspace) {
  var excludeArgs = GIT_ADD_EXCLUDE_PATTERNS.map(function (p) {
    return "':!".concat(p, "'");
  }).join(' ');
  node_nodeCommand.execCommand("git add -A -- . ".concat(excludeArgs), workspace, 'inherit');
}
/**
 * 创建一个 fix 分支、提交并推送，然后创建 MR
 * @returns MR 信息，失败时返回 undefined
 */
function commitFixAndCreateMR(_ref2) {
  var workspace = _ref2.workspace,
    fixBranch = _ref2.fixBranch,
    fixTargetBranch = _ref2.fixTargetBranch,
    commitMsg = _ref2.commitMsg,
    repo = _ref2.repo,
    privateToken = _ref2.privateToken,
    _ref2$gitApiPrefix = _ref2.gitApiPrefix,
    gitApiPrefix = _ref2$gitApiPrefix === void 0 ? tgit_helper.T_GIT_BASE_URL : _ref2$gitApiPrefix,
    mrTitlePrefix = _ref2.mrTitlePrefix;
  return tslib_es6.__awaiter(this, void 0, void 0, /*#__PURE__*/_regeneratorRuntime__default["default"].mark(function _callee2() {
    var diffOutput, mrData, _t2;
    return _regeneratorRuntime__default["default"].wrap(function (_context2) {
      while (1) switch (_context2.prev = _context2.next) {
        case 0:
          gitAddExcludingLintOutputs(workspace);
          // 检查是否有实际变更（fix 可能没改任何文件）
          diffOutput = node_nodeCommand.execCommand('git diff --cached --name-only', workspace).trim();
          if (diffOutput) {
            _context2.next = 1;
            break;
          }
          console.log("[autoFixMR] ".concat(fixBranch, " \u65E0\u5B9E\u9645\u53D8\u66F4\uFF0C\u8DF3\u8FC7\u521B\u5EFA MR"));
          return _context2.abrupt("return", undefined);
        case 1:
          _context2.prev = 1;
          node_nodeCommand.execCommand("git commit --no-verify -m \"".concat(commitMsg, "\""), workspace, 'inherit');
          node_nodeCommand.execCommand("git push origin ".concat(fixBranch), workspace, 'inherit');
          _context2.next = 2;
          return tgit_mr.createMR({
            projectName: repo,
            privateToken: privateToken,
            sourceBranch: fixBranch,
            targetBranch: fixTargetBranch,
            baseUrl: gitApiPrefix,
            titlePrefix: mrTitlePrefix
          });
        case 2:
          mrData = _context2.sent;
          console.log("[autoFixMR] \u5DF2\u521B\u5EFA\u4FEE\u590D MR: ".concat(fixBranch, " => ").concat(fixTargetBranch));
          return _context2.abrupt("return", {
            fixBranch: fixBranch,
            fixTargetBranch: fixTargetBranch,
            mrData: mrData
          });
        case 3:
          _context2.prev = 3;
          _t2 = _context2["catch"](1);
          console.log("[autoFixMR] \u63D0\u4EA4\u6216\u521B\u5EFA MR \u5931\u8D25 (".concat(fixBranch, "): "), _t2);
          return _context2.abrupt("return", undefined);
        case 4:
        case "end":
          return _context2.stop();
      }
    }, _callee2, null, [[1, 3]]);
  }));
}
/**
 * 自动执行 --fix 并创建修复 MR
 * eslint 和 stylelint 分别创建独立 MR，便于 review
 * @returns 创建的修复 MR 信息列表，失败时返回 undefined
 * @example
 * ```ts
 * const fixMRList = await autoFixAndCreateMR({
 *   fileMap,
 *   workspace: '/path/to/repo',
 *   sourceBranch: 'feature/foo',
 *   targetBranch: 'master',
 *   repo: 'group/project',
 *   privateToken: 'xxx',
 *   mrTitlePrefix: '[WIP]',
 * });
 * ```
 */
function autoFixAndCreateMR(_ref3) {
  var fileMap = _ref3.fileMap,
    workspace = _ref3.workspace,
    sourceBranch = _ref3.sourceBranch,
    targetBranch = _ref3.targetBranch,
    repo = _ref3.repo,
    privateToken = _ref3.privateToken,
    _ref3$gitApiPrefix = _ref3.gitApiPrefix,
    gitApiPrefix = _ref3$gitApiPrefix === void 0 ? tgit_helper.T_GIT_BASE_URL : _ref3$gitApiPrefix,
    mrTitlePrefix = _ref3.mrTitlePrefix;
  return tslib_es6.__awaiter(this, void 0, void 0, /*#__PURE__*/_regeneratorRuntime__default["default"].mark(function _callee3() {
    var currentBranch, fixTargetBranch, eslintEntries, stylelintEntries, results, eslintFixBranch, _iterator2, _step2, _step2$value, key, info, eslintMR, stylelintFixBranch, _iterator3, _step3, _step3$value, _key, _info, stylelintMR, _t3;
    return _regeneratorRuntime__default["default"].wrap(function (_context3) {
      while (1) switch (_context3.prev = _context3.next) {
        case 0:
          _context3.prev = 0;
          currentBranch = sourceBranch || node_nodeCommand.execCommand('git symbolic-ref --short -q HEAD', workspace).trim();
          fixTargetBranch = currentBranch || targetBranch || 'master'; // 按 eslint / stylelint 分组有错误的文件类型
          eslintEntries = [];
          stylelintEntries = [];
          Object.keys(fileMap).forEach(function (key) {
            var info = fileMap[key];
            if (!info.total || !info.lintKeyword) return;
            if (info.isStyle) {
              stylelintEntries.push([key, info]);
            } else {
              eslintEntries.push([key, info]);
            }
          });
          results = []; // ---- ESLint fix MR ----
          if (!(eslintEntries.length > 0)) {
            _context3.next = 2;
            break;
          }
          eslintFixBranch = genFixBranchName();
          node_nodeCommand.execCommand("git checkout -b ".concat(eslintFixBranch), workspace, 'inherit');
          _iterator2 = _createForOfIteratorHelper(eslintEntries);
          try {
            for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
              _step2$value = _slicedToArray__default["default"](_step2.value, 2), key = _step2$value[0], info = _step2$value[1];
              try {
                node_nodeCommand.execCommand("npx eslint ".concat(info.lintKeyword, " --fix || true"), workspace, 'pipe');
                console.log("[ESLint --fix] ".concat(key, " done"));
              } catch (err) {
                console.log("[ESLint --fix] ".concat(key, " error: "), err);
              }
            }
          } catch (err) {
            _iterator2.e(err);
          } finally {
            _iterator2.f();
          }
          _context3.next = 1;
          return commitFixAndCreateMR({
            workspace: workspace,
            fixBranch: eslintFixBranch,
            fixTargetBranch: fixTargetBranch,
            commitMsg: 'fix: auto fix eslint errors by checkLint',
            repo: repo,
            privateToken: privateToken,
            gitApiPrefix: gitApiPrefix,
            mrTitlePrefix: mrTitlePrefix
          });
        case 1:
          eslintMR = _context3.sent;
          if (eslintMR) results.push(eslintMR);
          // 切回原分支，为下一轮 stylelint fix 做准备
          try {
            node_nodeCommand.execCommand("git checkout ".concat(currentBranch), workspace, 'inherit');
          } catch (err) {
            console.log('[autoFixMR] 切回原分支失败: ', err);
          }
        case 2:
          if (!(stylelintEntries.length > 0)) {
            _context3.next = 4;
            break;
          }
          stylelintFixBranch = genFixBranchName('stylelint', Date.now() + 1);
          node_nodeCommand.execCommand("git checkout -b ".concat(stylelintFixBranch), workspace, 'inherit');
          _iterator3 = _createForOfIteratorHelper(stylelintEntries);
          try {
            for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
              _step3$value = _slicedToArray__default["default"](_step3.value, 2), _key = _step3$value[0], _info = _step3$value[1];
              try {
                node_nodeCommand.execCommand("npx stylelint ".concat(_info.lintKeyword, " --fix || true"), workspace, 'pipe');
                console.log("[StyleLint --fix] ".concat(_key, " done"));
              } catch (err) {
                console.log("[StyleLint --fix] ".concat(_key, " error: "), err);
              }
            }
          } catch (err) {
            _iterator3.e(err);
          } finally {
            _iterator3.f();
          }
          _context3.next = 3;
          return commitFixAndCreateMR({
            workspace: workspace,
            fixBranch: stylelintFixBranch,
            fixTargetBranch: fixTargetBranch,
            commitMsg: 'fix: auto fix stylelint errors by checkLint',
            repo: repo,
            privateToken: privateToken,
            gitApiPrefix: gitApiPrefix,
            mrTitlePrefix: mrTitlePrefix
          });
        case 3:
          stylelintMR = _context3.sent;
          if (stylelintMR) results.push(stylelintMR);
          // 切回原分支
          try {
            node_nodeCommand.execCommand("git checkout ".concat(currentBranch), workspace, 'inherit');
          } catch (err) {
            console.log('[autoFixMR] 切回原分支失败: ', err);
          }
        case 4:
          return _context3.abrupt("return", results.length > 0 ? results : undefined);
        case 5:
          _context3.prev = 5;
          _t3 = _context3["catch"](0);
          console.log('[autoFixMR] error: ', _t3);
          return _context3.abrupt("return", undefined);
        case 6:
        case "end":
          return _context3.stop();
      }
    }, _callee3, null, [[0, 5]]);
  }));
}
/**
 * 执行代码 lint 检查（支持 ESLint 和 StyleLint），并将结果通知到企业微信群、MR 评论等。
 *
 * 支持增量模式（仅检查 sourceBranch 与 targetBranch 之间的 diff 文件）和全量模式（checkAll=true）。
 * 检查完成后可自动执行 --fix 并创建修复 MR（autoFixMR=true）。
 *
 * @param options - 配置参数
 * @param options.privateToken - Git API 私有令牌，用于操作 MR
 * @param options.gitApiPrefix - Git API 地址前缀
 * @param options.workspace - 项目工作目录绝对路径
 * @param options.mrUrl - MR 页面链接，用于消息通知中展示
 * @param options.mrId - MR ID，传入后会在 MR 中添加评论和逐行批注
 * @param options.buildUrl - 流水线构建链接，用于消息通知中展示
 * @param options.repo - 仓库名称（如 group/project）
 * @param options.repoUrl - 仓库页面链接
 * @param options.sourceBranch - 源分支名（增量模式必填）
 * @param options.targetBranch - 目标分支名（增量模式必填）
 * @param options.docLink - 说明文档链接，用于消息通知中展示
 * @param options.webhookUrl - 企业微信机器人 Webhook 地址
 * @param options.chatId - 企业微信群聊 ID 列表，默认 ['ALL']
 * @param options.checkAll - 是否全量检查，默认 false（增量模式）
 * @param options.mentionList - 需要 @ 的企业微信用户列表
 * @param options.lintFiles - 需要检查的文件类型列表，默认检查所有配置的类型
 * @param options.throwError - 检查不通过时是否抛出异常，默认 true
 * @param options.ignoreSubmodules - 是否在 lint 时忽略 git submodule，默认 true
 * @param options.autoFixMR - 是否自动执行 --fix 并创建修复 MR，默认 false
 * @param options.mrTitlePrefix - autoFixMR 创建 MR 时的标题前缀，如 '[WIP]' 可防止被自动合入
 * @param options.onReport - 上报回调，lint 完成后调用，传入错误数量等关键信息
 * @returns 返回 fileMap，包含各文件类型的 lint 结果
 * @throws 当 throwError 为 true 且存在 lint 错误时抛出异常
 *
 * @example
 * ```ts
 * import { checkLint } from 't-comm';
 *
 * await checkLint({
 *   privateToken: 'your-token',
 *   gitApiPrefix: 'https://git.woa.com/api/v3',
 *   workspace: '/path/to/project',
 *   buildUrl: 'https://ci.example.com/build/123',
 *   repo: 'group/project',
 *   sourceBranch: 'feature/xxx',
 *   targetBranch: 'master',
 *   docLink: 'https://doc.example.com/lint',
 *   webhookUrl: 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx',
 * });
 * ```
 */
function checkLint(_ref4) {
  var privateToken = _ref4.privateToken,
    _ref4$gitApiPrefix = _ref4.gitApiPrefix,
    gitApiPrefix = _ref4$gitApiPrefix === void 0 ? tgit_helper.T_GIT_BASE_URL : _ref4$gitApiPrefix,
    workspace = _ref4.workspace,
    mrUrl = _ref4.mrUrl,
    mrId = _ref4.mrId,
    buildUrl = _ref4.buildUrl,
    repo = _ref4.repo,
    repoUrl = _ref4.repoUrl,
    sourceBranch = _ref4.sourceBranch,
    targetBranch = _ref4.targetBranch,
    docLink = _ref4.docLink,
    webhookUrl = _ref4.webhookUrl,
    _ref4$chatId = _ref4.chatId,
    chatId = _ref4$chatId === void 0 ? ['ALL'] : _ref4$chatId,
    checkAll = _ref4.checkAll,
    _ref4$mentionList = _ref4.mentionList,
    mentionList = _ref4$mentionList === void 0 ? [] : _ref4$mentionList,
    _ref4$lintFiles = _ref4.lintFiles,
    lintFiles = _ref4$lintFiles === void 0 ? Object.keys(lint_config.FILE_TYPE_MAP) : _ref4$lintFiles,
    _ref4$throwError = _ref4.throwError,
    throwError = _ref4$throwError === void 0 ? true : _ref4$throwError,
    _ref4$ignoreSubmodule = _ref4.ignoreSubmodules,
    ignoreSubmodules = _ref4$ignoreSubmodule === void 0 ? true : _ref4$ignoreSubmodule,
    _ref4$autoFixMR = _ref4.autoFixMR,
    autoFixMR = _ref4$autoFixMR === void 0 ? false : _ref4$autoFixMR,
    mrTitlePrefix = _ref4.mrTitlePrefix,
    onReport = _ref4.onReport;
  return tslib_es6.__awaiter(this, void 0, void 0, /*#__PURE__*/_regeneratorRuntime__default["default"].mark(function _callee4() {
    var startTime, fileMap, _getDiffFile, diffFilesMap, innerExecCommand, keys, eslintKeys, stylelintKeys, restoreParserOptions, mergedExts, mergedOutputFile, lintResult, _iterator4, _step4, k, _iterator5, _step5, key, outputFile, _parseResult, errorMap, duration, hasError, fixMRList, errorDetails, totalErrors, commentSuccess, message, getPostFix, robotMessage, _i, _Object$keys, _key2, _t4, _t6;
    return _regeneratorRuntime__default["default"].wrap(function (_context4) {
      while (1) switch (_context4.prev = _context4.next) {
        case 0:
          if (!(!checkAll && (!sourceBranch || !targetBranch))) {
            _context4.next = 1;
            break;
          }
          throw new Error('增量模式，必须提供 sourceBranch 和 targetBranch！');
        case 1:
          startTime = Date.now();
          if (ignoreSubmodules) {
            lint_helper.ignoreSubmoduleInESLint(workspace);
            lint_helper.ignoreSubmoduleInStyleLint(workspace);
          }
          fileMap = Object.keys(lint_config.FILE_TYPE_MAP).filter(function (item) {
            return lintFiles.includes(item);
          }).reduce(function (acc, key) {
            return Object.assign(Object.assign({}, acc), _defineProperty__default["default"]({}, key, lint_config.FILE_TYPE_MAP[key]));
          }, {});
          if (!checkAll) {
            _getDiffFile = getDiffFile({
              sourceBranch: sourceBranch,
              targetBranch: targetBranch,
              workspace: workspace
            }), diffFilesMap = _getDiffFile.diffFilesMap;
            Object.keys(fileMap).forEach(function (key) {
              fileMap[key].lintKeyword = diffFilesMap[key];
            });
          }
          innerExecCommand = function innerExecCommand(key, info) {
            console.log("\u6B63\u5728\u6267\u884C lint ".concat(key, " ..."));
            // 增量模式下，如果 diff 中没有该类型的文件，lintKeyword 为空字符串，应跳过执行
            // 否则 stylelint 会因为没有传入文件参数而对整个 cwd 做全量扫描
            if (!checkAll && !info.lintKeyword) {
              console.log("[Skip] ".concat(key, " \u589E\u91CF\u6A21\u5F0F\u65E0\u53D8\u66F4\u6587\u4EF6\uFF0C\u8DF3\u8FC7"));
              return '';
            }
            var restoreParserOptions = info.isVue ? removeParserOptionsProject(workspace) : function () {};
            var outputFile = nodejs_path.getPath().resolve(workspace, info.outputFileName);
            try {
              if (info.isStyle) {
                try {
                  // inherit 无法真正捕获错误
                  var lintResult = node_nodeCommand.execCommand("npx stylelint ".concat(info.lintKeyword, " --quiet -o ").concat(outputFile, " --formatter json || true"), workspace, 'pipe');
                  console.log('[StyleLint] result: \n', lintResult);
                } catch (err) {
                  console.log('[StyleLint] error: ', err);
                }
              } else {
                try {
                  var _lintResult = node_nodeCommand.execCommand("npx eslint ".concat(info.lintKeyword, " --quiet -o ").concat(outputFile, " --format json || true"), workspace, 'pipe');
                  console.log('[ESLint] result: \n', _lintResult);
                } catch (err) {
                  console.log('[ESLint] error: ', err);
                }
              }
            } finally {
              restoreParserOptions();
            }
            return outputFile;
          }; // 🚀 性能优化：将同引擎的文件类型合并执行，减少 npx 调用次数
          // 对于增量模式，每种类型有不同的文件列表，无法合并，仍逐个执行
          // 对于全量模式，同引擎可合并为一次调用（ESLint 支持 --ext .js,.ts,.tsx 等）
          keys = Object.keys(fileMap);
          if (checkAll && keys.length > 1) {
            // 按 eslint / stylelint 分组
            eslintKeys = keys.filter(function (k) {
              return !fileMap[k].isStyle;
            });
            stylelintKeys = keys.filter(function (k) {
              return fileMap[k].isStyle;
            }); // ESLint：合并所有非 style 文件类型，一次调用
            if (eslintKeys.length > 0) {
              // vue 需要先移除 parserOptions.project；执行完后必须恢复，避免影响 ts 类型感知规则
              restoreParserOptions = eslintKeys.some(function (k) {
                return fileMap[k].isVue;
              }) ? removeParserOptionsProject(workspace) : function () {};
              mergedExts = eslintKeys.map(function (k) {
                return ".".concat(k);
              }).join(',');
              mergedOutputFile = nodejs_path.getPath().resolve(workspace, 'lint-merged-eslint.json');
              try {
                console.log("\u6B63\u5728\u6267\u884C ESLint\uFF08\u5408\u5E76: ".concat(eslintKeys.join(', '), "\uFF09..."));
                lintResult = node_nodeCommand.execCommand("npx eslint --ext ".concat(mergedExts, " . --quiet -o ").concat(mergedOutputFile, " --format json || true"), workspace, 'pipe');
                console.log('[ESLint merged] result: \n', lintResult);
              } catch (err) {
                console.log('[ESLint merged] error: ', err);
              } finally {
                restoreParserOptions();
              }
              // 将合并结果文件赋给每个子类型，后续 parseResult 从同一文件读取并按 ext 过滤
              _iterator4 = _createForOfIteratorHelper(eslintKeys);
              try {
                for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
                  k = _step4.value;
                  fileMap[k].outputFile = mergedOutputFile;
                  fileMap[k].isMerged = true;
                }
              } catch (err) {
                _iterator4.e(err);
              } finally {
                _iterator4.f();
              }
            }
            // StyleLint：各类型单独执行（stylelint 不支持多 glob 合并输出）
            _iterator5 = _createForOfIteratorHelper(stylelintKeys);
            try {
              for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
                key = _step5.value;
                outputFile = innerExecCommand(key, fileMap[key]);
                fileMap[key].outputFile = outputFile;
              }
            } catch (err) {
              _iterator5.e(err);
            } finally {
              _iterator5.f();
            }
          } else {
            // 增量模式或只有一种类型，逐个执行
            keys.forEach(function (key) {
              var outputFile = innerExecCommand(key, fileMap[key]);
              fileMap[key].outputFile = outputFile;
            });
          }
          _parseResult = parseResult({
            fileMap: fileMap
          }), errorMap = _parseResult.errorMap;
          Object.keys(fileMap).forEach(function (key) {
            fileMap[key].errorFiles = errorMap[key].errorFiles;
            fileMap[key].total = errorMap[key].total;
          });
          duration = Date.now() - startTime;
          hasError = !!Object.values(fileMap).find(function (item) {
            return item.total;
          }); // autoFix 需要在 onReport 之前执行，确保 fixMR 信息可传给 onReport
          if (!(autoFixMR && hasError)) {
            _context4.next = 3;
            break;
          }
          _context4.next = 2;
          return autoFixAndCreateMR({
            fileMap: fileMap,
            workspace: workspace,
            sourceBranch: sourceBranch,
            targetBranch: targetBranch,
            repo: repo,
            privateToken: privateToken,
            gitApiPrefix: gitApiPrefix,
            mrTitlePrefix: mrTitlePrefix
          });
        case 2:
          fixMRList = _context4.sent;
        case 3:
          if (!onReport) {
            _context4.next = 7;
            break;
          }
          errorDetails = Object.keys(fileMap).map(function (key) {
            var _a, _b, _c;
            return {
              fileType: key,
              errorCount: (_a = fileMap[key].total) !== null && _a !== void 0 ? _a : 0,
              fileCount: (_c = (_b = fileMap[key].errorFiles) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0
            };
          });
          totalErrors = errorDetails.reduce(function (acc, item) {
            return acc + item.errorCount;
          }, 0);
          _context4.prev = 4;
          _context4.next = 5;
          return onReport({
            totalErrors: totalErrors,
            errorDetails: errorDetails,
            checkAll: !!checkAll,
            mrId: mrId,
            repo: repo,
            sourceBranch: sourceBranch,
            targetBranch: targetBranch,
            passed: totalErrors === 0,
            duration: duration,
            lintFiles: Object.keys(fileMap),
            fileMap: fileMap,
            fixMRList: fixMRList
          });
        case 5:
          _context4.next = 7;
          break;
        case 6:
          _context4.prev = 6;
          _t4 = _context4["catch"](4);
          console.log('[onReport] error: ', _t4);
        case 7:
          commentSuccess = false;
          if (!mrId) {
            _context4.next = 12;
            break;
          }
          message = genRobotMessage({
            fileMap: fileMap,
            checkAll: checkAll,
            mrUrl: mrUrl,
            sourceBranch: sourceBranch,
            targetBranch: targetBranch,
            buildUrl: buildUrl,
            docLink: docLink,
            repo: repo,
            repoUrl: repoUrl,
            mentionList: mentionList,
            workspace: workspace
          });
          _context4.prev = 8;
          _context4.next = 9;
          return lint_git.createMRComment({
            projectName: repo,
            mrId: mrId,
            data: message,
            privateToken: privateToken,
            gitApiPrefix: gitApiPrefix
          });
        case 9:
          commentSuccess = _context4.sent;
          _context4.next = 11;
          break;
        case 10:
          _context4.prev = 10;
          _context4["catch"](8);
        case 11:
          console.log('[commentSuccess]', commentSuccess);
        case 12:
          getPostFix = function getPostFix() {
            if (!mrId) return '';
            return commentSuccess ? '评论成功' : '评论失败';
          };
          robotMessage = genRobotMessage({
            fileMap: fileMap,
            postFix: getPostFix(),
            mrUrl: mrUrl,
            sourceBranch: sourceBranch,
            targetBranch: targetBranch,
            buildUrl: buildUrl,
            docLink: docLink,
            checkAll: checkAll,
            repo: repo,
            repoUrl: repoUrl,
            mentionList: mentionList,
            workspace: workspace
          });
          console.log('[robotMessage]: \n', robotMessage);
          _context4.prev = 13;
          _context4.next = 14;
          return wecomRobot_batchSend.batchSendWxRobotMarkdown({
            content: robotMessage,
            chatId: chatId,
            webhookUrl: webhookUrl
          });
        case 14:
          _context4.next = 16;
          break;
        case 15:
          _context4.prev = 15;
          _t6 = _context4["catch"](13);
          console.log('[batchSendWxRobotMarkdown] err', _t6);
        case 16:
          if (!mrId) {
            _context4.next = 19;
            break;
          }
          _i = 0, _Object$keys = Object.keys(fileMap);
        case 17:
          if (!(_i < _Object$keys.length)) {
            _context4.next = 19;
            break;
          }
          _key2 = _Object$keys[_i];
          _context4.next = 18;
          return tryCreateMRNote({
            projectName: repo,
            mrId: mrId,
            errorFiles: fileMap[_key2].errorFiles || [],
            workspace: workspace,
            privateToken: privateToken,
            gitApiPrefix: gitApiPrefix,
            isScss: fileMap[_key2].isStyle
          });
        case 18:
          _i++;
          _context4.next = 17;
          break;
        case 19:
          if (!(throwError && hasError)) {
            _context4.next = 20;
            break;
          }
          throw new Error('Lint 检查不通过！');
        case 20:
          return _context4.abrupt("return", fileMap);
        case 21:
        case "end":
          return _context4.stop();
      }
    }, _callee4, null, [[4, 6], [8, 10], [13, 15]]);
  }));
}
function getErrorInfo(result) {
  var errorFiles = result.filter(function (item) {
    return item.errorCount;
  });
  var total = errorFiles.reduce(function (acc, file) {
    acc += file.errorCount || 0;
    return acc;
  }, 0);
  return {
    total: total,
    errorFiles: errorFiles
  };
}
var readyFile = function readyFile(file) {
  if (!nodejs_fs.getFs().existsSync(file)) {
    fs_fs.writeFileSync(file, [], true);
    return [];
  }
  return fs_fs.readFileSync(file, true);
};
var parseErrorResult = function parseErrorResult(key, info) {
  if (!info.outputFile || !nodejs_fs.getFs().existsSync(info.outputFile)) {
    return {
      total: 0,
      errorFiles: []
    };
  }
  var content = readyFile(info.outputFile);
  // 全量模式下多个文件类型共用同一个合并输出文件，需要按扩展名过滤，避免数据重复
  if (info.isMerged && !info.isStyle) {
    var ext = ".".concat(key);
    content = content.filter(function (item) {
      var fp = item.filePath || '';
      return fp.endsWith(ext);
    });
  }
  console.log("[result] ".concat(key, ": \n"), JSON.stringify(content, null, 2));
  var resultTotal = 0;
  var resultErrorFiles = [];
  if (info.isStyle) {
    var parsed = content.filter(function (item) {
      var _a;
      return (_a = item.warnings) === null || _a === void 0 ? void 0 : _a.length;
    }).map(function (item) {
      return Object.assign(Object.assign({}, item), {
        errorCount: item.warnings.filter(function (warn) {
          return warn.severity === 'error';
        }).length
      });
    });
    var _getErrorInfo = getErrorInfo(parsed),
      total = _getErrorInfo.total,
      errorFiles = _getErrorInfo.errorFiles;
    resultTotal = total;
    resultErrorFiles = errorFiles;
  } else {
    var _getErrorInfo2 = getErrorInfo(content),
      _total = _getErrorInfo2.total,
      _errorFiles = _getErrorInfo2.errorFiles;
    resultTotal = _total;
    resultErrorFiles = _errorFiles;
  }
  return {
    total: resultTotal,
    errorFiles: resultErrorFiles
  };
};
function parseResult(_ref5) {
  var fileMap = _ref5.fileMap;
  var errorMap = {};
  Object.keys(fileMap).forEach(function (key) {
    errorMap[key] = parseErrorResult(key, fileMap[key]);
  });
  return {
    errorMap: errorMap
  };
}
function genRobotMessage(_ref6) {
  var fileMap = _ref6.fileMap,
    mrUrl = _ref6.mrUrl,
    sourceBranch = _ref6.sourceBranch,
    targetBranch = _ref6.targetBranch,
    buildUrl = _ref6.buildUrl,
    docLink = _ref6.docLink,
    repo = _ref6.repo,
    repoUrl = _ref6.repoUrl,
    postFix = _ref6.postFix,
    _ref6$checkAll = _ref6.checkAll,
    checkAll = _ref6$checkAll === void 0 ? false : _ref6$checkAll,
    _ref6$mentionList = _ref6.mentionList,
    mentionList = _ref6$mentionList === void 0 ? [] : _ref6$mentionList,
    workspace = _ref6.workspace;
  var postFixList = postFix ? [postFix] : [];
  var repoAndMrInfo = lint_message.genReportInfo({
    workspace: workspace,
    mrUrl: mrUrl,
    sourceBranch: sourceBranch,
    targetBranch: targetBranch,
    repo: repo,
    repoUrl: repoUrl,
    checkAll: checkAll
  });
  var allTotal = Object.values(fileMap).reduce(function (acc, item) {
    var _a;
    return acc + ((_a = item.total) !== null && _a !== void 0 ? _a : 0);
  }, 0);
  if (!allTotal) {
    return [lint_message.genTitle('✅', checkAll)].concat(_toConsumableArray__default["default"](repoAndMrInfo), ['未发现代码规范异常'], postFixList).join('，');
  }
  var lintErrorMessageList = Object.keys(fileMap).filter(function (item) {
    return !!fileMap[item].total;
  }).map(function (key) {
    var info = fileMap[key];
    var total = info.total,
      errorFiles = info.errorFiles;
    return "- **".concat(key.toUpperCase(), " \u9519\u8BEF**\uFF1A").concat(total && (errorFiles === null || errorFiles === void 0 ? void 0 : errorFiles.length) ? "".concat(errorFiles === null || errorFiles === void 0 ? void 0 : errorFiles.length, "\u4E2A\u6587\u4EF6").concat(total, "\u4E2A\u9519\u8BEF") : '无');
  });
  return [[lint_message.genTitle('⚠️', checkAll)].concat(_toConsumableArray__default["default"](repoAndMrInfo), ["\u53EF\u5728[\u6D41\u6C34\u7EBF](".concat(buildUrl, ")\u4E2D\u67E5\u770B\u8BE6\u60C5\uFF0C\u6216\u672C\u5730\u8FD0\u884C `npx eslint --fix file` \u7B49\u547D\u4EE4"), docLink ? "[\u8BF4\u660E\u6587\u6863](".concat(docLink, ")") : '', mentionList.filter(function (mention) {
    return mention;
  }).map(function (mention) {
    return "<@".concat(mention, ">");
  }).join('')], postFixList).filter(function (item) {
    return item;
  }).join('，')].concat(_toConsumableArray__default["default"](lintErrorMessageList)).join('\n');
}
function getDiffFile(_ref7) {
  var sourceBranch = _ref7.sourceBranch,
    targetBranch = _ref7.targetBranch,
    workspace = _ref7.workspace;
  node_nodeCommand.execCommand("git clean -df && git reset --hard HEAD && git checkout ".concat(targetBranch, " && git pull && git submodule update --init"), workspace, 'inherit');
  node_nodeCommand.execCommand("git checkout ".concat(sourceBranch, " && git reset --hard \"origin/").concat(sourceBranch, "\" && git pull && git submodule update --init"), workspace, 'inherit');
  var list = node_nodeCommand.execCommand("git diff --name-only ".concat(sourceBranch, " ").concat(targetBranch), workspace, {
    stdio: 'pipe',
    line: -1
  }).split('\n').map(function (item) {
    return item.trim();
  }).filter(function (item) {
    return item;
  }).filter(function (item) {
    return nodejs_fs.getFs().existsSync(nodejs_path.getPath().resolve(workspace, item));
  });
  console.log('diff list: ', JSON.stringify(list, null, 2));
  var diffFilesMap = {};
  Object.keys(lint_config.FILE_TYPE_MAP).forEach(function (key) {
    var reg = lint_config.FILE_TYPE_MAP[key].reg;
    var files = list.filter(function (item) {
      return reg.test(item);
    });
    diffFilesMap[key] = files.join(' ');
  });
  return {
    diffFilesMap: diffFilesMap
  };
}

exports.autoFixAndCreateMR = autoFixAndCreateMR;
exports.checkLint = checkLint;
exports.genFixBranchName = genFixBranchName;
exports.getErrorInfo = getErrorInfo;
exports.parseJSFiles = parseJSFiles;
exports.parseScssFiles = parseScssFiles;
