'use strict';

var chunk4UERBOUH_cjs = require('./chunk-4UERBOUH.cjs');
var chunkAF3E2D32_cjs = require('./chunk-AF3E2D32.cjs');
var napi = require('@ast-grep/napi');
var types = require('@storm-software/config-tools/types');
var readFile = require('@stryke/fs/read-file');
var deepClone = require('@stryke/helpers/deep-clone');
var isEqual = require('@stryke/helpers/is-equal');
var mutex$1 = require('@stryke/helpers/mutex');
var stormJson = require('@stryke/json/storm-json');
var joinPaths = require('@stryke/path/join-paths');
var defu = require('defu');
var fs = require('fs');

function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }

var defu__default = /*#__PURE__*/_interopDefault(defu);

var mutex = new mutex$1.Mutex();
function getLatestErrorCode(type = "general", errorCodes = {}) {
  if (!errorCodes[type]) {
    return "1";
  }
  const keys = Object.keys(errorCodes[type]);
  if (keys.length === 0) {
    return "1";
  }
  const errorCode = Number.parseInt(keys.sort((a, b) => b.localeCompare(a))[0]);
  if (Number.isNaN(errorCode)) {
    return "1";
  }
  return String(errorCode + 1);
}
chunkAF3E2D32_cjs.__name(getLatestErrorCode, "getLatestErrorCode");
async function transformErrors(log, source, context) {
  const errorCodesFilePath = joinPaths.joinPaths(context.workspaceConfig.workspaceRoot, context.options.errorsFile);
  let errorCodes = {};
  if (!fs.existsSync(errorCodesFilePath)) {
    log(types.LogLevelLabel.WARN, `No error codes file path exists. Writing empty file.`);
    await chunk4UERBOUH_cjs.writeFile(log, errorCodesFilePath, stormJson.StormJSON.stringify({}));
  } else {
    errorCodes = await readFile.readJsonFile(errorCodesFilePath);
  }
  const originalErrorCodes = deepClone.deepClone(errorCodes);
  const ast = await napi.parseAsync(napi.Lang.TypeScript, source.code.toString());
  const root = ast.root();
  const nodes = root.findAll({
    rule: {
      kind: "new_expression",
      any: [
        {
          pattern: "new Error($$$ARGS)"
        },
        {
          pattern: "new TypeError($$$ARGS)"
        },
        {
          pattern: "new ReferenceError($$$ARGS)"
        },
        {
          pattern: "new SyntaxError($$$ARGS)"
        },
        {
          pattern: "new RangeError($$$ARGS)"
        },
        {
          pattern: "new EvalError($$$ARGS)"
        },
        {
          pattern: "new URIError($$$ARGS)"
        },
        {
          pattern: "new AggregateError($$$ARGS)"
        },
        {
          pattern: "new InternalError($$$ARGS)"
        },
        {
          pattern: "new SystemError($$$ARGS)"
        },
        {
          pattern: "new NotImplementedError($$$ARGS)"
        },
        {
          pattern: "new StormError($$$ARGS)"
        }
      ]
    }
  });
  if (!nodes || nodes.length === 0) {
    log(types.LogLevelLabel.TRACE, `No error messages require transformation in ${source.id}.`);
    return source;
  }
  for (const node of nodes) {
    const args = node.getMultipleMatches("ARGS").filter((arg) => arg.kind() === "string" || arg.kind() === "template_string");
    if (args.length >= 1 && args[0]) {
      let message = "";
      const params = [];
      if (args[0].kind() === "string") {
        message = args[0].text().slice(1, -1);
      } else if (args[0].kind() === "template_string") {
        for (const node2 of args[0].children()) {
          if (node2.kind() === "string_fragment") {
            message += node2.text();
          } else if (node2.kind() === "template_substitution") {
            const param = node2.text().slice(2, -1);
            if (param) {
              params.push(param);
              message += "%s";
            }
          }
        }
      }
      if (message) {
        let type = "general";
        if (args.length > 1 && args[1]) {
          const text = args[1].text();
          if (text) {
            type = text;
          }
        }
        errorCodes[type] ??= {};
        let code = Object.keys(errorCodes[type] ?? {}).find((key) => errorCodes[type]?.[key] === message);
        if (!code) {
          code = getLatestErrorCode(type, errorCodes);
          log(types.LogLevelLabel.INFO, `Found unlisted error message "${message}" in ${source.id}. Assigning it to "${type}" code #${code}.`);
          errorCodes[type] ??= {};
          errorCodes[type][code] = message;
        }
        source.code = source.code.replaceAll(node.text(), `new StormError({ type: "${type}", code: ${code}${params.length > 0 ? ` params: [${params.join(", ")}] ` : ""} })`);
      }
    }
  }
  if (!isEqual.isEqual(originalErrorCodes, errorCodes)) {
    log(types.LogLevelLabel.INFO, `Adding error messages from ${source.id} to ${context.options.errorsFile}.`);
    await mutex.acquire();
    try {
      await chunk4UERBOUH_cjs.writeFile(log, errorCodesFilePath, stormJson.StormJSON.stringify(defu__default.default(errorCodes, await readFile.readJsonFile(errorCodesFilePath))));
    } finally {
      mutex.release();
    }
  }
  return source;
}
chunkAF3E2D32_cjs.__name(transformErrors, "transformErrors");

exports.transformErrors = transformErrors;
//# sourceMappingURL=chunk-ZW7CBT5E.cjs.map
//# sourceMappingURL=chunk-ZW7CBT5E.cjs.map