import { describe, expect, test } from "bun:test";

import { errorFailure, mismatchFailure, truncateActual } from "../../../../../src/server/checker/expect/failure";

describe("truncateActual", () => {
  test("短字符串不截断", () => {
    expect(truncateActual("hello")).toBe("hello");
  });

  test("恰好等于限制长度不截断", () => {
    const str = "a".repeat(200);
    expect(truncateActual(str)).toBe(str);
  });

  test("超过限制长度截断并加省略号与字符计数", () => {
    const str = "a".repeat(300);
    const result = truncateActual(str) as string;
    expect(result).toBe(`${"a".repeat(200)}…(共 300 字符)`);
    expect(result.includes("...")).toBe(false);
    expect(result.startsWith("a".repeat(200))).toBe(true);
  });

  test("自定义最大长度", () => {
    const str = "abcdefghij";
    const result = truncateActual(str, 5) as string;
    expect(result).toBe("abcde…(共 10 字符)");
  });

  test("null 不截断", () => {
    expect(truncateActual(null)).toBe(null);
  });

  test("undefined 不截断", () => {
    expect(truncateActual(undefined)).toBe(undefined);
  });

  test("标量不截断", () => {
    expect(truncateActual(42)).toBe(42);
    expect(truncateActual(123456789, 3)).toBe(123456789);
    expect(truncateActual(true, 3)).toBe(true);
  });

  test("对象序列化后超限时截断", () => {
    const result = truncateActual({ value: "x".repeat(20) }, 10) as string;
    expect(result.startsWith('{"value":"')).toBe(true);
    expect(result.endsWith("…(共 32 字符)")).toBe(true);
  });
});

describe("mismatchFailure", () => {
  test("返回正确的 mismatch 结构", () => {
    const f = mismatchFailure("status", "status", [200], 500, "status mismatch");
    expect(f).toEqual({
      actual: 500,
      expected: [200],
      kind: "mismatch",
      message: "status mismatch",
      path: "status",
      phase: "status",
    });
  });

  test("自动截断过长的 actual", () => {
    const longStr = "x".repeat(300);
    const f = mismatchFailure("body", "body[0]", "short", longStr, "too long");
    expect(f.actual).toBe(`${"x".repeat(200)}…(共 300 字符)`);
  });
});

describe("errorFailure", () => {
  test("返回正确的 error 结构", () => {
    const f = errorFailure("body", "body[0].json($.x)", "body is not valid JSON");
    expect(f).toEqual({
      kind: "error",
      message: "body is not valid JSON",
      path: "body[0].json($.x)",
      phase: "body",
    });
  });

  test("不含 expected 和 actual 字段", () => {
    const f = errorFailure("headers", "headers.x", "header missing");
    expect(f).not.toHaveProperty("expected");
    expect(f).not.toHaveProperty("actual");
  });
});
