/**
 * 编辑内容解析器
 *
 * 将各种格式的编辑指令解析为统一的 Edit 对象
 */

import type {
  Edit,
  WholeFileEdit,
  SearchReplaceEdit,
  SearchReplaceBlock,
  DiffEdit,
} from './types.js';

/**
 * 解析搜索替换块
 *
 * 支持多种格式：
 * 1. 简单格式: { search: "...", replace: "..." }
 * 2. 标记格式:
 *    <<<<<<< SEARCH
 *    要搜索的内容
 *    =======
 *    替换后的内容
 *    >>>>>>> REPLACE
 */
export function parseSearchReplaceBlocks(content: string): SearchReplaceBlock[] {
  const blocks: SearchReplaceBlock[] = [];

  // 尝试解析标记格式
  const markerPattern = /<<<<<<<?[ ]*SEARCH\n([\s\S]*?)\n?=======\n?([\s\S]*?)\n?>>>>>>>?[ ]*REPLACE/g;
  let match;

  while ((match = markerPattern.exec(content)) !== null) {
    blocks.push({
      search: match[1],
      replace: match[2],
    });
  }

  // 如果找到了标记格式的块，直接返回
  if (blocks.length > 0) {
    return blocks;
  }

  // 尝试解析 JSON 数组格式
  try {
    const parsed = JSON.parse(content);
    if (Array.isArray(parsed)) {
      for (const item of parsed) {
        if (typeof item.search === 'string' && typeof item.replace === 'string') {
          blocks.push({
            search: item.search,
            replace: item.replace,
          });
        }
      }
      return blocks;
    }
  } catch {
    // 不是 JSON 格式，继续
  }

  return blocks;
}

/**
 * 创建整文件替换编辑
 */
export function createWholeFileEdit(filePath: string, content: string): WholeFileEdit {
  return {
    mode: 'whole',
    filePath,
    content,
  };
}

/**
 * 创建搜索替换编辑
 */
export function createSearchReplaceEdit(
  filePath: string,
  blocks: SearchReplaceBlock[]
): SearchReplaceEdit {
  return {
    mode: 'search-replace',
    filePath,
    blocks,
  };
}

/**
 * 创建单个搜索替换编辑
 */
export function createSingleSearchReplaceEdit(
  filePath: string,
  search: string,
  replace: string
): SearchReplaceEdit {
  return {
    mode: 'search-replace',
    filePath,
    blocks: [{ search, replace }],
  };
}

/**
 * 创建 Diff 编辑
 */
export function createDiffEdit(filePath: string, patch: string): DiffEdit {
  return {
    mode: 'diff',
    filePath,
    patch,
  };
}

/**
 * 从统一 diff 格式解析编辑
 *
 * 支持标准的 unified diff 格式：
 * --- a/file.txt
 * +++ b/file.txt
 * @@ -1,3 +1,4 @@
 *  context line
 * -removed line
 * +added line
 *  context line
 */
export function parseDiffPatch(patch: string): Map<string, string> {
  const filePatches = new Map<string, string>();

  // 按文件分割
  const filePattern = /^diff --git a\/(.*) b\/(.*)$/gm;
  const sections = patch.split(/(?=^diff --git)/m).filter(Boolean);

  for (const section of sections) {
    const headerMatch = section.match(/^diff --git a\/(.*) b\/(.*)$/m);
    if (headerMatch) {
      const filePath = headerMatch[2];
      filePatches.set(filePath, section);
    }
  }

  return filePatches;
}

/**
 * 应用统一 diff 补丁到内容
 *
 * 简化实现：提取搜索替换块
 */
export function applyDiffPatch(originalContent: string, patch: string): string {
  const lines = originalContent.split('\n');
  const patchLines = patch.split('\n');
  const result: string[] = [];

  let lineIndex = 0;
  let patchIndex = 0;

  // 跳过 diff 头部
  while (patchIndex < patchLines.length && !patchLines[patchIndex].startsWith('@@')) {
    patchIndex++;
  }

  while (patchIndex < patchLines.length) {
    const line = patchLines[patchIndex];

    if (line.startsWith('@@')) {
      // 解析 hunk 头部: @@ -start,count +start,count @@
      const hunkMatch = line.match(/@@ -(\d+),?(\d*) \+(\d+),?(\d*) @@/);
      if (hunkMatch) {
        const oldStart = parseInt(hunkMatch[1], 10);

        // 复制 hunk 之前的未修改行
        while (lineIndex < oldStart - 1 && lineIndex < lines.length) {
          result.push(lines[lineIndex]);
          lineIndex++;
        }
      }
      patchIndex++;
      continue;
    }

    if (line.startsWith('+') && !line.startsWith('+++')) {
      // 新增行
      result.push(line.slice(1));
      patchIndex++;
    } else if (line.startsWith('-') && !line.startsWith('---')) {
      // 删除行 - 跳过原始内容
      lineIndex++;
      patchIndex++;
    } else if (line.startsWith(' ') || line === '') {
      // 上下文行
      if (lineIndex < lines.length) {
        result.push(lines[lineIndex]);
        lineIndex++;
      }
      patchIndex++;
    } else {
      patchIndex++;
    }
  }

  // 复制剩余的原始行
  while (lineIndex < lines.length) {
    result.push(lines[lineIndex]);
    lineIndex++;
  }

  return result.join('\n');
}

/**
 * 检测编辑模式
 *
 * 根据内容特征自动检测合适的编辑模式
 */
export function detectEditMode(content: string, fileSize: number): 'whole' | 'search-replace' | 'diff' {
  // 检测 diff 格式
  if (content.includes('diff --git') || content.match(/^@@\s+-\d+,?\d*\s+\+\d+,?\d*\s+@@/m)) {
    return 'diff';
  }

  // 检测搜索替换标记格式
  if (content.includes('<<<<<<< SEARCH') || content.includes('<<<<<<SEARCH')) {
    return 'search-replace';
  }

  // 大文件优先使用 search-replace（如果有明显的结构）
  if (fileSize > 50 * 1024) { // 50KB
    return 'search-replace';
  }

  // 默认使用 whole
  return 'whole';
}

/**
 * 规范化搜索字符串
 *
 * 处理常见的格式问题：
 * - 行尾空格
 * - 不同的换行符
 * - 缩进差异
 */
export function normalizeSearchString(search: string, options: {
  trimTrailingWhitespace?: boolean;
  normalizeLineEndings?: boolean;
  normalizeIndentation?: boolean;
} = {}): string {
  let result = search;

  // 规范化换行符
  if (options.normalizeLineEndings !== false) {
    result = result.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
  }

  // 去除行尾空格
  if (options.trimTrailingWhitespace) {
    result = result.split('\n').map(line => line.trimEnd()).join('\n');
  }

  return result;
}

/**
 * 在内容中查找搜索字符串的位置
 */
export function findSearchPositions(content: string, search: string): number[] {
  const positions: number[] = [];
  let pos = 0;

  while (true) {
    const index = content.indexOf(search, pos);
    if (index === -1) break;
    positions.push(index);
    pos = index + 1;
  }

  return positions;
}

/**
 * 获取搜索字符串在内容中的行号
 */
export function getSearchLineNumbers(content: string, search: string): number[] {
  const positions = findSearchPositions(content, search);
  const lineNumbers: number[] = [];

  for (const pos of positions) {
    const lineNumber = content.slice(0, pos).split('\n').length;
    lineNumbers.push(lineNumber);
  }

  return lineNumbers;
}
