import { describe, it, expect } from "vitest";
import { lineDiff, diffStat } from "./diff";

describe("lineDiff", () => {
  it("完全相同 → 全 eq", () => {
    const d = lineDiff("a\nb\nc", "a\nb\nc");
    expect(d.every((l) => l.op === "eq")).toBe(true);
    expect(d.map((l) => l.text)).toEqual(["a", "b", "c"]);
  });

  it("纯新增行标 add", () => {
    const d = lineDiff("a\nc", "a\nb\nc");
    expect(d).toEqual([
      { op: "eq", text: "a" },
      { op: "add", text: "b" },
      { op: "eq", text: "c" },
    ]);
  });

  it("纯删除行标 del", () => {
    const d = lineDiff("a\nb\nc", "a\nc");
    expect(d).toEqual([
      { op: "eq", text: "a" },
      { op: "del", text: "b" },
      { op: "eq", text: "c" },
    ]);
  });

  it("替换 = del 旧 + add 新", () => {
    const d = lineDiff("hello\nworld", "hello\nthere");
    expect(d).toContainEqual({ op: "del", text: "world" });
    expect(d).toContainEqual({ op: "add", text: "there" });
    expect(d[0]).toEqual({ op: "eq", text: "hello" });
  });

  it("空 → 非空全是 add", () => {
    const d = lineDiff("", "x\ny");
    // 空串 split 出一个空行，故首行是 "" 的替换
    expect(d.filter((l) => l.op === "add").map((l) => l.text)).toContain("x");
    expect(d.filter((l) => l.op === "add").map((l) => l.text)).toContain("y");
  });

  it("保留公共子序列、只动差异块", () => {
    const d = lineDiff("1\n2\n3\n4", "1\nX\n3\n4");
    expect(d.filter((l) => l.op === "eq").map((l) => l.text)).toEqual(["1", "3", "4"]);
    expect(diffStat(d)).toEqual({ add: 1, del: 1 });
  });
});

describe("diffStat", () => {
  it("统计 add/del 行数", () => {
    expect(diffStat(lineDiff("a\nb", "a\nb\nc\nd"))).toEqual({ add: 2, del: 0 });
  });
});
