import { hasFeature } from "./features.js";
const EMPTY_DIAGNOSTICS = Object.freeze({
  missingDependencies: Object.freeze([]),
  orphanedDependents: Object.freeze([]),
  unknownReferences: Object.freeze([])
});
function normalizeGranted(granted) {
  if (!Array.isArray(granted)) return [];
  const set = /* @__PURE__ */ new Set();
  for (const entry of granted) {
    if (typeof entry !== "string") continue;
    const trimmed = entry.trim();
    if (!trimmed) continue;
    set.add(trimmed);
  }
  return Array.from(set);
}
function indexCatalog(catalog) {
  const map = /* @__PURE__ */ new Map();
  for (const descriptor of catalog) {
    if (!descriptor || typeof descriptor.id !== "string") continue;
    const id = descriptor.id.trim();
    if (!id) continue;
    if (!map.has(id)) map.set(id, descriptor);
  }
  return map;
}
function resolveAclDependencyDiagnostics(granted, catalog) {
  if (!Array.isArray(catalog) || catalog.length === 0) return EMPTY_DIAGNOSTICS;
  const grantedList = normalizeGranted(granted);
  if (grantedList.includes("*")) return EMPTY_DIAGNOSTICS;
  const catalogIndex = indexCatalog(catalog);
  const missingDependencies = [];
  const unknownReferences = [];
  const dependentsByDependency = /* @__PURE__ */ new Map();
  for (const descriptor of catalog) {
    if (!descriptor || typeof descriptor.id !== "string") continue;
    const featureId = descriptor.id.trim();
    if (!featureId) continue;
    const deps = Array.isArray(descriptor.dependsOn) ? descriptor.dependsOn : [];
    if (deps.length === 0) continue;
    if (!hasFeature(grantedList, featureId)) continue;
    const missing = [];
    const unknown = [];
    for (const rawDep of deps) {
      if (typeof rawDep !== "string") continue;
      const dep = rawDep.trim();
      if (!dep) continue;
      const isRegistered = catalogIndex.has(dep) || dep.endsWith(".*") || dep === "*";
      if (!isRegistered) {
        unknown.push(dep);
        continue;
      }
      if (!hasFeature(grantedList, dep)) {
        missing.push(dep);
        const bucket = dependentsByDependency.get(dep) ?? /* @__PURE__ */ new Set();
        bucket.add(featureId);
        dependentsByDependency.set(dep, bucket);
      }
    }
    if (missing.length > 0) {
      missingDependencies.push({ feature: featureId, missing: dedupe(missing) });
    }
    if (unknown.length > 0) {
      unknownReferences.push({ feature: featureId, missing: dedupe(unknown) });
    }
  }
  const orphanedDependents = [];
  for (const [dep, dependents] of dependentsByDependency) {
    const known = catalogIndex.has(dep);
    if (!known) continue;
    orphanedDependents.push({
      dependency: dep,
      dependents: Array.from(dependents).sort((a, b) => a.localeCompare(b))
    });
  }
  orphanedDependents.sort((a, b) => a.dependency.localeCompare(b.dependency));
  return {
    missingDependencies,
    orphanedDependents,
    unknownReferences: unknownReferences.sort((a, b) => a.feature.localeCompare(b.feature))
  };
}
function dedupe(values) {
  return Array.from(new Set(values)).sort((a, b) => a.localeCompare(b));
}
function applyAddMissingDependency(granted, dependency) {
  if (!dependency || !dependency.trim()) return [...granted];
  if (granted.includes(dependency)) return [...granted];
  return [...granted, dependency];
}
function applyRemoveDependents(granted, dependents) {
  if (!dependents.length) return [...granted];
  const dropSet = new Set(dependents);
  return granted.filter((feature) => !dropSet.has(feature));
}
function applyRestoreDependency(granted, dependency) {
  return applyAddMissingDependency(granted, dependency);
}
export {
  applyAddMissingDependency,
  applyRemoveDependents,
  applyRestoreDependency,
  resolveAclDependencyDiagnostics
};
//# sourceMappingURL=aclDependencies.js.map
