import { describe, expect, it } from "vitest";
import { applyBacklinkBoost, applyCompiledTruthBoost } from "../boosts.js";

describe("applyCompiledTruthBoost", () => {
  it("is identity on hits without compiledTruth", () => {
    const hits = [
      { nodeId: "a", score: 1.0, properties: {} },
      { nodeId: "b", score: 0.5, properties: { compiledTruth: null } },
      { nodeId: "c", score: 0.3, properties: { compiledTruth: "" } },
    ];
    const out = applyCompiledTruthBoost(hits);
    expect(out.map((h) => h.score)).toEqual([1.0, 0.5, 0.3]);
  });

  it("adds 15% to hits with a non-empty compiledTruth", () => {
    const hits = [
      { nodeId: "a", score: 1.0, properties: { compiledTruth: "Adam founded X." } },
    ];
    const out = applyCompiledTruthBoost(hits);
    expect(out[0].score).toBeCloseTo(1.15, 6);
  });

  it("respects the weight override", () => {
    const hits = [{ nodeId: "a", score: 1.0, properties: { compiledTruth: "x" } }];
    const out = applyCompiledTruthBoost(hits, 0.25);
    expect(out[0].score).toBeCloseTo(1.25, 6);
  });

  it("throws on out-of-range weight", () => {
    expect(() =>
      applyCompiledTruthBoost([{ nodeId: "a", score: 1, properties: {} }], 1.5),
    ).toThrow();
  });
});

describe("applyBacklinkBoost", () => {
  it("is identity on missing or zero count", () => {
    const hits = [
      { nodeId: "a", score: 1.0, properties: {} },
      { nodeId: "b", score: 1.0, properties: { backlinkCount: 0 } },
    ];
    const out = applyBacklinkBoost(hits);
    expect(out.map((h) => h.score)).toEqual([1.0, 1.0]);
  });

  it("scales log-weighted with the documented floor/ceiling", () => {
    const hits = [
      { nodeId: "a", score: 1.0, properties: { backlinkCount: 1 } },
      { nodeId: "b", score: 1.0, properties: { backlinkCount: 10 } },
      { nodeId: "c", score: 1.0, properties: { backlinkCount: 100 } },
      { nodeId: "d", score: 1.0, properties: { backlinkCount: 10_000 } },
    ];
    const out = applyBacklinkBoost(hits);
    expect(out[0].score).toBeCloseTo(1.05, 6); // 1 → +5%
    expect(out[1].score).toBeCloseTo(1.10, 6); // 10 → +10%
    expect(out[2].score).toBeCloseTo(1.15, 6); // 100 → +15%
    expect(out[3].score).toBeCloseTo(1.25, 6); // 10k → capped at +25%
  });
});
