import _toConsumableArray from '@babel/runtime/helpers/toConsumableArray';

/**
 * 通用「搜索-替换」工具
 *
 * 适用场景：AI Agent / Code Mod 需要根据"搜索-替换对"对源文件进行原地修改的场景。
 *
 * 提供两个函数：
 *   - cleanLineNumberPrefix：清理 AI 输出 search/replace 块时常带的行号前缀（如 "12| " "12 | "）
 *   - applySearchReplace：在源代码中查找 search 并替换为 replace，按 "精确 → 行级 → 子串" 三级策略匹配
 */
/**
 * 清理 AI 输出 search/replace 块时常带的行号前缀
 *
 * AI 在生成搜索字符串时，有时会无意把行号也带上，导致与源文件无法精确匹配。
 * 本函数支持 5 种常见格式：
 *   - "12| code"   → "code"
 *   - "12 | code"  → "code"
 *   - "12  code"   → "code"  (多空格分隔，仅当首行匹配且行号递增时才认为是行号)
 *   - "12: code"   → "code"
 *   - "12. code"   → "code"
 *
 * 为避免误删（如某些 markdown / 注释开头是数字），仅当：
 *   - 首行能匹配到行号格式
 *   - 后续行行号严格递增（差值为 1）
 * 时才视为带行号前缀，全部清理。
 *
 * @param text 原始字符串（来自 AI 输出的 search/replace 块）
 * @returns 清理后的字符串；不像行号前缀时原样返回
 */
function cleanLineNumberPrefix(text) {
  if (!text) return text;
  var lines = text.split('\n');
  if (lines.length === 0) return text;
  // 5 种常见行号格式
  var patterns = [/^(\d+)\|\s?(.*)$/, /^(\d+)\s+\|\s?(.*)$/, /^(\d+)\s{2,}(.*)$/, /^(\d+):\s(.*)$/, /^(\d+)\.\s(.*)$/ // "12. code"
  ];
  // 先用首行确定使用哪种 pattern
  var detectedPattern = null;
  var firstLineNum = -1;
  for (var _i = 0, _patterns = patterns; _i < _patterns.length; _i++) {
    var pat = _patterns[_i];
    var m = lines[0].match(pat);
    if (m) {
      detectedPattern = pat;
      firstLineNum = parseInt(m[1], 10);
      break;
    }
  }
  if (!detectedPattern) return text;
  // 校验后续行行号严格递增
  var cleanedLines = [];
  for (var i = 0; i < lines.length; i += 1) {
    var line = lines[i];
    var _m = line.match(detectedPattern);
    if (!_m) {
      // 空行允许保留
      if (line.trim() === '') {
        cleanedLines.push(line);
        continue;
      }
      // 行号校验失败，原样返回
      return text;
    }
    var num = parseInt(_m[1], 10);
    if (i > 0 && num !== firstLineNum + i) {
      // 行号不连续，认为不是行号前缀
      return text;
    }
    cleanedLines.push(_m[2]);
  }
  return cleanedLines.join('\n');
}
/**
 * 在源代码中查找 search 并替换为 replace，按 3 级策略匹配
 *
 * 策略：
 *   1. 精确匹配：原样查找 search
 *   2. 行级匹配：去除每行首尾空白后逐行对比（应对 AI 输出与源文件缩进不一致）
 *   3. 子串匹配：查找首行 trim 后的子串位置，从该位置开始截取与 search 等长的范围替换
 *
 * @param source 源代码字符串
 * @param search 要查找的字符串（可能被 AI 带了行号前缀，函数会自动清理）
 * @param replace 替换为的新字符串（同上，自动清理行号前缀）
 * @returns 替换后的字符串；查找失败返回 null
 */
function applySearchReplace(fileContent, rawSearch, rawReplace) {
  // Level 1
  if (fileContent.includes(rawSearch)) {
    return {
      content: fileContent.replace(rawSearch, rawReplace),
      applied: true,
      matchLevel: 'exact'
    };
  }
  var searchLines = rawSearch.split('\n');
  var contentLines = fileContent.split('\n');
  // Level 2
  var trimEndMatch = findLineMatch(contentLines, searchLines, function (fileLine, searchLine) {
    return fileLine.trimEnd() === searchLine.trimEnd();
  });
  if (trimEndMatch >= 0) {
    return buildReplacedResult(contentLines, trimEndMatch, searchLines.length, rawReplace, 'trimEnd');
  }
  // Level 3
  var indentMatch = findLineMatch(contentLines, searchLines, function (fileLine, searchLine) {
    return fileLine.trimStart() === searchLine.trimStart();
  });
  if (indentMatch >= 0) {
    var adjustedReplace = adjustReplaceIndent(rawReplace, searchLines, contentLines, indentMatch);
    return buildReplacedResult(contentLines, indentMatch, searchLines.length, adjustedReplace, 'indentNormalize');
  }
  return {
    content: fileContent,
    applied: false,
    matchLevel: 'none'
  };
}
// ============ 内部工具函数 =====// ...省略其他代码...
// ==== 修改后代码 ====
function findLineMatch(contentLines, searchLines, compareFn) {
  for (var i = 0; i <= contentLines.length - searchLines.length; i += 1) {
    var matched = true;
    for (var j = 0; j < searchLines.length; j += 1) {
      if (!compareFn(contentLines[i + j], searchLines[j])) {
        matched = false;
        break;
      }
    }
    if (matched) return i;
  }
  return -1;
}
function buildReplacedResult(contentLines, matchStart, matchLength, replaceText, matchLevel) {
  var before = contentLines.slice(0, matchStart);
  var after = contentLines.slice(matchStart + matchLength);
  var replaceLines = replaceText.split('\n');
  return {
    content: [].concat(_toConsumableArray(before), _toConsumableArray(replaceLines), _toConsumableArray(after)).join('\n'),
    applied: true,
    matchLevel: matchLevel
  };
}
function leadingWhitespaceCount(line) {
  var m = line.match(/^(\s*)/);
  return m ? m[1].length : 0;
}
function leadingWhitespace(line) {
  var m = line.match(/^(\s*)/);
  return m ? m[1] : '';
}
function adjustReplaceIndent(rawReplace, searchLines, contentLines, matchStart) {
  var searchFirstNonEmpty = searchLines.find(function (l) {
    return l.trim().length > 0;
  });
  var fileMatchLines = contentLines.slice(matchStart, matchStart + searchLines.length);
  var fileFirstNonEmpty = fileMatchLines.find(function (l) {
    return l.trim().length > 0;
  });
  if (!searchFirstNonEmpty || !fileFirstNonEmpty) return rawReplace;
  var searchIndent = leadingWhitespaceCount(searchFirstNonEmpty);
  var fileIndent = leadingWhitespaceCount(fileFirstNonEmpty);
  var delta = fileIndent - searchIndent;
  if (delta === 0) {
    var fileWhitespaceChar = leadingWhitespace(fileFirstNonEmpty).includes('\t') ? '\t' : ' ';
    var searchWhitespaceChar = leadingWhitespace(searchFirstNonEmpty).includes('\t') ? '\t' : ' ';
    if (fileWhitespaceChar === searchWhitespaceChar) return rawReplace;
    var _replaceLines = rawReplace.split('\n');
    return _replaceLines.map(function (line) {
      if (line.trim().length === 0) return line;
      var lw = leadingWhitespace(line);
      var rest = line.slice(lw.length);
      var newLw = lw.replace(searchWhitespaceChar === '\t' ? /\t/g : / /g, fileWhitespaceChar);
      return newLw + rest;
    }).join('\n');
  }
  var fileWhitespaceUnit = leadingWhitespace(fileFirstNonEmpty).includes('\t') ? '\t' : ' ';
  var replaceLines = rawReplace.split('\n');
  return replaceLines.map(function (line) {
    if (line.trim().length === 0) return line;
    if (delta > 0) return fileWhitespaceUnit.repeat(delta) + line;
    var lw = leadingWhitespace(line);
    var removeCount = Math.min(Math.abs(delta), lw.length);
    return line.slice(removeCount);
  }).join('\n');
}

export { applySearchReplace, cleanLineNumberPrefix };
