import { describe, expect, it } from "vitest";

import { applyConflictFix, hasApplicableFix } from "./applyFix";

describe("hasApplicableFix", () => {
  it("requires non-empty original and string replacement", () => {
    expect(hasApplicableFix({ original: "迈巴赫", replacement: "奔驰" })).toBe(true);
    // 空串=删除，仍可应用
    expect(hasApplicableFix({ original: "删我", replacement: "" })).toBe(true);
    expect(hasApplicableFix({ original: null, replacement: "奔驰" })).toBe(false);
    expect(hasApplicableFix({ original: "", replacement: "奔驰" })).toBe(false);
    expect(hasApplicableFix({ original: "迈巴赫", replacement: null })).toBe(false);
    expect(hasApplicableFix({ original: undefined, replacement: undefined })).toBe(
      false,
    );
  });

  it("narrows original/replacement to string when true (type predicate)", () => {
    const patch: { original: string | null; replacement: string | null } = {
      original: "迈巴赫",
      replacement: "奔驰",
    };
    if (!hasApplicableFix(patch)) throw new Error("expected applicable");
    // 编译期收窄：无需强转即可当 string 拼接（`as string` 已消除）。
    const combined: string = patch.original + patch.replacement;
    expect(combined).toBe("迈巴赫奔驰");
  });
});

describe("applyConflictFix", () => {
  it("replaces the first occurrence of original with replacement", () => {
    const out = applyConflictFix(
      "他乘坐迈巴赫扬长而去，迈巴赫的尾灯。",
      "迈巴赫",
      "奔驰",
    );
    expect(out.status).toBe("applied");
    expect(out.text).toBe("他乘坐奔驰扬长而去，迈巴赫的尾灯。");
  });

  it("returns not-found and leaves text untouched when original is absent (drift)", () => {
    const out = applyConflictFix("作者已经手改过的终稿。", "迈巴赫", "奔驰");
    expect(out.status).toBe("not-found");
    expect(out.text).toBe("作者已经手改过的终稿。");
  });

  it("returns no-patch when conflict carries no applicable patch", () => {
    const out = applyConflictFix("正文", null, null);
    expect(out.status).toBe("no-patch");
    expect(out.text).toBe("正文");
  });

  it("does not mutate the input string", () => {
    const original = "迈巴赫尾灯";
    applyConflictFix(original, "迈巴赫", "奔驰");
    expect(original).toBe("迈巴赫尾灯");
  });
});
