/**
 * Line diff — one copy, for every surface that shows what changed.
 *
 * WHY THIS FILE EXISTS. The same LCS walk was written out three times:
 * privately in `useAssist.ts`, and again inside `HistoryPanel.vue` and
 * `VersionHistorySection.vue`. The three were character-identical apart from
 * quote style — nobody had diverged them on purpose, they were simply copied
 * because `computeDiff` was never exported. Milestone 323 needed a fourth
 * consumer (a rule's edit history), and a fourth copy is the cost #3207
 * records: a fix or an improvement now has to be found in N places by someone
 * who does not know N.
 */

export interface DiffLine {
  type: "equal" | "delete" | "insert";
  text: string;
}

/**
 * Diff `a` against `b`, line by line.
 *
 * `delete` lines come from `a`, `insert` lines from `b` — so the caller
 * decides which side reads as "before" by which argument it passes. Every
 * caller here passes the CURRENT text as `a` and the older text as `b`, so a
 * deletion is what the old version had and an insertion is what replaced it.
 *
 * O(m·n) in time and memory: fine for a note or a rule, and deliberately not
 * generalised further, since nothing here diffs a file of thousands of lines.
 */
export function computeDiff(a: string, b: string): DiffLine[] {
  const aLines = a.split("\n");
  const bLines = b.split("\n");
  const m = aLines.length, n = bLines.length;
  const dp: number[][] = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
  for (let i = m - 1; i >= 0; i--)
    for (let j = n - 1; j >= 0; j--)
      dp[i][j] = aLines[i] === bLines[j]
        ? dp[i + 1][j + 1] + 1
        : Math.max(dp[i + 1][j], dp[i][j + 1]);
  const result: DiffLine[] = [];
  let i = 0, j = 0;
  while (i < m && j < n) {
    if (aLines[i] === bLines[j]) { result.push({ type: "equal", text: aLines[i++] }); j++; }
    else if (dp[i + 1][j] >= dp[i][j + 1]) result.push({ type: "delete", text: aLines[i++] });
    else result.push({ type: "insert", text: bLines[j++] });
  }
  while (i < m) result.push({ type: "delete", text: aLines[i++] });
  while (j < n) result.push({ type: "insert", text: bLines[j++] });
  return result;
}
