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

import type { ContentExpectations } from "../../../../../src/server/checker/expect/types";

import {
  checkAnswerCount,
  checkDnsValues,
  checkFlag,
  checkRcode,
  checkResponded,
  checkResult,
  checkTtlMax,
  checkTtlMin,
  checkValueCount,
} from "../../../../../src/server/checker/runner/dns/expect";

describe("checkResponded", () => {
  it("responded=true 期望 true → 匹配", () => {
    const result = checkResponded(true, true);
    expect(result.matched).toBe(true);
    expect(result.failure).toBeNull();
  });

  it("responded=false 期望 true → 不匹配", () => {
    const result = checkResponded(false, true);
    expect(result.matched).toBe(false);
    expect(result.failure!.kind).toBe("mismatch");
    expect(result.failure!.phase).toBe("responded");
    expect(result.failure!.message).toContain("未收到");
  });

  it("responded=true 期望 false → 不匹配", () => {
    const result = checkResponded(true, false);
    expect(result.matched).toBe(false);
    expect(result.failure!.kind).toBe("mismatch");
    expect(result.failure!.phase).toBe("responded");
    expect(result.failure!.message).toContain("收到响应");
  });

  it("responded=false 期望 false → 匹配", () => {
    const result = checkResponded(false, false);
    expect(result.matched).toBe(true);
    expect(result.failure).toBeNull();
  });
});

describe("checkRcode", () => {
  it("NOERROR 在 [NOERROR] → 匹配", () => {
    const result = checkRcode("NOERROR", ["NOERROR"]);
    expect(result.matched).toBe(true);
    expect(result.failure).toBeNull();
  });

  it("NXDOMAIN 在 [NOERROR] → 不匹配", () => {
    const result = checkRcode("NXDOMAIN", ["NOERROR"]);
    expect(result.matched).toBe(false);
    expect(result.failure!.kind).toBe("mismatch");
    expect(result.failure!.phase).toBe("rcode");
  });

  it("NXDOMAIN 在 [NXDOMAIN, SERVFAIL] → 匹配", () => {
    const result = checkRcode("NXDOMAIN", ["NXDOMAIN", "SERVFAIL"]);
    expect(result.matched).toBe(true);
    expect(result.failure).toBeNull();
  });
});

describe("checkDnsValues", () => {
  it("exact: 相同集合不同顺序 → 匹配", () => {
    const result = checkDnsValues(["2.2.2.2", "1.1.1.1"], { exact: ["1.1.1.1", "2.2.2.2"] });
    expect(result.matched).toBe(true);
    expect(result.failure).toBeNull();
  });

  it("exact: 不同集合 → 不匹配", () => {
    const result = checkDnsValues(["1.1.1.1"], { exact: ["2.2.2.2"] });
    expect(result.matched).toBe(false);
    expect(result.failure!.kind).toBe("mismatch");
    expect(result.failure!.phase).toBe("values");
  });

  it("exact: 数量不同 → 不匹配", () => {
    const result = checkDnsValues(["1.1.1.1", "2.2.2.2"], { exact: ["1.1.1.1"] });
    expect(result.matched).toBe(false);
  });

  it("include: 全部存在 → 匹配", () => {
    const result = checkDnsValues(["1.1.1.1", "2.2.2.2"], { include: ["1.1.1.1"] });
    expect(result.matched).toBe(true);
    expect(result.failure).toBeNull();
  });

  it("include: 缺少一个 → 不匹配", () => {
    const result = checkDnsValues(["1.1.1.1"], { include: ["3.3.3.3"] });
    expect(result.matched).toBe(false);
    expect(result.failure!.message).toContain("3.3.3.3");
  });

  it("exclude: 全不存在 → 匹配", () => {
    const result = checkDnsValues(["1.1.1.1"], { exclude: ["3.3.3.3"] });
    expect(result.matched).toBe(true);
    expect(result.failure).toBeNull();
  });

  it("exclude: 存在一个 → 不匹配", () => {
    const result = checkDnsValues(["1.1.1.1", "2.2.2.2"], { exclude: ["2.2.2.2"] });
    expect(result.matched).toBe(false);
    expect(result.failure!.message).toContain("2.2.2.2");
  });

  it("include + exclude 组合：全部满足 → 匹配", () => {
    const result = checkDnsValues(["1.1.1.1", "2.2.2.2"], { exclude: ["3.3.3.3"], include: ["1.1.1.1"] });
    expect(result.matched).toBe(true);
    expect(result.failure).toBeNull();
  });

  it("include + exclude 组合：include 失败 → 不匹配", () => {
    const result = checkDnsValues(["1.1.1.1"], { exclude: ["3.3.3.3"], include: ["4.4.4.4"] });
    expect(result.matched).toBe(false);
  });

  it("空 expectation → 匹配", () => {
    const result = checkDnsValues(["1.1.1.1"], {});
    expect(result.matched).toBe(true);
    expect(result.failure).toBeNull();
  });
});

describe("checkValueCount", () => {
  it("count=3 gte=1 → 匹配", () => {
    const result = checkValueCount(3, { gte: 1 });
    expect(result.matched).toBe(true);
    expect(result.failure).toBeNull();
  });

  it("count=0 gte=1 → 不匹配", () => {
    const result = checkValueCount(0, { gte: 1 });
    expect(result.matched).toBe(false);
    expect(result.failure!.kind).toBe("mismatch");
    expect(result.failure!.phase).toBe("valueCount");
  });
});

describe("checkAnswerCount", () => {
  it("count=2 gte=2 → 匹配", () => {
    const result = checkAnswerCount(2, { gte: 2 });
    expect(result.matched).toBe(true);
    expect(result.failure).toBeNull();
  });

  it("count=1 gte=2 → 不匹配", () => {
    const result = checkAnswerCount(1, { gte: 2 });
    expect(result.matched).toBe(false);
    expect(result.failure!.kind).toBe("mismatch");
    expect(result.failure!.phase).toBe("answerCount");
  });
});

describe("checkTtlMin", () => {
  it("ttl=300 gte=60 → 匹配", () => {
    const result = checkTtlMin(300, { gte: 60 });
    expect(result.matched).toBe(true);
    expect(result.failure).toBeNull();
  });

  it("ttl=30 gte=60 → 不匹配", () => {
    const result = checkTtlMin(30, { gte: 60 });
    expect(result.matched).toBe(false);
    expect(result.failure!.kind).toBe("mismatch");
    expect(result.failure!.phase).toBe("ttlMin");
  });
});

describe("checkTtlMax", () => {
  it("ttl=100 lte=3600 → 匹配", () => {
    const result = checkTtlMax(100, { lte: 3600 });
    expect(result.matched).toBe(true);
    expect(result.failure).toBeNull();
  });

  it("ttl=5000 lte=3600 → 不匹配", () => {
    const result = checkTtlMax(5000, { lte: 3600 });
    expect(result.matched).toBe(false);
    expect(result.failure!.kind).toBe("mismatch");
    expect(result.failure!.phase).toBe("ttlMax");
  });
});

describe("checkFlag", () => {
  it("匹配 → matched", () => {
    const result = checkFlag(true, true, "authoritative");
    expect(result!.matched).toBe(true);
    expect(result!.failure).toBeNull();
  });

  it("不匹配 → mismatch", () => {
    const result = checkFlag(false, true, "authoritative");
    expect(result!.matched).toBe(false);
    expect(result!.failure!.kind).toBe("mismatch");
    expect(result!.failure!.phase).toBe("authoritative");
  });

  it("undefined 期望 → 跳过返回 null", () => {
    const result = checkFlag(true, undefined, "authoritative");
    expect(result).toBeNull();
  });
});

describe("checkResult", () => {
  it("单条 contains 匹配 JSON 字符串", () => {
    const observation = { answers: ["1.1.1.1"], rcode: "NOERROR" };
    const expectations: ContentExpectations = [{ kind: "value", matcher: { contains: "NOERROR" } }];
    const result = checkResult(observation, expectations);
    expect(result.matched).toBe(true);
    expect(result.failure).toBeNull();
  });

  it("单条 contains 不匹配 → 不匹配", () => {
    const observation = { rcode: "SERVFAIL" };
    const expectations: ContentExpectations = [{ kind: "value", matcher: { contains: "NOERROR" } }];
    const result = checkResult(observation, expectations);
    expect(result.matched).toBe(false);
    expect(result.failure!.kind).toBe("mismatch");
    expect(result.failure!.phase).toBe("result");
  });
});
