/**
 * 文件 diff 计算工具
 * 纯计算逻辑，不包含任何 UI 渲染
 */

export interface DiffLine {
  type: 'add' | 'remove' | 'context';
  lineNumber: number | null;
  content: string;
}

export interface DiffResult {
  oldContent: string | null;
  newContent: string;
  isNew: boolean;
  hunks: DiffHunk[];
}

export interface DiffHunk {
  oldStart: number;
  oldCount: number;
  newStart: number;
  newCount: number;
  lines: DiffLine[];
}

/**
 * 计算两个字符串的 diff
 * 使用简化的 LCS (最长公共子序列) 算法
 */
export function computeDiff(oldContent: string | null, newContent: string): DiffResult {
  const isNew = oldContent === null;
  const oldLines = oldContent ? oldContent.split('\n') : [];
  const newLines = newContent.split('\n');

  if (isNew) {
    // 新文件，所有行都是新增
    return {
      oldContent,
      newContent,
      isNew: true,
      hunks: [{
        oldStart: 0,
        oldCount: 0,
        newStart: 1,
        newCount: newLines.length,
        lines: newLines.map((line, i) => ({
          type: 'add' as const,
          lineNumber: i + 1,
          content: line,
        })),
      }],
    };
  }

  // 计算 diff hunks
  const hunks = computeHunks(oldLines, newLines);

  return {
    oldContent,
    newContent,
    isNew: false,
    hunks,
  };
}

/**
 * 计算 diff hunks
 */
function computeHunks(oldLines: string[], newLines: string[]): DiffHunk[] {
  // 使用简化的 diff 算法
  const lcs = computeLCS(oldLines, newLines);
  const hunks: DiffHunk[] = [];

  let oldIdx = 0;
  let newIdx = 0;
  let lcsIdx = 0;
  let currentHunk: DiffHunk | null = null;

  const CONTEXT_LINES = 3;

  while (oldIdx < oldLines.length || newIdx < newLines.length) {
    const lcsLine = lcsIdx < lcs.length ? lcs[lcsIdx] : null;

    // 检查是否匹配 LCS
    const oldMatch = lcsLine !== null && oldIdx < oldLines.length && oldLines[oldIdx] === lcsLine.content;
    const newMatch = lcsLine !== null && newIdx < newLines.length && newLines[newIdx] === lcsLine.content;

    if (oldMatch && newMatch) {
      // 上下文行
      if (currentHunk) {
        currentHunk.lines.push({
          type: 'context',
          lineNumber: newIdx + 1,
          content: newLines[newIdx],
        });
        currentHunk.oldCount++;
        currentHunk.newCount++;
      }
      oldIdx++;
      newIdx++;
      lcsIdx++;
    } else if (!oldMatch && oldIdx < oldLines.length && (lcsLine === null || oldLines[oldIdx] !== lcsLine.content)) {
      // 删除行
      if (!currentHunk) {
        currentHunk = {
          oldStart: oldIdx + 1,
          oldCount: 0,
          newStart: newIdx + 1,
          newCount: 0,
          lines: [],
        };
      }
      currentHunk.lines.push({
        type: 'remove',
        lineNumber: oldIdx + 1,
        content: oldLines[oldIdx],
      });
      currentHunk.oldCount++;
      oldIdx++;
    } else if (!newMatch && newIdx < newLines.length) {
      // 新增行
      if (!currentHunk) {
        currentHunk = {
          oldStart: oldIdx + 1,
          oldCount: 0,
          newStart: newIdx + 1,
          newCount: 0,
          lines: [],
        };
      }
      currentHunk.lines.push({
        type: 'add',
        lineNumber: newIdx + 1,
        content: newLines[newIdx],
      });
      currentHunk.newCount++;
      newIdx++;
    } else {
      // 匹配但还没到
      if (currentHunk && currentHunk.lines.length > 0) {
        // 检查是否应该结束当前 hunk
        const lastNonContext = [...currentHunk.lines].reverse().findIndex(l => l.type !== 'context');
        if (lastNonContext > CONTEXT_LINES) {
          hunks.push(currentHunk);
          currentHunk = null;
        }
      }
      oldIdx++;
      newIdx++;
      if (lcsLine) lcsIdx++;
    }
  }

  if (currentHunk && currentHunk.lines.some(l => l.type !== 'context')) {
    hunks.push(currentHunk);
  }

  // 如果没有实际变化，返回空
  if (hunks.length === 0 && oldLines.join('\n') !== newLines.join('\n')) {
    // 全文替换的情况
    return [{
      oldStart: 1,
      oldCount: oldLines.length,
      newStart: 1,
      newCount: newLines.length,
      lines: [
        ...oldLines.map((line, i) => ({
          type: 'remove' as const,
          lineNumber: i + 1,
          content: line,
        })),
        ...newLines.map((line, i) => ({
          type: 'add' as const,
          lineNumber: i + 1,
          content: line,
        })),
      ],
    }];
  }

  return hunks;
}

/**
 * 计算最长公共子序列
 */
function computeLCS(oldLines: string[], newLines: string[]): Array<{ content: string; oldIdx: number; newIdx: number }> {
  const m = oldLines.length;
  const n = newLines.length;

  // DP 表
  const dp: number[][] = Array(m + 1).fill(null).map(() => Array(n + 1).fill(0));

  for (let i = 1; i <= m; i++) {
    for (let j = 1; j <= n; j++) {
      if (oldLines[i - 1] === newLines[j - 1]) {
        dp[i][j] = dp[i - 1][j - 1] + 1;
      } else {
        dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
      }
    }
  }

  // 回溯找出 LCS
  const result: Array<{ content: string; oldIdx: number; newIdx: number }> = [];
  let i = m, j = n;

  while (i > 0 && j > 0) {
    if (oldLines[i - 1] === newLines[j - 1]) {
      result.unshift({ content: oldLines[i - 1], oldIdx: i - 1, newIdx: j - 1 });
      i--;
      j--;
    } else if (dp[i - 1][j] > dp[i][j - 1]) {
      i--;
    } else {
      j--;
    }
  }

  return result;
}

/**
 * 统计变更数量
 */
export function countChanges(diff: DiffResult): { additions: number; deletions: number } {
  let additions = 0;
  let deletions = 0;

  for (const hunk of diff.hunks) {
    for (const line of hunk.lines) {
      if (line.type === 'add') additions++;
      if (line.type === 'remove') deletions++;
    }
  }

  return { additions, deletions };
}
