"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var fs = __toESM(require("fs"));
var path = __toESM(require("path"));
var import_fingerprint = require("./fingerprint");
const cases = [];
function test(name, run) {
  cases.push({ name, run });
}
function assertEqual(actual, expected, msg) {
  const a = JSON.stringify(actual);
  const e = JSON.stringify(expected);
  if (a !== e)
    throw new Error(`${msg ?? "assertEqual"} \u2014 expected ${e}, got ${a}`);
}
test("normalizeClasses: keeps BEM-ish classes", () => {
  assertEqual(
    (0, import_fingerprint.normalizeClasses)("vue-treeselect vue-treeselect__menu vue-treeselect--single"),
    "vue-treeselect vue-treeselect--single vue-treeselect__menu"
  );
});
test("normalizeClasses: keeps framework-prefixed classes", () => {
  assertEqual(
    (0, import_fingerprint.normalizeClasses)("MuiSelect-root MuiSelect-standard"),
    "MuiSelect-root MuiSelect-standard"
  );
});
test("normalizeClasses: drops tailwind utilities", () => {
  assertEqual(
    (0, import_fingerprint.normalizeClasses)("vue-treeselect bg-red-500 p-4 hover:text-white"),
    "vue-treeselect"
  );
});
test("normalizeClasses: drops CSS-module hashed suffixes", () => {
  assertEqual(
    (0, import_fingerprint.normalizeClasses)("button_abc123 vue-treeselect"),
    "vue-treeselect"
  );
});
test("normalizeClasses: drops numeric-index suffixes", () => {
  assertEqual(
    (0, import_fingerprint.normalizeClasses)("item-1 item-2 vue-treeselect"),
    "vue-treeselect"
  );
});
test("normalizeClasses: drops state tokens", () => {
  assertEqual(
    (0, import_fingerprint.normalizeClasses)("vue-treeselect is-active is-open expanded"),
    "vue-treeselect"
  );
});
test("normalizeClasses: framework prefix beats numeric-suffix deny-list", () => {
  assertEqual(
    (0, import_fingerprint.normalizeClasses)("MuiSelect-root MuiSelect-123 ant-select-item-1"),
    "MuiSelect-123 MuiSelect-root ant-select-item-1"
  );
});
test("normalizeClasses: framework prefix beats tailwind-shape deny-list", () => {
  assertEqual(
    (0, import_fingerprint.normalizeClasses)("data-radix-border-blue"),
    "data-radix-border-blue"
  );
});
test("normalizeClasses: empty string returns empty string", () => {
  assertEqual((0, import_fingerprint.normalizeClasses)(""), "");
});
test("normalizeClasses: sorts alphabetically", () => {
  assertEqual(
    (0, import_fingerprint.normalizeClasses)("vue-treeselect__menu vue-treeselect"),
    "vue-treeselect vue-treeselect__menu"
  );
});
test("normalizeClasses: deduplicates", () => {
  assertEqual(
    (0, import_fingerprint.normalizeClasses)("vue-treeselect vue-treeselect"),
    "vue-treeselect"
  );
});
test("computeFingerprintFromInput: identical input yields identical hash", () => {
  const input = {
    root: { tag: "div", role: "combobox", ariaHasPopup: "", classPattern: "vue-treeselect", dataAttrKeys: [] },
    descendants: [],
    portal: null
  };
  assertEqual((0, import_fingerprint.computeFingerprintFromInput)(input), (0, import_fingerprint.computeFingerprintFromInput)(input));
});
test("computeFingerprintFromInput: different tag yields different hash", () => {
  const a = {
    root: { tag: "div", role: "combobox", ariaHasPopup: "", classPattern: "", dataAttrKeys: [] },
    descendants: [],
    portal: null
  };
  const b = {
    root: { tag: "button", role: "combobox", ariaHasPopup: "", classPattern: "", dataAttrKeys: [] },
    descendants: [],
    portal: null
  };
  if ((0, import_fingerprint.computeFingerprintFromInput)(a) === (0, import_fingerprint.computeFingerprintFromInput)(b))
    throw new Error("expected different hashes");
});
test("computeFingerprintFromInput: same descendant order produces same hash (stability)", () => {
  const d1 = { tag: "div", role: "", ariaHasPopup: "", classPattern: "a", dataAttrKeys: [] };
  const d2 = { tag: "div", role: "", ariaHasPopup: "", classPattern: "b", dataAttrKeys: [] };
  const a = {
    root: { tag: "div", role: "combobox", ariaHasPopup: "", classPattern: "", dataAttrKeys: [] },
    descendants: [d1, d2],
    portal: null
  };
  const b = {
    root: { tag: "div", role: "combobox", ariaHasPopup: "", classPattern: "", dataAttrKeys: [] },
    descendants: [d1, d2],
    // same order
    portal: null
  };
  assertEqual((0, import_fingerprint.computeFingerprintFromInput)(a), (0, import_fingerprint.computeFingerprintFromInput)(b));
});
test("computeFingerprintFromInput: descendant order DOES affect hash (order is part of the fingerprint)", () => {
  const d1 = { tag: "div", role: "", ariaHasPopup: "", classPattern: "a", dataAttrKeys: [] };
  const d2 = { tag: "div", role: "", ariaHasPopup: "", classPattern: "b", dataAttrKeys: [] };
  const a = {
    root: { tag: "div", role: "combobox", ariaHasPopup: "", classPattern: "", dataAttrKeys: [] },
    descendants: [d1, d2],
    portal: null
  };
  const b = {
    root: { tag: "div", role: "combobox", ariaHasPopup: "", classPattern: "", dataAttrKeys: [] },
    descendants: [d2, d1],
    // reversed
    portal: null
  };
  if ((0, import_fingerprint.computeFingerprintFromInput)(a) === (0, import_fingerprint.computeFingerprintFromInput)(b))
    throw new Error("expected different hashes when descendant order differs");
});
test("computeFingerprintFromInput: returns 16 hex chars", () => {
  const input = {
    root: { tag: "div", role: "", ariaHasPopup: "", classPattern: "", dataAttrKeys: [] },
    descendants: [],
    portal: null
  };
  const hash = (0, import_fingerprint.computeFingerprintFromInput)(input);
  if (!/^[0-9a-f]{16}$/.test(hash))
    throw new Error(`expected 16-hex hash, got "${hash}"`);
});
test("computeFingerprintFromInput: null portal differs from populated portal", () => {
  const portalTuple = { tag: "div", role: "", ariaHasPopup: "", classPattern: "data-radix-popper-content-wrapper", dataAttrKeys: [] };
  const a = {
    root: { tag: "button", role: "combobox", ariaHasPopup: "", classPattern: "", dataAttrKeys: [] },
    descendants: [],
    portal: null
  };
  const b = {
    root: { tag: "button", role: "combobox", ariaHasPopup: "", classPattern: "", dataAttrKeys: [] },
    descendants: [],
    portal: portalTuple
  };
  if ((0, import_fingerprint.computeFingerprintFromInput)(a) === (0, import_fingerprint.computeFingerprintFromInput)(b))
    throw new Error("expected different hashes");
});
test("drift detection: blueprint.ts inline rule constants match fingerprint.ts exports", () => {
  const blueprintSrcPath = path.resolve(__dirname, "..", "..", "src", "dom-analyzer", "blueprint.ts");
  const src = fs.readFileSync(blueprintSrcPath, "utf-8");
  const beginMarker = "// INLINE_RULES_BEGIN";
  const endMarker = "// INLINE_RULES_END";
  const beginIdx = src.indexOf(beginMarker);
  const endIdx = src.indexOf(endMarker, beginIdx);
  if (beginIdx === -1 || endIdx === -1)
    throw new Error(`blueprint.ts must contain ${beginMarker} / ${endMarker} markers around the inlined fingerprint rule constants`);
  const newlineAfterBegin = src.indexOf("\n", beginIdx);
  const block = src.slice(newlineAfterBegin + 1, endIdx);
  const inlined = new Function(
    block + "\nreturn { BEM_ISH, FRAMEWORK_PREFIXES, TAILWIND_UTILITY, CSS_MODULE_HASH, NUMERIC_INDEX_SUFFIX, STATE_TOKENS };"
  )();
  function regexEq(a, b, name) {
    if (a.source !== b.source || a.flags !== b.flags)
      throw new Error(`${name} drift: fingerprint.ts has /${a.source}/${a.flags}, blueprint.ts has /${b.source}/${b.flags}`);
  }
  function arrayEq(a, b, name) {
    if (a.length !== b.length || a.some((v, i) => v !== b[i]))
      throw new Error(`${name} drift: fingerprint.ts has ${JSON.stringify(a)}, blueprint.ts has ${JSON.stringify(b)}`);
  }
  function setEq(a, b, name) {
    const aSorted = Array.from(a).sort();
    const bSorted = Array.from(b).sort();
    arrayEq(aSorted, bSorted, name);
  }
  regexEq(import_fingerprint.BEM_ISH, inlined.BEM_ISH, "BEM_ISH");
  arrayEq(import_fingerprint.FRAMEWORK_PREFIXES, inlined.FRAMEWORK_PREFIXES, "FRAMEWORK_PREFIXES");
  regexEq(import_fingerprint.TAILWIND_UTILITY, inlined.TAILWIND_UTILITY, "TAILWIND_UTILITY");
  regexEq(import_fingerprint.CSS_MODULE_HASH, inlined.CSS_MODULE_HASH, "CSS_MODULE_HASH");
  regexEq(import_fingerprint.NUMERIC_INDEX_SUFFIX, inlined.NUMERIC_INDEX_SUFFIX, "NUMERIC_INDEX_SUFFIX");
  setEq(import_fingerprint.STATE_TOKENS, inlined.STATE_TOKENS, "STATE_TOKENS");
});
let failed = 0;
for (const { name, run } of cases) {
  try {
    run();
    console.log("  \u2713", name);
  } catch (e) {
    failed++;
    console.log("  \u2717", name);
    console.log("     ", e.message);
  }
}
if (failed > 0) {
  console.log(`
${failed}/${cases.length} failed`);
  process.exit(1);
}
console.log(`
${cases.length} passed`);
