import { access, readFile } from "node:fs/promises";
import { dirname, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { normalizeMapSubjectDetailProfiles } from "../server/map-subject-detail-profile.mjs";

const root = resolve(dirname(fileURLToPath(import.meta.url)), "..");
const parse = async (path) => JSON.parse(await readFile(resolve(root, path), "utf8"));

const registry = await parse("registry/registry.json");
const sources = await parse("registry/sources.json");
const components = await parse("registry/components.json");
const candidates = await parse("registry/candidates.json");
const icons = await parse("registry/icons.json");
const pages = await parse("registry/pages.json");
const applicationManifestSchema = await parse("registry/schemas/application-manifest-v0.1.schema.json");
const designProfileSchema = await parse("registry/schemas/design-profile-v0.1.schema.json");
const mapSceneFixtureSchema = await parse("registry/schemas/map-scene-fixture-v0.1.schema.json");
const mapLodPolicySchema = await parse("registry/schemas/map-lod-policy-v0.1.schema.json");
const mapPresentationProfiles = await parse("registry/map-presentation-profiles.json");
const mapSubjectDetailProfiles = await parse("registry/map-subject-detail-profiles.json");
const dataProductConsumerPolicies = await parse("registry/data-product-consumer-policies.json");

const failures = [];
const requireValue = (condition, message) => {
  if (!condition) failures.push(message);
};

requireValue(registry.schemaVersion === "1.0.0", "registry schemaVersion must be 1.0.0");
requireValue(registry.libraryVersion, "registry libraryVersion is required");
requireValue(Array.isArray(registry.packages) && registry.packages.length >= 4, "registry must list all packages");
requireValue(Array.isArray(sources.sources) && sources.sources.length >= 6, "source audit is incomplete");
requireValue(Array.isArray(components.components) && components.components.length >= 10, "component registry is incomplete");
requireValue(Array.isArray(candidates.candidates) && candidates.candidates.length >= 1, "candidate registry is incomplete");
requireValue(
  Array.isArray(components.components)
    && Array.isArray(candidates.candidates)
    && components.components.length + candidates.candidates.length >= 20,
  "component inventory is incomplete",
);
requireValue(Array.isArray(icons.groups) && icons.groups.length >= 5, "icon registry is incomplete");
requireValue(pages.schemaVersion === "0.1.0", "page registry schemaVersion must be 0.1.0");
requireValue(Array.isArray(pages.templates) && pages.templates.length >= 1, "page registry must contain at least one template");
requireValue(registry.applicationManifestSchema === "schemas/application-manifest-v0.1.schema.json", "application manifest schema must be registered");
requireValue(registry.designProfileSchema === "schemas/design-profile-v0.1.schema.json", "design profile schema must be registered");
requireValue(registry.mapSceneFixtureSchema === "schemas/map-scene-fixture-v0.1.schema.json", "map scene fixture schema must be registered");
requireValue(registry.mapLodPolicySchema === "schemas/map-lod-policy-v0.1.schema.json", "map LOD policy schema must be registered");
requireValue(registry.mapPresentationProfileRegistry === "map-presentation-profiles.json", "map presentation profile registry must be registered");
requireValue(registry.mapSubjectDetailProfileRegistry === "map-subject-detail-profiles.json", "map subject detail profile registry must be registered");
requireValue(applicationManifestSchema.properties?.schemaVersion?.const === "0.1.0", "application manifest schema version must be 0.1.0");
requireValue(designProfileSchema.properties?.schemaVersion?.const === "0.1.0", "design profile schema version must be 0.1.0");
requireValue(mapSceneFixtureSchema.properties?.schemaVersion?.const === "0.1.0", "map scene fixture schema version must be 0.1.0");
requireValue(mapLodPolicySchema.properties?.schemaVersion?.const === "0.1.0", "map LOD policy schema version must be 0.1.0");
requireValue(mapPresentationProfiles.schemaVersion === "nodedc.map-presentation-profiles/v1", "map presentation profile registry schema is unsupported");
requireValue(Array.isArray(mapPresentationProfiles.profiles) && mapPresentationProfiles.profiles.length >= 1, "map presentation profiles are missing");
requireValue(mapSubjectDetailProfiles.schemaVersion === "nodedc.map-subject-detail-profiles/v1", "map subject detail profile registry schema is unsupported");
try {
  const normalizedSubjectDetailProfiles = normalizeMapSubjectDetailProfiles(mapSubjectDetailProfiles.profiles);
  requireValue(normalizedSubjectDetailProfiles.length >= 1, "map subject detail profiles are missing");
} catch (error) {
  requireValue(false, `invalid map subject detail profile registry: ${error instanceof Error ? error.message : String(error)}`);
}
requireValue(dataProductConsumerPolicies.schemaVersion === "nodedc.foundry.data-product-consumer-policies/v1", "data product consumer policy registry schema is unsupported");
requireValue(Array.isArray(dataProductConsumerPolicies.policies) && dataProductConsumerPolicies.policies.length >= 1, "data product consumer policies are missing");

const consumerPolicies = dataProductConsumerPolicies.policies ?? [];
const consumerPolicyIds = consumerPolicies.map((policy) => `${policy.id}@${policy.version}`);
const consumerPolicyProducts = consumerPolicies.map((policy) => `${policy.dataProductId}@${policy.productVersion}`);
requireValue(new Set(consumerPolicyIds).size === consumerPolicyIds.length, "data product consumer policy id/version pairs must be unique");
requireValue(new Set(consumerPolicyProducts).size === consumerPolicyProducts.length, "data product consumer policy product/version pairs must be unique");
for (const policy of consumerPolicies) {
  const statusContract = policy.statusContract;
  const freshness = policy.freshness ?? statusContract?.freshness ?? "observed-at";
  const allowedPolicyKeys = new Set([
    "id",
    "version",
    "dataProductId",
    "productVersion",
    "freshness",
    "staleAfterMs",
    "terminalStatuses",
    "statusContract",
    "consumerContract",
    "dataClass",
    "removeMode",
  ]);
  requireValue(Object.keys(policy).every((key) => allowedPolicyKeys.has(key)), `unsupported data product consumer policy key: ${policy.id ?? "unknown"}`);
  requireValue(typeof policy.id === "string" && /^[a-z0-9._-]{1,160}$/.test(policy.id), `invalid data product consumer policy id: ${policy.id ?? "unknown"}`);
  requireValue(typeof policy.version === "string" && /^\d+\.\d+\.\d+$/.test(policy.version), `invalid data product consumer policy version: ${policy.id ?? "unknown"}`);
  requireValue(typeof policy.dataProductId === "string" && /^[A-Za-z0-9._:-]{1,160}$/.test(policy.dataProductId), `invalid data product consumer policy product: ${policy.id ?? "unknown"}`);
  requireValue(typeof policy.productVersion === "string" && /^\d+\.\d+\.\d+$/.test(policy.productVersion), `invalid data product consumer product version: ${policy.id ?? "unknown"}`);
  requireValue(Array.isArray(policy.terminalStatuses) && policy.terminalStatuses.every((value) => typeof value === "string" && /^[a-z0-9_-]{1,64}$/.test(value)), `invalid terminal statuses: ${policy.id ?? "unknown"}`);
  requireValue(policy.removeMode === "canonical-tombstone-or-snapshot-rebase", `invalid remove mode: ${policy.id ?? "unknown"}`);
  requireValue(["operational", "restricted"].includes(policy.dataClass ?? "operational"), `invalid data class: ${policy.id ?? "unknown"}`);
  requireValue(["none", "observed-at"].includes(freshness), `invalid freshness mode: ${policy.id ?? "unknown"}`);
  if (policy.consumerContract !== undefined) {
    const contract = policy.consumerContract;
    const keys = contract && typeof contract === "object" && !Array.isArray(contract) ? Object.keys(contract).sort() : [];
    requireValue(JSON.stringify(keys) === JSON.stringify(["deliveryMode", "fieldProjection", "fieldTypes", "geometryTypes", "ontologyRevision", "patchMode", "semanticTypes", "snapshotMode", "subjectIdentity"]), `invalid consumer contract keys: ${policy.id ?? "unknown"}`);
    requireValue(typeof contract?.ontologyRevision === "string" && /^[A-Za-z0-9._:-]{1,160}$/.test(contract.ontologyRevision), `invalid consumer ontology revision: ${policy.id ?? "unknown"}`);
    requireValue(contract?.deliveryMode === "snapshot+patch", `invalid consumer delivery mode: ${policy.id ?? "unknown"}`);
    requireValue(Array.isArray(contract?.semanticTypes) && contract.semanticTypes.length >= 1 && new Set(contract.semanticTypes).size === contract.semanticTypes.length, `invalid consumer semantic types: ${policy.id ?? "unknown"}`);
    requireValue(contract?.semanticTypes?.every((value) => typeof value === "string" && /^[A-Za-z0-9._:-]{1,160}$/.test(value)), `invalid consumer semantic type: ${policy.id ?? "unknown"}`);
    requireValue(Array.isArray(contract?.fieldProjection) && contract.fieldProjection.length >= 1 && new Set(contract.fieldProjection).size === contract.fieldProjection.length, `invalid consumer field projection: ${policy.id ?? "unknown"}`);
    requireValue(contract?.fieldProjection?.every((value) => typeof value === "string" && /^[A-Za-z][A-Za-z0-9_.-]{0,127}$/.test(value)), `invalid consumer projection field: ${policy.id ?? "unknown"}`);
    requireValue(contract?.fieldTypes && typeof contract.fieldTypes === "object" && !Array.isArray(contract.fieldTypes), `invalid consumer field types: ${policy.id ?? "unknown"}`);
    requireValue(JSON.stringify(Object.keys(contract?.fieldTypes ?? {})) === JSON.stringify(contract?.fieldProjection ?? []), `consumer field type order/scope mismatch: ${policy.id ?? "unknown"}`);
    requireValue(Object.values(contract?.fieldTypes ?? {}).every((value) => ["string", "number", "boolean", "string_array"].includes(value)), `invalid consumer field type: ${policy.id ?? "unknown"}`);
    const supportedGeometryTypes = ["Point", "LineString", "Polygon", "MultiPolygon"];
    requireValue(
      Array.isArray(contract?.geometryTypes)
        && contract.geometryTypes.length <= supportedGeometryTypes.length
        && new Set(contract.geometryTypes).size === contract.geometryTypes.length
        && contract.geometryTypes.every((value) => supportedGeometryTypes.includes(value)),
      `invalid consumer geometry types: ${policy.id ?? "unknown"}`,
    );
    requireValue(contract?.subjectIdentity === "semantic-type+source-id", `invalid consumer subject identity: ${policy.id ?? "unknown"}`);
    requireValue(contract?.snapshotMode === "atomic-replace" && contract?.patchMode === "atomic", `invalid consumer commit modes: ${policy.id ?? "unknown"}`);
  }
  if (statusContract === undefined) {
    requireValue(
      freshness === "none"
        ? policy.staleAfterMs === null
        : Number.isInteger(policy.staleAfterMs) && policy.staleAfterMs >= 1_000 && policy.staleAfterMs <= 7 * 24 * 60 * 60 * 1000,
      `invalid stale window: ${policy.id ?? "unknown"}`,
    );
    continue;
  }
  requireValue(statusContract && typeof statusContract === "object" && !Array.isArray(statusContract), `invalid status contract: ${policy.id ?? "unknown"}`);
  requireValue(typeof statusContract?.attribute === "string" && /^[A-Za-z][A-Za-z0-9_.-]{0,127}$/.test(statusContract.attribute), `invalid status attribute: ${policy.id ?? "unknown"}`);
  requireValue(Array.isArray(statusContract?.allowedValues) && statusContract.allowedValues.length >= 1 && new Set(statusContract.allowedValues).size === statusContract.allowedValues.length, `invalid allowed status values: ${policy.id ?? "unknown"}`);
  requireValue(statusContract?.allowedValues?.every((value) => typeof value === "string" && /^[a-z0-9_-]{1,64}$/.test(value)), `invalid allowed status value: ${policy.id ?? "unknown"}`);
  requireValue(statusContract?.missing === "reject", `status contract must reject missing values: ${policy.id ?? "unknown"}`);
  requireValue(["none", "observed-at"].includes(statusContract?.freshness), `invalid status freshness mode: ${policy.id ?? "unknown"}`);
  requireValue(statusContract?.freshness === freshness, `status and policy freshness modes must match: ${policy.id ?? "unknown"}`);
  requireValue(statusContract?.freshness === "none" ? policy.staleAfterMs === null : Number.isInteger(policy.staleAfterMs), `status freshness/stale window mismatch: ${policy.id ?? "unknown"}`);
  requireValue(policy.terminalStatuses.every((value) => statusContract.allowedValues.includes(value)), `terminal status is outside the closed value contract: ${policy.id ?? "unknown"}`);
}

const movingObjectV4Policy = consumerPolicies.find((policy) => policy.dataProductId === "fleet.positions.current.v4" && policy.productVersion === "4.0.0");
requireValue(movingObjectV4Policy?.id === "map-moving-object-current-v4", "fleet.positions.current.v4 consumer policy is missing");
requireValue(movingObjectV4Policy?.statusContract?.attribute === "signal_state", "fleet.positions.current.v4 status source must be signal_state");
requireValue(JSON.stringify(movingObjectV4Policy?.statusContract?.allowedValues) === JSON.stringify(["active", "inactive"]), "fleet.positions.current.v4 signal states must remain closed active/inactive");
requireValue(movingObjectV4Policy?.statusContract?.freshness === "none" && movingObjectV4Policy?.staleAfterMs === null, "fleet.positions.current.v4 must not invent freshness states");

const movingObjectV5Policy = consumerPolicies.find((policy) => policy.dataProductId === "fleet.positions.current.v5" && policy.productVersion === "5.0.0");
requireValue(movingObjectV5Policy?.id === "map-moving-object-current-v5", "fleet.positions.current.v5 consumer policy is missing");
requireValue(movingObjectV5Policy?.statusContract?.attribute === "signal_state", "fleet.positions.current.v5 status source must be signal_state");
requireValue(JSON.stringify(movingObjectV5Policy?.statusContract?.allowedValues) === JSON.stringify(["active", "inactive"]), "fleet.positions.current.v5 signal states must remain closed active/inactive");
requireValue(movingObjectV5Policy?.statusContract?.freshness === "none" && movingObjectV5Policy?.staleAfterMs === null, "fleet.positions.current.v5 must not invent freshness states");

const zoneV1Policy = consumerPolicies.find((policy) => policy.dataProductId === "map.zones.current.v1" && policy.productVersion === "1.0.0");
requireValue(JSON.stringify(zoneV1Policy) === JSON.stringify({
  id: "map-zone-current-v1",
  version: "1.0.0",
  dataProductId: "map.zones.current.v1",
  productVersion: "1.0.0",
  freshness: "none",
  staleAfterMs: null,
  terminalStatuses: [],
  removeMode: "canonical-tombstone-or-snapshot-rebase",
}), "historical map.zones.current.v1 consumer policy changed");

const zoneV2Policy = consumerPolicies.find((policy) => policy.dataProductId === "map.zones.current.v2" && policy.productVersion === "2.0.0");
const zoneV2Projection = ["display_name", "geometry_kind", "max_speed_kph", "schedule_timezone", "applies_to_couriers", "applies_to_kicksharing"];
requireValue(zoneV2Policy?.id === "map-zone-current-v2" && zoneV2Policy?.version === "2.0.0", "map.zones.current.v2 consumer policy is missing");
requireValue(zoneV2Policy?.freshness === "none" && zoneV2Policy?.staleAfterMs === null, "map.zones.current.v2 must not invent freshness states");
requireValue(JSON.stringify(zoneV2Policy?.consumerContract?.semanticTypes) === JSON.stringify(["map.zone"]), "map.zones.current.v2 semantic scope must be exact");
requireValue(JSON.stringify(zoneV2Policy?.consumerContract?.fieldProjection) === JSON.stringify(zoneV2Projection), "map.zones.current.v2 field projection must be exact");
requireValue(JSON.stringify(zoneV2Policy?.consumerContract?.geometryTypes) === JSON.stringify(["Polygon", "MultiPolygon"]), "map.zones.current.v2 geometry contract must be Polygon/MultiPolygon");
requireValue(!/(provider|tenant|connection|endpoint|credential|token|secret|authorization)/i.test(JSON.stringify(zoneV2Policy)), "map.zones.current.v2 consumer policy crosses the transport/secret boundary");

const unitProfileV1Policy = consumerPolicies.find((policy) => policy.dataProductId === "fleet.units.profile.current.v1" && policy.productVersion === "1.0.0");
const unitProfileV1Projection = [
  "corrected_engine_hours_factor",
  "corrected_mileage_factor",
  "display_name",
  "filter_by_satellite_count_enabled",
  "filter_by_satellite_count_value",
  "filter_emissions",
  "hardware_manufacturer_name",
  "hardware_port",
  "hardware_type_class",
  "hardware_type_name",
  "limit_acceleration",
  "lost_connection_enabled",
  "lost_connection_time_value",
  "maximum_permissible_speed",
  "maximum_valid_height",
  "maximum_valid_speed",
  "mileage_by_ignition",
  "minimum_movement_speed",
  "minimum_movement_time",
  "minimum_parking_time",
  "minimum_stop_time",
  "minimum_trip_distance",
  "minimum_valid_height",
  "speed_parameter",
  "trip_detection_type",
  "unit_type_class",
  "unit_type_name",
  "use_odometer",
];
requireValue(unitProfileV1Policy?.id === "map-moving-object-unit-profile-current-v1" && unitProfileV1Policy?.version === "1.0.0", "fleet.units.profile.current.v1 consumer policy is missing");
requireValue(unitProfileV1Policy?.freshness === "none" && unitProfileV1Policy?.staleAfterMs === null, "fleet.units.profile.current.v1 must not invent freshness states");
requireValue(JSON.stringify(unitProfileV1Policy?.consumerContract?.semanticTypes) === JSON.stringify(["map.moving_object"]), "fleet.units.profile.current.v1 semantic scope must be exact");
requireValue(JSON.stringify(unitProfileV1Policy?.consumerContract?.fieldProjection) === JSON.stringify(unitProfileV1Projection), "fleet.units.profile.current.v1 field projection must be exact");
requireValue(JSON.stringify(unitProfileV1Policy?.consumerContract?.geometryTypes) === JSON.stringify([]), "fleet.units.profile.current.v1 must remain a non-geometric aspect");
requireValue(!/(provider|tenant|endpoint|credential|token|secret|authorization)/i.test(JSON.stringify(unitProfileV1Policy)), "fleet.units.profile.current.v1 consumer policy crosses the transport/secret boundary");

const unitContactsV1Policy = consumerPolicies.find(
  (policy) => policy.dataProductId === "fleet.units.contacts.current.v1"
    && policy.productVersion === "1.0.0",
);
const unitContactsV1Projection = [
  "device_imei",
  "device_phone_primary",
  "device_phone_secondary",
  "display_name",
  "provider_creator_login",
];
requireValue(
  unitContactsV1Policy?.id === "map-moving-object-unit-contacts-current-v1"
    && unitContactsV1Policy?.version === "1.0.0",
  "fleet.units.contacts.current.v1 consumer policy is missing",
);
requireValue(
  unitContactsV1Policy?.dataClass === "restricted",
  "fleet.units.contacts.current.v1 must be explicitly restricted",
);
requireValue(
  JSON.stringify(unitContactsV1Policy?.consumerContract?.fieldProjection)
    === JSON.stringify(unitContactsV1Projection),
  "fleet.units.contacts.current.v1 field projection must be exact",
);
requireValue(
  JSON.stringify(unitContactsV1Policy?.consumerContract?.geometryTypes) === JSON.stringify([]),
  "fleet.units.contacts.current.v1 must remain a non-geometric aspect",
);
requireValue(
  !/(tenant|endpoint|credential|token|secret|authorization)/i.test(
    JSON.stringify(unitContactsV1Policy),
  ),
  "fleet.units.contacts.current.v1 consumer policy crosses the transport/secret boundary",
);

const ids = components.components.map((component) => component.id);
requireValue(new Set(ids).size === ids.length, "component ids must be unique");
const candidateIds = candidates.candidates.map((component) => component.id);
requireValue(new Set(candidateIds).size === candidateIds.length, "candidate ids must be unique");
requireValue(candidateIds.every((id) => !ids.includes(id)), "a component cannot be both baseline and candidate");
const iconNames = icons.groups.flatMap((group) => group.names ?? []);
requireValue(iconNames.length >= 35, "icon registry must contain the audited baseline set");
requireValue(new Set(iconNames).size === iconNames.length, "icon names must be unique across groups");
const pageTemplateKeys = pages.templates.map((template) => `${template.id}@${template.version}`);
requireValue(new Set(pageTemplateKeys).size === pageTemplateKeys.length, "page template id/version pairs must be unique");

for (const template of pages.templates) {
  requireValue(template.schemaVersion === "0.1.0", `unsupported page template schema: ${template.id ?? "unknown"}`);
  requireValue(template.id && template.version && template.title && template.page, `page template entry is incomplete: ${template.id ?? "unknown"}`);
  requireValue(Array.isArray(template.features), `page template features are missing: ${template.id ?? "unknown"}`);
  requireValue(Array.isArray(template.slots), `page template slots are missing: ${template.id ?? "unknown"}`);
  requireValue(Array.isArray(template.actions), `page template actions are missing: ${template.id ?? "unknown"}`);

  if (template.contracts) {
    requireValue(typeof template.contracts.fixtureSchema === "string", `page template fixture schema is missing: ${template.id ?? "unknown"}`);
    requireValue(Array.isArray(template.contracts.acceptanceFixtures) && template.contracts.acceptanceFixtures.length >= 1, `page template acceptance fixtures are missing: ${template.id ?? "unknown"}`);

    for (const fixturePath of template.contracts.acceptanceFixtures ?? []) {
      let fixture;
      try {
        fixture = await parse(fixturePath);
      } catch {
        failures.push(`missing or invalid acceptance fixture: ${fixturePath}`);
        continue;
      }

      requireValue(fixture.schemaVersion === "0.1.0", `unsupported fixture schema: ${fixturePath}`);
      requireValue(fixture.template?.id === template.id && fixture.template?.version === template.version, `fixture template mismatch: ${fixturePath}`);
      requireValue(["ready", "loading", "empty", "stale", "error", "offline"].includes(fixture.state), `unsupported fixture state: ${fixturePath}`);
      requireValue(Array.isArray(fixture.capabilities), `fixture capabilities are missing: ${fixturePath}`);
      requireValue(Array.isArray(fixture.styleProfiles), `fixture style profiles are missing: ${fixturePath}`);
      requireValue(Array.isArray(fixture.acceptance) && fixture.acceptance.length >= 1, `fixture acceptance checks are missing: ${fixturePath}`);

      const collections = ["layers", "places", "movingObjects", "stations", "routes", "tracks", "zones"];
      requireValue(collections.every((name) => Array.isArray(fixture.scene?.[name])), `fixture scene collections are incomplete: ${fixturePath}`);

      const entities = collections.flatMap((name) => fixture.scene?.[name] ?? []);
      const entityIds = entities.map((entity) => entity.id);
      requireValue(entityIds.every(Boolean), `fixture entity id is missing: ${fixturePath}`);
      requireValue(new Set(entityIds).size === entityIds.length, `fixture entity ids must be unique: ${fixturePath}`);

      const styleIds = fixture.styleProfiles?.map((style) => style.id) ?? [];
      requireValue(styleIds.every(Boolean), `fixture style profile id is missing: ${fixturePath}`);
      requireValue(new Set(styleIds).size === styleIds.length, `fixture style profile ids must be unique: ${fixturePath}`);

      const referencedStyleIds = entities.flatMap((entity) => [entity.styleProfileId, entity.pinStyleProfileId, entity.label?.styleProfileId]).filter(Boolean);
      requireValue(referencedStyleIds.every((id) => styleIds.includes(id)), `fixture references an unknown style profile: ${fixturePath}`);

      const selectedEntityId = fixture.selection?.entityId;
      requireValue(selectedEntityId === null || entityIds.includes(selectedEntityId), `fixture selection references an unknown entity: ${fixturePath}`);

      for (const layer of fixture.scene?.layers ?? []) {
        if (!layer.lodLevels) continue;
        const levels = [...layer.lodLevels].sort((a, b) => a.minRange - b.minRange);
        requireValue(levels.every((level) => level.maxRange > level.minRange), `fixture LOD range is invalid: ${fixturePath}#${layer.id}`);
        requireValue(levels.every((level, index) => index === 0 || level.minRange === levels[index - 1].maxRange), `fixture LOD ranges must be contiguous: ${fixturePath}#${layer.id}`);
      }
    }

    if (template.contracts.lodPolicies) {
      let policySet;
      try {
        policySet = await parse(template.contracts.lodPolicies);
      } catch {
        failures.push(`missing or invalid LOD policy set: ${template.contracts.lodPolicies}`);
      }

      if (policySet) {
        requireValue(policySet.schemaVersion === "0.1.0", `unsupported LOD policy schema: ${template.contracts.lodPolicies}`);
        requireValue(policySet.template?.id === template.id && policySet.template?.version === template.version, `LOD policy template mismatch: ${template.contracts.lodPolicies}`);
        requireValue(policySet.metric === "camera-range-meters", `LOD policy metric must be provider-neutral camera range: ${template.contracts.lodPolicies}`);
        requireValue(policySet.intervalRule === "min-inclusive-max-exclusive", `LOD interval rule is unsupported: ${template.contracts.lodPolicies}`);
        requireValue(Array.isArray(policySet.policies) && policySet.policies.length >= 1, `LOD policies are missing: ${template.contracts.lodPolicies}`);

        const policyIds = policySet.policies?.map((policy) => policy.id) ?? [];
        requireValue(new Set(policyIds).size === policyIds.length, `LOD policy ids must be unique: ${template.contracts.lodPolicies}`);

        for (const policy of policySet.policies ?? []) {
          const bands = [...(policy.bands ?? [])].sort((a, b) => a.minRange - b.minRange);
          requireValue(bands.length >= 1, `LOD policy bands are missing: ${policy.id}`);
          requireValue(new Set(bands.map((band) => band.id)).size === bands.length, `LOD band ids must be unique: ${policy.id}`);
          requireValue(bands.every((band) => band.maxRange > band.minRange), `LOD range is invalid: ${policy.id}`);
          requireValue(bands.every((band, index) => index === 0 || band.minRange === bands[index - 1].maxRange), `LOD ranges must be contiguous: ${policy.id}`);
          requireValue(typeof policy.hysteresisRatio === "number" && policy.hysteresisRatio >= 0 && policy.hysteresisRatio <= 0.5, `LOD hysteresis ratio is invalid: ${policy.id}`);
        }
      }
    }
  }
}

for (const component of components.components) {
  requireValue(component.id && component.status && component.summary, `component entry is incomplete: ${component.id ?? "unknown"}`);
}

for (const pkg of registry.packages) {
  try {
    await access(resolve(root, pkg.path, "package.json"));
  } catch {
    failures.push(`missing package manifest: ${pkg.path}/package.json`);
  }
}

for (const path of Object.values(registry.documentation)) {
  try {
    await access(resolve(root, "registry", path));
  } catch {
    failures.push(`missing documentation target: ${path}`);
  }
}

if (failures.length > 0) {
  console.error(failures.map((failure) => `- ${failure}`).join("\n"));
  process.exit(1);
}

console.log(`Registry valid: ${components.components.length} components, ${iconNames.length} icons, ${pages.templates.length} page templates, ${candidates.candidates.length} candidates, ${sources.sources.length} audited sources.`);
