import { describe, it, expect } from "vitest";
import { escapeLucene, normaliseBm25Scores } from "../index.js";

describe("escapeLucene", () => {
  it("escapes Lucene operators in field:value syntax", () => {
    expect(escapeLucene("foo:bar")).toBe("foo\\:bar");
  });

  it("escapes boolean-grouping parens and OR", () => {
    expect(escapeLucene("(a OR b)")).toBe("\\(a OR b\\)");
  });

  it("escapes wildcard characters", () => {
    expect(escapeLucene("bar*")).toBe("bar\\*");
  });

  it("escapes backslash", () => {
    expect(escapeLucene("a\\b")).toBe("a\\\\b");
  });

  it("preserves non-special characters", () => {
    expect(escapeLucene("hello world 123")).toBe("hello world 123");
  });

  it("escapes a mix of specials in one pass", () => {
    expect(escapeLucene("a+b-c&d|e!f")).toBe("a\\+b\\-c\\&d\\|e\\!f");
  });
});

describe("normaliseBm25Scores", () => {
  it("returns empty array for empty input", () => {
    expect(normaliseBm25Scores([])).toEqual([]);
  });

  it("maps [min..max] to [0..1] via min-max", () => {
    expect(normaliseBm25Scores([1, 2, 3])).toEqual([0, 0.5, 1]);
  });

  it("returns 1.0 for all values when range is zero (all scores equal)", () => {
    expect(normaliseBm25Scores([5, 5, 5])).toEqual([1, 1, 1]);
  });

  it("returns 1.0 for single-element input (range is zero)", () => {
    expect(normaliseBm25Scores([42])).toEqual([1]);
  });

  it("handles non-integer scores", () => {
    const result = normaliseBm25Scores([0.5, 1.5, 2.5]);
    expect(result[0]).toBeCloseTo(0);
    expect(result[1]).toBeCloseTo(0.5);
    expect(result[2]).toBeCloseTo(1);
  });
});
