'use strict';

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

var _typeof = require('@babel/runtime/helpers/typeof');

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

var _typeof__default = /*#__PURE__*/_interopDefaultLegacy(_typeof);

/**
 * 通用 LLM 输出 JSON 容错解析
 *
 * 用于解析大语言模型（AI Agent）输出的 JSON：通常 LLM 输出的内容有以下几种 "脏" 情况：
 *   1. 直接就是合法 JSON
 *   2. JSON 被自然语言包围（"好的，下面是 JSON: { ... } 谢谢"）
 *   3. JSON 被 markdown 代码块包裹（```json { ... } ```）
 *   4. 因 token 上限被截断（缺少闭合的 ] 和 }）
 *
 * 本函数依次使用 5 层策略尽力解析：
 *   策略 1: 直接 JSON.parse
 *   策略 2: 提取第一个 `{` 到最后一个 `}` 之间的内容
 *   策略 3: 贪婪匹配最外层 markdown 代码块
 *   策略 4: 按括号平衡从第一个 `{` 开始匹配（应对尾部自然语言夹带）
 *   策略 5: token 截断时尝试补齐闭合符号（"、]、}）
 *
 * @param content LLM 返回的原始字符串
 * @param logTag  策略 5 触发时的日志前缀（默认 [AI]），便于上层区分调用方
 *
 * @example
 * ```ts
 * const result = parseLooseJson<{ name: string }>(aiResponseText);
 * if (result) console.log(result.name);
 * ```
 */
function parseLooseJson(content) {
  var logTag = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '[AI]';
  var trimmed = content.trim();
  var tryParse = function tryParse(str) {
    try {
      var _result = JSON.parse(str);
      if (_result && _typeof__default["default"](_result) === 'object') return _result;
    } catch (/* ignore */_a) {/* ignore */}
    return null;
  };
  // 策略 1: 直接解析
  var result = tryParse(trimmed);
  // 策略 2: 提取第一个 `{` 到最后一个 `}` 之间的内容
  if (!result) {
    var firstBrace = trimmed.indexOf('{');
    var lastBrace = trimmed.lastIndexOf('}');
    if (firstBrace !== -1 && lastBrace > firstBrace) {
      result = tryParse(trimmed.slice(firstBrace, lastBrace + 1));
    }
  }
  // 策略 3: 贪婪匹配最外层 markdown 代码块（从第一个 ``` 到最后一个 ```）
  if (!result) {
    var codeBlockMatch = trimmed.match(/```(?:json)?\s*([\s\S]*)```\s*$/);
    if (codeBlockMatch) {
      var inner = codeBlockMatch[1].trim();
      result = tryParse(inner);
      if (!result) {
        var _firstBrace = inner.indexOf('{');
        var _lastBrace = inner.lastIndexOf('}');
        if (_firstBrace !== -1 && _lastBrace > _firstBrace) {
          result = tryParse(inner.slice(_firstBrace, _lastBrace + 1));
        }
      }
    }
  }
  // 策略 4: 按括号平衡从第一个 `{` 开始匹配
  // 策略 2 是简单地取 "第一个{到最后一个}"，可能因为尾部有自然语言而匹配到错误范围。
  // 这里从第一个 `{` 开始，逐字符追踪括号层级和字符串上下文，找到顶层闭合位置。
  if (!result) {
    var startIdx = trimmed.indexOf('{');
    if (startIdx !== -1) {
      var depth = 0;
      var inString = false;
      var _escape = false;
      var endIdx = -1;
      for (var i = startIdx; i < trimmed.length; i += 1) {
        var ch = trimmed[i];
        if (_escape) {
          _escape = false;
          continue;
        }
        if (ch === '\\' && inString) {
          _escape = true;
          continue;
        }
        if (ch === '"') {
          inString = !inString;
          continue;
        }
        if (inString) continue;
        if (ch === '{') depth += 1;else if (ch === '}') {
          depth -= 1;
          if (depth === 0) {
            endIdx = i;
            break;
          }
        }
      }
      if (endIdx > startIdx) {
        result = tryParse(trimmed.slice(startIdx, endIdx + 1));
      }
    }
  }
  // 策略 5: JSON 被 token 截断时尝试修复
  // AI 输出可能因为 token 限制在中途截断，导致 JSON 不完整（如缺少闭合的 "]}"）。
  // 尝试从第一个 `{` 取到字符串末尾，逐步补上缺失的闭合符号。
  if (!result) {
    var _startIdx = trimmed.indexOf('{');
    if (_startIdx !== -1) {
      var jsonCandidate = trimmed.slice(_startIdx);
      // 移除尾部明显不属于 JSON 的内容（如 AI 在 JSON 后面追加的自然语言）
      var lastJsonChar = Math.max(jsonCandidate.lastIndexOf('}'), jsonCandidate.lastIndexOf(']'), jsonCandidate.lastIndexOf('"'));
      if (lastJsonChar > 0) {
        jsonCandidate = jsonCandidate.slice(0, lastJsonChar + 1);
      }
      // 计算缺失的闭合符号
      var depth2 = 0;
      var arrDepth = 0;
      var inStr = false;
      var esc = false;
      for (var _i = 0; _i < jsonCandidate.length; _i += 1) {
        var _ch = jsonCandidate[_i];
        if (esc) {
          esc = false;
          continue;
        }
        if (_ch === '\\' && inStr) {
          esc = true;
          continue;
        }
        if (_ch === '"') {
          inStr = !inStr;
          continue;
        }
        if (inStr) continue;
        if (_ch === '{') depth2 += 1;else if (_ch === '}') depth2 -= 1;else if (_ch === '[') arrDepth += 1;else if (_ch === ']') arrDepth -= 1;
      }
      // 如果在字符串内，先关闭字符串
      if (inStr) jsonCandidate += '"';
      // 补上缺失的 ] 和 }
      for (var a = 0; a < arrDepth; a += 1) jsonCandidate += ']';
      for (var b = 0; b < depth2; b += 1) jsonCandidate += '}';
      if (depth2 > 0 || arrDepth > 0 || inStr) {
        var closeParts = [];
        if (inStr) closeParts.push('1个"');
        if (arrDepth > 0) closeParts.push("".concat(arrDepth, "\u4E2A]"));
        if (depth2 > 0) closeParts.push("".concat(depth2, "\u4E2A}"));
        // eslint-disable-next-line no-console
        console.log("".concat(logTag, " parseLooseJson \u7B56\u75655: \u5C1D\u8BD5\u4FEE\u590D\u622A\u65AD\u7684 JSON (\u8865\u5145 ").concat(closeParts.join(''), ")"));
        result = tryParse(jsonCandidate);
      }
    }
  }
  return result;
}

exports.parseLooseJson = parseLooseJson;
