import { describe, it } from "node:test";
import assert from "node:assert/strict";

import {
  getAvailableLanguagePacks,
  loadAllRulesForLanguage,
  loadRulePack,
  validateRulePack,
} from "../../../open-sse/services/compression/index.ts";
import { getRulesForContext } from "../../../open-sse/services/compression/cavemanRules.ts";
import { applyRulesToText } from "../../../open-sse/services/compression/caveman.ts";

describe("Caveman file-based rule loader", () => {
  it("loads English rule packs by category", () => {
    assert.equal(loadRulePack("en", "filler", { refresh: true }).length, 14);
    assert.ok(loadRulePack("en", "context", { refresh: true }).length >= 8);
    assert.ok(loadRulePack("en", "structural", { refresh: true }).length >= 7);
    assert.ok(loadRulePack("en", "dedup", { refresh: true }).length >= 4);
    assert.ok(loadRulePack("en", "ultra", { refresh: true }).length >= 1);
  });

  it("loads all English rules and lists metadata", () => {
    const rules = loadAllRulesForLanguage("en", { refresh: true });
    const packs = getAvailableLanguagePacks();

    assert.ok(rules.length >= 31, `Expected 31+ rules, got ${rules.length}`);
    assert.ok(packs.some((pack) => pack.language === "en" && pack.ruleCount >= 31));
  });

  it("validates rule pack structure", () => {
    assert.equal(
      validateRulePack({
        language: "xx",
        category: "filler",
        rules: [{ name: "x", pattern: "\\\\btest\\\\b", replacement: "" }],
      }).valid,
      true
    );
    assert.equal(
      validateRulePack({ language: "xx", category: "filler", rules: [{}] }).valid,
      false
    );
  });

  it("validates flags and replacement maps", () => {
    assert.equal(
      validateRulePack({
        language: "xx",
        category: "context",
        rules: [
          {
            name: "mapped",
            pattern: "\\b(?:one|two)\\b",
            flags: "g",
            replacementMap: { one: "1", two: "2" },
          },
        ],
      }).valid,
      true
    );
    assert.equal(
      validateRulePack({
        language: "xx",
        category: "context",
        rules: [
          {
            name: "bad_map",
            pattern: "\\b(?:one|two)\\b",
            replacementMap: { one: 1 },
          },
        ],
      }).valid,
      false
    );
  });

  it("falls back to hardcoded rules when language pack is missing", () => {
    const rules = getRulesForContext("user", "full", "missing-language");
    assert.ok(rules.some((rule) => rule.name === "polite_framing"));
  });

  it("applies file-based English rules without losing core behavior", () => {
    const rules = getRulesForContext("user", "full", "en");
    const { text } = applyRulesToText("Please provide a detailed explanation of this code", rules);

    assert.ok(!text.toLowerCase().includes("please"));
    assert.ok(!text.toLowerCase().includes("detailed"));
    assert.ok(text.includes("provide") || text.includes("explain"));
  });

  it("applies mapped replacements without semantic regressions", () => {
    const fullRules = getRulesForContext("user", "full", "en");
    const ultraRules = getRulesForContext("user", "ultra", "en");

    assert.equal(
      applyRulesToText("Could you show me how to configure auth?", fullRules).text,
      "Show how to configure auth?"
    );
    assert.equal(
      applyRulesToText("The code seems to parse JSON.", fullRules).text,
      "Code: parse JSON."
    );
    assert.equal(
      applyRulesToText("The value was generated by the server.", fullRules).text,
      "value generated by server."
    );
    assert.equal(
      applyRulesToText("The dependencies are outdated.", ultraRules).text,
      "deps are outdated."
    );
  });
});
