import {
  type AudioAssetMetadata,
  type ImageAssetMetadata,
  type ModelAssetMetadata,
  type ProjectAssetBoundingBox,
  type ProjectAssetRecord
} from "../assets/project-assets";
import type { ModelInstance } from "../assets/model-instances";
import { isModelInstanceCollisionMode } from "../assets/model-instances";
import {
  type CameraRigControlTargetRef,
  type ActorControlTargetRef,
  getControlEffectResolutionKey,
  isActorPathProgressMode,
  type ControlEffect,
  type ControlTargetRef,
  type InteractionControlTargetRef,
  type LightControlTargetRef,
  type ModelInstanceControlTargetRef,
  type SceneControlTargetRef,
  type SoundEmitterControlTargetRef,
  getControlTargetRefKey
} from "../controls/control-surface";
import { WHITEBOX_SELECTION_MODES } from "../core/whitebox-selection-mode";
import {
  isCameraRigRailPlacementMode,
  isCameraRigTransitionMode,
  isNpcPresenceMode,
  isPlayerStartColliderMode,
  isPlayerStartGamepadActionBinding,
  isPlayerStartGamepadCameraLookBinding,
  isPlayerStartGamepadBinding,
  isPlayerStartKeyboardBindingCode,
  isPlayerStartMovementTemplateKind,
  isPlayerStartNavigationMode,
  getNpcColliderHeight,
  getPlayerStartColliderHeight,
  type CameraRigEntity,
  type CameraRigTargetRef,
  type EntityInstance,
  type InteractableEntity,
  type CharacterColliderSettings,
  type NpcPresence,
  type NpcEntity,
  type PointLightEntity,
  type PlayerStartEntity,
  type SceneEntryEntity,
  type SoundEmitterEntity,
  type SpotLightEntity,
  type TeleportTargetEntity,
  type TriggerVolumeEntity
} from "../entities/entity-instances";
import { type InteractionLink } from "../interactions/interaction-links";
import {
  MAX_BOX_BRUSH_WATER_FOAM_CONTACT_LIMIT,
  hasPositiveBoxSize,
  isBoxBrushLightFalloffMode,
  isBoxBrushVolumeMode,
  normalizeConeSideCount,
  normalizeRadialPrismSideCount,
  normalizeTorusMajorSegmentCount,
  normalizeTorusTubeSegmentCount
} from "./brushes";
import {
  getBrushFaceIds,
  getBrushVertexIds
} from "../geometry/whitebox-topology";
import {
  createSceneDocumentFromProject,
  type ProjectDocument,
  type SceneDocument
} from "./scene-document";
import {
  HOURS_PER_DAY,
  type ProjectTimeSettings
} from "./project-time-settings";
import { MIN_SCENE_PATH_POINT_COUNT, type ScenePath } from "./paths";
import {
  MIN_TERRAIN_SAMPLE_COUNT,
  TERRAIN_LAYER_COUNT,
  type Terrain
} from "./terrains";
import {
  isAdvancedRenderingWaterReflectionMode,
  isAdvancedRenderingShadowMapSize,
  isAdvancedRenderingShadowType,
  isBoxVolumeRenderPath,
  isAdvancedRenderingToneMappingMode,
  isHexColorString,
  isWorldShaderSkyPresetId,
  type WorldCelestialOrbitAuthoringSettings,
  type WorldBackgroundSettings,
  type WorldShaderSkySettings,
  type WorldTimePhaseProfile,
  type WorldSettings
} from "./world-settings";
import {
  createEmptyProjectScheduler,
  isProjectScheduleWeekday,
  type ProjectScheduler
} from "../scheduler/project-scheduler";
import type { ProjectDialogue } from "../dialogues/project-dialogues";
import type {
  ProjectSequence,
  ProjectSequenceLibrary
} from "../sequencer/project-sequences";
import {
  getHeldSequenceControlEffects,
  getProjectScheduleRoutineHeldSteps,
  getProjectSequenceImpulseSteps
} from "../sequencer/project-sequence-steps";

export type SceneDiagnosticSeverity = "error" | "warning";
export type SceneDiagnosticScope = "document" | "build";

export interface SceneDiagnostic {
  code: string;
  severity: SceneDiagnosticSeverity;
  scope: SceneDiagnosticScope;
  message: string;
  path?: string;
}

export interface SceneDocumentValidationResult {
  diagnostics: SceneDiagnostic[];
  errors: SceneDiagnostic[];
  warnings: SceneDiagnostic[];
}

export function createDiagnostic(
  severity: SceneDiagnosticSeverity,
  code: string,
  message: string,
  path?: string,
  scope: SceneDiagnosticScope = "document"
): SceneDiagnostic {
  return {
    code,
    severity,
    scope,
    message,
    path
  };
}

function isFiniteNumber(value: unknown): value is number {
  return typeof value === "number" && Number.isFinite(value);
}

function isFiniteVec3(vector: {
  x: unknown;
  y: unknown;
  z: unknown;
}): vector is { x: number; y: number; z: number } {
  return (
    isFiniteNumber(vector.x) &&
    isFiniteNumber(vector.y) &&
    isFiniteNumber(vector.z)
  );
}

function hasPositiveFiniteVec3(vector: {
  x: unknown;
  y: unknown;
  z: unknown;
}): vector is { x: number; y: number; z: number } {
  return isFiniteVec3(vector) && vector.x > 0 && vector.y > 0 && vector.z > 0;
}

function isNonNegativeFiniteNumber(value: unknown): value is number {
  return isFiniteNumber(value) && value >= 0;
}

function isPositiveFiniteNumber(value: unknown): value is number {
  return isFiniteNumber(value) && value > 0;
}

function isFiniteNumberInRange(
  value: unknown,
  min: number,
  max: number
): value is number {
  return isFiniteNumber(value) && value >= min && value <= max;
}

function isPositiveInteger(value: unknown): value is number {
  return isFiniteNumber(value) && Number.isInteger(value) && value > 0;
}

function isPositiveIntegerInRange(
  value: unknown,
  max: number
): value is number {
  return isPositiveInteger(value) && value <= max;
}

function isBoolean(value: unknown): value is boolean {
  return typeof value === "boolean";
}

function hasNonZeroVectorLength(vector: {
  x: number;
  y: number;
  z: number;
}): boolean {
  return vector.x !== 0 || vector.y !== 0 || vector.z !== 0;
}

function validateWorldBackgroundSettings(
  background: WorldBackgroundSettings,
  document: SceneDocument | ProjectDocument,
  diagnostics: SceneDiagnostic[],
  path: string,
  label: string,
  options: { allowEmptyImageAssetId?: boolean; allowShader?: boolean } = {}
) {
  if (background.mode === "solid") {
    if (!isHexColorString(background.colorHex)) {
      diagnostics.push(
        createDiagnostic(
          "error",
          `invalid-${label}-color`,
          `${label} must use a #RRGGBB color.`,
          `${path}.colorHex`
        )
      );
    }

    return;
  }

  if (background.mode === "verticalGradient") {
    if (!isHexColorString(background.topColorHex)) {
      diagnostics.push(
        createDiagnostic(
          "error",
          `invalid-${label}-top-color`,
          `${label} top color must use a #RRGGBB color.`,
          `${path}.topColorHex`
        )
      );
    }

    if (!isHexColorString(background.bottomColorHex)) {
      diagnostics.push(
        createDiagnostic(
          "error",
          `invalid-${label}-bottom-color`,
          `${label} bottom color must use a #RRGGBB color.`,
          `${path}.bottomColorHex`
        )
      );
    }

    return;
  }

  if (background.mode === "shader") {
    if (options.allowShader === false) {
      diagnostics.push(
        createDiagnostic(
          "error",
          `invalid-${label}-mode`,
          `${label} must not use shader mode here.`,
          `${path}.mode`
        )
      );
    }

    return;
  }

  if (
    typeof background.assetId !== "string" ||
    background.assetId.trim().length === 0
  ) {
    if (!options.allowEmptyImageAssetId) {
      diagnostics.push(
        createDiagnostic(
          "error",
          `invalid-${label}-asset-id`,
          `${label} must reference a non-empty image asset id.`,
          `${path}.assetId`
        )
      );
    }
  } else {
    const backgroundAsset = document.assets[background.assetId];

    if (backgroundAsset === undefined) {
      diagnostics.push(
        createDiagnostic(
          "error",
          `missing-${label}-asset`,
          `${label} asset ${background.assetId} does not exist.`,
          `${path}.assetId`
        )
      );
    } else if (backgroundAsset.kind !== "image") {
      diagnostics.push(
        createDiagnostic(
          "error",
          `invalid-${label}-asset-kind`,
          `${label} must reference an image asset.`,
          `${path}.assetId`
        )
      );
    }
  }

  if (!isNonNegativeFiniteNumber(background.environmentIntensity)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        `invalid-${label}-environment-intensity`,
        `${label} environment intensity must be a non-negative finite number.`,
        `${path}.environmentIntensity`
      )
    );
  }
}

function validateWorldShaderSkySettings(
  settings: WorldShaderSkySettings,
  diagnostics: SceneDiagnostic[],
  path: string
) {
  if (!isWorldShaderSkyPresetId(settings.presetId)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-preset",
        "World shader sky preset must be a supported built-in preset.",
        `${path}.presetId`
      )
    );
  }

  if (!isHexColorString(settings.dayTopColorHex)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-day-top-color",
        "World shader sky day top color must use a #RRGGBB color.",
        `${path}.dayTopColorHex`
      )
    );
  }

  if (!isHexColorString(settings.dayBottomColorHex)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-day-bottom-color",
        "World shader sky day bottom color must use a #RRGGBB color.",
        `${path}.dayBottomColorHex`
      )
    );
  }

  if (!isFiniteNumberInRange(settings.horizonHeight, -0.5, 0.5)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-horizon-height",
        "World shader sky horizon height must stay between -0.5 and 0.5.",
        `${path}.horizonHeight`
      )
    );
  }

  if (!isPositiveFiniteNumber(settings.celestial.sunDiscSizeDegrees)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-sun-disc-size",
        "World shader sky sun disc size must be a positive finite number.",
        `${path}.celestial.sunDiscSizeDegrees`
      )
    );
  }

  if (!isPositiveFiniteNumber(settings.celestial.moonDiscSizeDegrees)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-moon-disc-size",
        "World shader sky moon disc size must be a positive finite number.",
        `${path}.celestial.moonDiscSizeDegrees`
      )
    );
  }

  if (!isNonNegativeFiniteNumber(settings.stars.density)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-star-density",
        "World shader sky star density must be a non-negative finite number.",
        `${path}.stars.density`
      )
    );
  }

  if (!isNonNegativeFiniteNumber(settings.stars.brightness)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-star-brightness",
        "World shader sky star brightness must be a non-negative finite number.",
        `${path}.stars.brightness`
      )
    );
  }

  if (!isFiniteNumberInRange(settings.stars.horizonFadeOffset, -0.5, 0.5)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-star-horizon-fade-offset",
        "World shader sky star horizon offset must stay between -0.5 and 0.5.",
        `${path}.stars.horizonFadeOffset`
      )
    );
  }

  if (!isFiniteNumberInRange(settings.clouds.coverage, 0, 1)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-cloud-coverage",
        "World shader sky cloud coverage must stay between 0 and 1.",
        `${path}.clouds.coverage`
      )
    );
  }

  if (!isNonNegativeFiniteNumber(settings.clouds.density)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-cloud-density",
        "World shader sky cloud density must be a non-negative finite number.",
        `${path}.clouds.density`
      )
    );
  }

  if (!isFiniteNumberInRange(settings.clouds.softness, 0, 1)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-cloud-softness",
        "World shader sky cloud softness must stay between 0 and 1.",
        `${path}.clouds.softness`
      )
    );
  }

  if (!isPositiveFiniteNumber(settings.clouds.scale)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-cloud-scale",
        "World shader sky cloud scale must be a positive finite number.",
        `${path}.clouds.scale`
      )
    );
  }

  if (!isFiniteNumberInRange(settings.clouds.height, 0, 1)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-cloud-height",
        "World shader sky cloud height must stay between 0 and 1.",
        `${path}.clouds.height`
      )
    );
  }

  if (!isFiniteNumberInRange(settings.clouds.heightVariation, 0, 1)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-cloud-height-variation",
        "World shader sky cloud height variation must stay between 0 and 1.",
        `${path}.clouds.heightVariation`
      )
    );
  }

  if (!isHexColorString(settings.clouds.tintHex)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-cloud-tint",
        "World shader sky cloud tint must use a #RRGGBB color.",
        `${path}.clouds.tintHex`
      )
    );
  }

  if (!isFiniteNumberInRange(settings.clouds.opacity, 0, 1)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-cloud-opacity",
        "World shader sky cloud opacity must stay between 0 and 1.",
        `${path}.clouds.opacity`
      )
    );
  }

  if (!isFiniteNumberInRange(settings.clouds.opacityRandomness, 0, 1)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-cloud-opacity-randomness",
        "World shader sky cloud opacity randomness must stay between 0 and 1.",
        `${path}.clouds.opacityRandomness`
      )
    );
  }

  if (!isNonNegativeFiniteNumber(settings.clouds.driftSpeed)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-cloud-drift-speed",
        "World shader sky cloud drift speed must be a non-negative finite number.",
        `${path}.clouds.driftSpeed`
      )
    );
  }

  if (!isFiniteNumber(settings.clouds.driftDirectionDegrees)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-cloud-drift-direction",
        "World shader sky cloud drift direction must be a finite number.",
        `${path}.clouds.driftDirectionDegrees`
      )
    );
  }

  if (typeof settings.aurora.enabled !== "boolean") {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-aurora-enabled",
        "World shader sky aurora toggle must be true or false.",
        `${path}.aurora.enabled`
      )
    );
  }

  if (!isNonNegativeFiniteNumber(settings.aurora.intensity)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-aurora-intensity",
        "World shader sky aurora intensity must be a non-negative finite number.",
        `${path}.aurora.intensity`
      )
    );
  }

  if (!isFiniteNumberInRange(settings.aurora.height, 0, 1)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-aurora-height",
        "World shader sky aurora height must stay between 0 and 1.",
        `${path}.aurora.height`
      )
    );
  }

  if (!isFiniteNumberInRange(settings.aurora.thickness, 0, 1)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-aurora-thickness",
        "World shader sky aurora thickness must stay between 0 and 1.",
        `${path}.aurora.thickness`
      )
    );
  }

  if (!isNonNegativeFiniteNumber(settings.aurora.speed)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-aurora-speed",
        "World shader sky aurora speed must be a non-negative finite number.",
        `${path}.aurora.speed`
      )
    );
  }

  if (!isHexColorString(settings.aurora.primaryColorHex)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-aurora-primary-color",
        "World shader sky aurora primary color must use a #RRGGBB color.",
        `${path}.aurora.primaryColorHex`
      )
    );
  }

  if (!isHexColorString(settings.aurora.secondaryColorHex)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-shader-sky-aurora-secondary-color",
        "World shader sky aurora secondary color must use a #RRGGBB color.",
        `${path}.aurora.secondaryColorHex`
      )
    );
  }
}

function validateWorldCelestialOrbitSettings(
  settings: WorldCelestialOrbitAuthoringSettings,
  diagnostics: SceneDiagnostic[],
  path: string
) {
  const validateOrbit = (
    orbit: WorldCelestialOrbitAuthoringSettings["sun"],
    orbitPath: string,
    label: "sun" | "moon"
  ) => {
    if (!isFiniteNumberInRange(orbit.azimuthDegrees, 0, 360)) {
      diagnostics.push(
        createDiagnostic(
          "error",
          `invalid-world-${label}-orbit-azimuth`,
          `World ${label} orbit azimuth must stay between 0 and 360 degrees.`,
          `${orbitPath}.azimuthDegrees`
        )
      );
    }

    if (!isFiniteNumberInRange(orbit.peakAltitudeDegrees, 0.1, 89.9)) {
      diagnostics.push(
        createDiagnostic(
          "error",
          `invalid-world-${label}-orbit-peak-altitude`,
          `World ${label} orbit peak altitude must stay between 0.1 and 89.9 degrees.`,
          `${orbitPath}.peakAltitudeDegrees`
        )
      );
    }
  };

  validateOrbit(settings.sun, `${path}.sun`, "sun");
  validateOrbit(settings.moon, `${path}.moon`, "moon");
}

function validateWorldSettings(
  world: WorldSettings,
  document: SceneDocument,
  diagnostics: SceneDiagnostic[]
) {
  if (!isBoolean(world.projectTimeLightingEnabled)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-project-time-lighting-enabled",
        "Scene world project-time lighting toggle must be true or false.",
        "world.projectTimeLightingEnabled"
      )
    );
  }

  if (!isBoolean(world.showCelestialBodies)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-show-celestial-bodies",
        "Scene world celestial body toggle must be true or false.",
        "world.showCelestialBodies"
      )
    );
  }

  validateWorldBackgroundSettings(
    world.background,
    document,
    diagnostics,
    "world.background",
    "world-background"
  );
  validateWorldShaderSkySettings(
    world.shaderSky,
    diagnostics,
    "world.shaderSky"
  );
  validateWorldCelestialOrbitSettings(
    world.celestialOrbits,
    diagnostics,
    "world.celestialOrbits"
  );

  if (!isHexColorString(world.ambientLight.colorHex)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-ambient-color",
        "World ambient light must use a #RRGGBB color.",
        "world.ambientLight.colorHex"
      )
    );
  }

  if (!isNonNegativeFiniteNumber(world.ambientLight.intensity)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-ambient-intensity",
        "World ambient light intensity must remain finite and zero or greater.",
        "world.ambientLight.intensity"
      )
    );
  }

  if (!isHexColorString(world.sunLight.colorHex)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-sun-color",
        "World sun color must use a #RRGGBB color.",
        "world.sunLight.colorHex"
      )
    );
  }

  if (!isNonNegativeFiniteNumber(world.sunLight.intensity)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-sun-intensity",
        "World sun intensity must remain finite and zero or greater.",
        "world.sunLight.intensity"
      )
    );
  }

  if (
    !isFiniteVec3(world.sunLight.direction) ||
    !hasNonZeroVectorLength(world.sunLight.direction)
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-world-sun-direction",
        "World sun direction must remain finite and must not be the zero vector.",
        "world.sunLight.direction"
      )
    );
  }

  validateWorldTimePhaseProfile(
    world.timeOfDay.dawn,
    diagnostics,
    document,
    "world.timeOfDay.dawn",
    "dawn"
  );
  validateWorldTimePhaseProfile(
    world.timeOfDay.dusk,
    diagnostics,
    document,
    "world.timeOfDay.dusk",
    "dusk"
  );
  validateWorldBackgroundSettings(
    world.timeOfDay.night.background,
    document,
    diagnostics,
    "world.timeOfDay.night.background",
    "night-background",
    {
      allowShader: false
    }
  );

  if (!isHexColorString(world.timeOfDay.night.ambientColorHex)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-night-ambient-color",
        "night ambient color must use a #RRGGBB color.",
        "world.timeOfDay.night.ambientColorHex"
      )
    );
  }

  if (
    !isNonNegativeFiniteNumber(world.timeOfDay.night.ambientIntensityFactor)
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-night-ambient-intensity-factor",
        "night ambient intensity factor must be a non-negative finite number.",
        "world.timeOfDay.night.ambientIntensityFactor"
      )
    );
  }

  if (!isHexColorString(world.timeOfDay.night.lightColorHex)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-night-light-color",
        "night light color must use a #RRGGBB color.",
        "world.timeOfDay.night.lightColorHex"
      )
    );
  }

  if (!isNonNegativeFiniteNumber(world.timeOfDay.night.lightIntensityFactor)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-night-light-intensity-factor",
        "night light intensity factor must be a non-negative finite number.",
        "world.timeOfDay.night.lightIntensityFactor"
      )
    );
  }

  const advancedRendering = world.advancedRendering;

  if (!isBoolean(advancedRendering.enabled)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-advanced-rendering-enabled",
        "Advanced rendering enabled must be a boolean.",
        "world.advancedRendering.enabled"
      )
    );
  }

  if (!isBoolean(advancedRendering.shadows.enabled)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-advanced-rendering-shadows-enabled",
        "Advanced rendering shadow enabled must be a boolean.",
        "world.advancedRendering.shadows.enabled"
      )
    );
  }

  if (!isAdvancedRenderingShadowMapSize(advancedRendering.shadows.mapSize)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-advanced-rendering-shadow-map-size",
        "Advanced rendering shadow map size must be one of 512, 1024, 2048, or 4096.",
        "world.advancedRendering.shadows.mapSize"
      )
    );
  }

  if (!isAdvancedRenderingShadowType(advancedRendering.shadows.type)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-advanced-rendering-shadow-type",
        "Advanced rendering shadow type must be basic, pcf, or pcfSoft.",
        "world.advancedRendering.shadows.type"
      )
    );
  }

  if (!isFiniteNumber(advancedRendering.shadows.bias)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-advanced-rendering-shadow-bias",
        "Advanced rendering shadow bias must be a finite number.",
        "world.advancedRendering.shadows.bias"
      )
    );
  }

  if (!isBoolean(advancedRendering.ambientOcclusion.enabled)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-advanced-rendering-ao-enabled",
        "Advanced rendering ambient occlusion enabled must be a boolean.",
        "world.advancedRendering.ambientOcclusion.enabled"
      )
    );
  }

  if (
    !isNonNegativeFiniteNumber(advancedRendering.ambientOcclusion.intensity)
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-advanced-rendering-ao-intensity",
        "Advanced rendering ambient occlusion intensity must be a non-negative finite number.",
        "world.advancedRendering.ambientOcclusion.intensity"
      )
    );
  }

  if (!isNonNegativeFiniteNumber(advancedRendering.ambientOcclusion.radius)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-advanced-rendering-ao-radius",
        "Advanced rendering ambient occlusion radius must be a non-negative finite number.",
        "world.advancedRendering.ambientOcclusion.radius"
      )
    );
  }

  if (!isPositiveInteger(advancedRendering.ambientOcclusion.samples)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-advanced-rendering-ao-samples",
        "Advanced rendering ambient occlusion samples must be a positive integer.",
        "world.advancedRendering.ambientOcclusion.samples"
      )
    );
  }

  if (!isBoolean(advancedRendering.bloom.enabled)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-advanced-rendering-bloom-enabled",
        "Advanced rendering bloom enabled must be a boolean.",
        "world.advancedRendering.bloom.enabled"
      )
    );
  }

  if (!isNonNegativeFiniteNumber(advancedRendering.bloom.intensity)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-advanced-rendering-bloom-intensity",
        "Advanced rendering bloom intensity must be a non-negative finite number.",
        "world.advancedRendering.bloom.intensity"
      )
    );
  }

  if (!isNonNegativeFiniteNumber(advancedRendering.bloom.threshold)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-advanced-rendering-bloom-threshold",
        "Advanced rendering bloom threshold must be a non-negative finite number.",
        "world.advancedRendering.bloom.threshold"
      )
    );
  }

  if (!isNonNegativeFiniteNumber(advancedRendering.bloom.radius)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-advanced-rendering-bloom-radius",
        "Advanced rendering bloom radius must be a non-negative finite number.",
        "world.advancedRendering.bloom.radius"
      )
    );
  }

  if (!isAdvancedRenderingToneMappingMode(advancedRendering.toneMapping.mode)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-advanced-rendering-tone-mapping-mode",
        "Advanced rendering tone mapping mode must be none, linear, reinhard, cineon, or acesFilmic.",
        "world.advancedRendering.toneMapping.mode"
      )
    );
  }

  if (!isPositiveFiniteNumber(advancedRendering.toneMapping.exposure)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-advanced-rendering-tone-mapping-exposure",
        "Advanced rendering tone mapping exposure must be a positive finite number.",
        "world.advancedRendering.toneMapping.exposure"
      )
    );
  }

  if (!isBoolean(advancedRendering.depthOfField.enabled)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-advanced-rendering-dof-enabled",
        "Advanced rendering depth of field enabled must be a boolean.",
        "world.advancedRendering.depthOfField.enabled"
      )
    );
  }

  if (
    !isNonNegativeFiniteNumber(advancedRendering.depthOfField.focusDistance)
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-advanced-rendering-dof-focus-distance",
        "Advanced rendering depth of field focus distance must be a non-negative finite number.",
        "world.advancedRendering.depthOfField.focusDistance"
      )
    );
  }

  if (!isPositiveFiniteNumber(advancedRendering.depthOfField.focalLength)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-advanced-rendering-dof-focal-length",
        "Advanced rendering depth of field focal length must be a positive finite number.",
        "world.advancedRendering.depthOfField.focalLength"
      )
    );
  }

  if (!isPositiveFiniteNumber(advancedRendering.depthOfField.bokehScale)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-advanced-rendering-dof-bokeh-scale",
        "Advanced rendering depth of field bokeh scale must be a positive finite number.",
        "world.advancedRendering.depthOfField.bokehScale"
      )
    );
  }

  if (!isBoolean(advancedRendering.whiteboxBevel.enabled)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-advanced-rendering-whitebox-bevel-enabled",
        "Advanced rendering whitebox bevel enabled must be a boolean.",
        "world.advancedRendering.whiteboxBevel.enabled"
      )
    );
  }

  if (!isNonNegativeFiniteNumber(advancedRendering.whiteboxBevel.edgeWidth)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-advanced-rendering-whitebox-bevel-edge-width",
        "Advanced rendering whitebox bevel edge width must be a non-negative finite number.",
        "world.advancedRendering.whiteboxBevel.edgeWidth"
      )
    );
  }

  if (
    !isNonNegativeFiniteNumber(advancedRendering.whiteboxBevel.normalStrength)
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-advanced-rendering-whitebox-bevel-normal-strength",
        "Advanced rendering whitebox bevel normal strength must be a non-negative finite number.",
        "world.advancedRendering.whiteboxBevel.normalStrength"
      )
    );
  }

  if (!isBoxVolumeRenderPath(advancedRendering.fogPath)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-advanced-rendering-fog-path",
        "Advanced rendering fog path must be performance or quality.",
        "world.advancedRendering.fogPath"
      )
    );
  }

  if (!isBoxVolumeRenderPath(advancedRendering.waterPath)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-advanced-rendering-water-path",
        "Advanced rendering water path must be performance or quality.",
        "world.advancedRendering.waterPath"
      )
    );
  }

  if (
    !isAdvancedRenderingWaterReflectionMode(
      advancedRendering.waterReflectionMode
    )
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-advanced-rendering-water-reflection-mode",
        "Advanced rendering water reflection mode must be none, world, or all.",
        "world.advancedRendering.waterReflectionMode"
      )
    );
  }
}

function validateWorldTimePhaseProfile(
  profile: WorldTimePhaseProfile,
  diagnostics: SceneDiagnostic[],
  document: SceneDocument | ProjectDocument,
  path: string,
  label: string
) {
  validateWorldBackgroundSettings(
    profile.background,
    document,
    diagnostics,
    `${path}.background`,
    `${label}-background`,
    {
      allowEmptyImageAssetId: true,
      allowShader: false
    }
  );

  if (!isHexColorString(profile.skyTopColorHex)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        `invalid-${label}-sky-top-color`,
        `${label} sky top color must use a #RRGGBB color.`,
        `${path}.skyTopColorHex`
      )
    );
  }

  if (!isHexColorString(profile.skyBottomColorHex)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        `invalid-${label}-sky-bottom-color`,
        `${label} sky bottom color must use a #RRGGBB color.`,
        `${path}.skyBottomColorHex`
      )
    );
  }

  if (!isHexColorString(profile.ambientColorHex)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        `invalid-${label}-ambient-color`,
        `${label} ambient color must use a #RRGGBB color.`,
        `${path}.ambientColorHex`
      )
    );
  }

  if (!isNonNegativeFiniteNumber(profile.ambientIntensityFactor)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        `invalid-${label}-ambient-intensity-factor`,
        `${label} ambient intensity factor must be a non-negative finite number.`,
        `${path}.ambientIntensityFactor`
      )
    );
  }

  if (!isHexColorString(profile.lightColorHex)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        `invalid-${label}-light-color`,
        `${label} light color must use a #RRGGBB color.`,
        `${path}.lightColorHex`
      )
    );
  }

  if (!isNonNegativeFiniteNumber(profile.lightIntensityFactor)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        `invalid-${label}-light-intensity-factor`,
        `${label} light intensity factor must be a non-negative finite number.`,
        `${path}.lightIntensityFactor`
      )
    );
  }
}

function validateProjectTimeSettings(
  time: ProjectTimeSettings,
  diagnostics: SceneDiagnostic[],
  path = "time"
) {
  if (!isPositiveInteger(time.startDayNumber)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-project-time-start-day-number",
        "Project start day must be a positive integer.",
        `${path}.startDayNumber`
      )
    );
  }

  if (!isFiniteNumber(time.startTimeOfDayHours)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-project-time-start-hours",
        "Project time start-of-day must be a finite hour value.",
        `${path}.startTimeOfDayHours`
      )
    );
  } else if (
    time.startTimeOfDayHours < 0 ||
    time.startTimeOfDayHours >= HOURS_PER_DAY
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-project-time-start-range",
        "Project time start-of-day must stay within the 0..24 hour range.",
        `${path}.startTimeOfDayHours`
      )
    );
  }

  if (!isFiniteNumber(time.sunriseTimeOfDayHours)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-project-time-sunrise-hours",
        "Project sunrise must be a finite hour value.",
        `${path}.sunriseTimeOfDayHours`
      )
    );
  } else if (
    time.sunriseTimeOfDayHours < 0 ||
    time.sunriseTimeOfDayHours >= HOURS_PER_DAY
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-project-time-sunrise-range",
        "Project sunrise must stay within the 0..24 hour range.",
        `${path}.sunriseTimeOfDayHours`
      )
    );
  }

  if (!isFiniteNumber(time.sunsetTimeOfDayHours)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-project-time-sunset-hours",
        "Project sunset must be a finite hour value.",
        `${path}.sunsetTimeOfDayHours`
      )
    );
  } else if (
    time.sunsetTimeOfDayHours < 0 ||
    time.sunsetTimeOfDayHours >= HOURS_PER_DAY
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-project-time-sunset-range",
        "Project sunset must stay within the 0..24 hour range.",
        `${path}.sunsetTimeOfDayHours`
      )
    );
  }

  if (
    isFiniteNumber(time.sunriseTimeOfDayHours) &&
    isFiniteNumber(time.sunsetTimeOfDayHours) &&
    time.sunriseTimeOfDayHours >= time.sunsetTimeOfDayHours
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-project-time-sun-window",
        "Project sunrise must be earlier than project sunset.",
        `${path}.sunriseTimeOfDayHours`
      )
    );
  }

  if (!isPositiveFiniteNumber(time.dayLengthMinutes)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-project-time-day-length",
        "Project time day length must be a positive finite number of real minutes.",
        `${path}.dayLengthMinutes`
      )
    );
  }

  if (
    !isPositiveFiniteNumber(time.dawnDurationHours) ||
    time.dawnDurationHours >= HOURS_PER_DAY
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-project-time-dawn-duration",
        "Project dawn duration must be a positive finite number shorter than one day.",
        `${path}.dawnDurationHours`
      )
    );
  }

  if (
    !isPositiveFiniteNumber(time.duskDurationHours) ||
    time.duskDurationHours >= HOURS_PER_DAY
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-project-time-dusk-duration",
        "Project dusk duration must be a positive finite number shorter than one day.",
        `${path}.duskDurationHours`
      )
    );
  }
}

function validatePointLightEntity(
  entity: PointLightEntity,
  path: string,
  diagnostics: SceneDiagnostic[]
) {
  validateAuthoredEntityState(entity, path, diagnostics);

  if (!isFiniteVec3(entity.position)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-point-light-position",
        "Point Light position must remain finite on every axis.",
        `${path}.position`
      )
    );
  }

  if (!isHexColorString(entity.colorHex)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-point-light-color",
        "Point Light color must use a #RRGGBB color.",
        `${path}.colorHex`
      )
    );
  }

  if (!isNonNegativeFiniteNumber(entity.intensity)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-point-light-intensity",
        "Point Light intensity must remain finite and zero or greater.",
        `${path}.intensity`
      )
    );
  }

  if (!isPositiveFiniteNumber(entity.distance)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-point-light-distance",
        "Point Light distance must remain finite and greater than zero.",
        `${path}.distance`
      )
    );
  }
}

function validateSpotLightEntity(
  entity: SpotLightEntity,
  path: string,
  diagnostics: SceneDiagnostic[]
) {
  validateAuthoredEntityState(entity, path, diagnostics);

  if (!isFiniteVec3(entity.position)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-spot-light-position",
        "Spot Light position must remain finite on every axis.",
        `${path}.position`
      )
    );
  }

  if (
    !isFiniteVec3(entity.direction) ||
    !hasNonZeroVectorLength(entity.direction)
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-spot-light-direction",
        "Spot Light direction must remain finite and must not be the zero vector.",
        `${path}.direction`
      )
    );
  }

  if (!isHexColorString(entity.colorHex)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-spot-light-color",
        "Spot Light color must use a #RRGGBB color.",
        `${path}.colorHex`
      )
    );
  }

  if (!isNonNegativeFiniteNumber(entity.intensity)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-spot-light-intensity",
        "Spot Light intensity must remain finite and zero or greater.",
        `${path}.intensity`
      )
    );
  }

  if (!isPositiveFiniteNumber(entity.distance)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-spot-light-distance",
        "Spot Light distance must remain finite and greater than zero.",
        `${path}.distance`
      )
    );
  }

  if (
    !isFiniteNumber(entity.angleDegrees) ||
    entity.angleDegrees <= 0 ||
    entity.angleDegrees >= 180
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-spot-light-angle",
        "Spot Light angle must remain a finite degree value between 0 and 180.",
        `${path}.angleDegrees`
      )
    );
  }
}

function validateCameraRigTargetRef(
  target: CameraRigTargetRef,
  entity: CameraRigEntity,
  path: string,
  document: SceneDocument,
  diagnostics: SceneDiagnostic[]
) {
  switch (target.kind) {
    case "player":
      return;
    case "actor": {
      if (target.actorId.trim().length === 0) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-camera-rig-target-actor-id",
            "Camera Rig actor targets must reference a non-empty actor id.",
            `${path}.actorId`
          )
        );
        return;
      }

      const matchingActor = Object.values(document.entities).some(
        (candidate) =>
          candidate.kind === "npc" && candidate.actorId === target.actorId
      );

      if (!matchingActor) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "missing-camera-rig-target-actor",
            `Camera Rig actor target ${target.actorId} does not exist in this scene.`,
            `${path}.actorId`
          )
        );
      }
      return;
    }
    case "entity": {
      if (target.entityId.trim().length === 0) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-camera-rig-target-entity-id",
            "Camera Rig entity targets must reference a non-empty entity id.",
            `${path}.entityId`
          )
        );
        return;
      }

      const targetEntity = document.entities[target.entityId];

      if (targetEntity === undefined) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "missing-camera-rig-target-entity",
            `Camera Rig entity target ${target.entityId} does not exist in this scene.`,
            `${path}.entityId`
          )
        );
        return;
      }

      if (targetEntity.id === entity.id) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "camera-rig-self-target",
            "Camera Rigs must not target themselves.",
            `${path}.entityId`
          )
        );
      }

      if (targetEntity.kind === "cameraRig") {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-camera-rig-target-entity-kind",
            "Camera Rigs must not target another Camera Rig entity.",
            `${path}.entityId`
          )
        );
      }
      return;
    }
    case "worldPoint":
      if (!isFiniteVec3(target.point)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-camera-rig-target-world-point",
            "Camera Rig world-point targets must remain finite on every axis.",
            `${path}.point`
          )
        );
      }
      return;
  }
}

function validateCameraRigEntity(
  entity: CameraRigEntity,
  path: string,
  document: SceneDocument,
  diagnostics: SceneDiagnostic[]
) {
  validateAuthoredEntityState(entity, path, diagnostics);

  if (entity.rigType === "fixed") {
    if (!isFiniteVec3(entity.position)) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-camera-rig-position",
          "Camera Rig position must remain finite on every axis.",
          `${path}.position`
        )
      );
    }
  } else {
    if (entity.pathId.trim().length === 0) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-camera-rig-path-id",
          "Rail Camera Rig path ids must be non-empty.",
          `${path}.pathId`
        )
      );
    } else {
      const authoredPath = document.paths[entity.pathId] ?? null;

      if (authoredPath === null) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "missing-camera-rig-path",
            `Rail Camera Rig path ${entity.pathId} does not exist in the scene.`,
            `${path}.pathId`
          )
        );
      } else if (!authoredPath.enabled) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "disabled-camera-rig-path",
            "Rail Camera Rigs require an enabled authored path.",
            `${path}.pathId`
          )
        );
      }
    }

    if (!isCameraRigRailPlacementMode(entity.railPlacementMode)) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-camera-rig-rail-placement-mode",
          "Rail Camera Rig placement mode must be nearestToTarget or mapTargetBetweenPoints.",
          `${path}.railPlacementMode`
        )
      );
    } else if (entity.railPlacementMode === "mapTargetBetweenPoints") {
      if (!isFiniteVec3(entity.trackStartPoint)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-camera-rig-track-start-point",
            "Mapped Rail Camera Rig track start points must remain finite on every axis.",
            `${path}.trackStartPoint`
          )
        );
      }

      if (!isFiniteVec3(entity.trackEndPoint)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-camera-rig-track-end-point",
            "Mapped Rail Camera Rig track end points must remain finite on every axis.",
            `${path}.trackEndPoint`
          )
        );
      }

      if (!isFiniteNumberInRange(entity.railStartProgress, 0, 1)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-camera-rig-rail-start-progress",
            "Mapped Rail Camera Rig start progress must remain between 0 and 1.",
            `${path}.railStartProgress`
          )
        );
      }

      if (!isFiniteNumberInRange(entity.railEndProgress, 0, 1)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-camera-rig-rail-end-progress",
            "Mapped Rail Camera Rig end progress must remain between 0 and 1.",
            `${path}.railEndProgress`
          )
        );
      }
    }
  }

  if (!isNonNegativeFiniteNumber(entity.priority)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-camera-rig-priority",
        "Camera Rig priority must remain finite and zero or greater.",
        `${path}.priority`
      )
    );
  }

  if (!isBoolean(entity.defaultActive)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-camera-rig-default-active",
        "Camera Rig defaultActive must remain a boolean.",
        `${path}.defaultActive`
      )
    );
  }

  validateCameraRigTargetRef(
    entity.target,
    entity,
    `${path}.target`,
    document,
    diagnostics
  );

  if (!isFiniteVec3(entity.targetOffset)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-camera-rig-target-offset",
        "Camera Rig targetOffset must remain finite on every axis.",
        `${path}.targetOffset`
      )
    );
  }

  if (!isCameraRigTransitionMode(entity.transitionMode)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-camera-rig-transition-mode",
        "Camera Rig transitionMode must be cut or blend.",
        `${path}.transitionMode`
      )
    );
  }

  if (!isNonNegativeFiniteNumber(entity.transitionDurationSeconds)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-camera-rig-transition-duration",
        "Camera Rig transition duration must remain finite and zero or greater.",
        `${path}.transitionDurationSeconds`
      )
    );
  }

  if (!isBoolean(entity.lookAround.enabled)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-camera-rig-look-around-enabled",
        "Camera Rig look-around enabled must remain a boolean.",
        `${path}.lookAround.enabled`
      )
    );
  }

  if (!isNonNegativeFiniteNumber(entity.lookAround.yawLimitDegrees)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-camera-rig-look-around-yaw-limit",
        "Camera Rig look-around yaw limit must remain finite and zero or greater.",
        `${path}.lookAround.yawLimitDegrees`
      )
    );
  }

  if (!isNonNegativeFiniteNumber(entity.lookAround.pitchLimitDegrees)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-camera-rig-look-around-pitch-limit",
        "Camera Rig look-around pitch limit must remain finite and zero or greater.",
        `${path}.lookAround.pitchLimitDegrees`
      )
    );
  }

  if (!isNonNegativeFiniteNumber(entity.lookAround.recenterSpeed)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-camera-rig-look-around-recenter-speed",
        "Camera Rig look-around recenter speed must remain finite and zero or greater.",
        `${path}.lookAround.recenterSpeed`
      )
    );
  }
}

function validateProjectAssetBoundingBox(
  boundingBox: ProjectAssetBoundingBox | null,
  path: string,
  diagnostics: SceneDiagnostic[]
) {
  if (boundingBox === null) {
    return;
  }

  if (!isFiniteVec3(boundingBox.min)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-asset-bounding-box-min",
        "Model asset bounding boxes must have finite minimum coordinates.",
        `${path}.min`
      )
    );
  }

  if (!isFiniteVec3(boundingBox.max)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-asset-bounding-box-max",
        "Model asset bounding boxes must have finite maximum coordinates.",
        `${path}.max`
      )
    );
  }

  if (
    !isFiniteVec3(boundingBox.size) ||
    boundingBox.size.x < 0 ||
    boundingBox.size.y < 0 ||
    boundingBox.size.z < 0
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-asset-bounding-box-size",
        "Model asset bounding boxes must have finite, zero-or-greater size values.",
        `${path}.size`
      )
    );
  }
}

function validateModelAssetMetadata(
  metadata: ModelAssetMetadata,
  path: string,
  diagnostics: SceneDiagnostic[]
) {
  if (metadata.format !== "glb" && metadata.format !== "gltf") {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-model-asset-format",
        "Model asset format must be glb or gltf.",
        `${path}.format`
      )
    );
  }

  if (metadata.sceneName !== null && metadata.sceneName.trim().length === 0) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-model-asset-scene-name",
        "Model asset scene names must be non-empty when authored.",
        `${path}.sceneName`
      )
    );
  }

  if (!isNonNegativeFiniteNumber(metadata.nodeCount)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-model-asset-node-count",
        "Model asset node counts must be finite and zero or greater.",
        `${path}.nodeCount`
      )
    );
  }

  if (!isNonNegativeFiniteNumber(metadata.meshCount)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-model-asset-mesh-count",
        "Model asset mesh counts must be finite and zero or greater.",
        `${path}.meshCount`
      )
    );
  }

  if (
    !Array.isArray(metadata.materialNames) ||
    metadata.materialNames.some((name) => typeof name !== "string")
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-model-asset-material-names",
        "Model asset material names must be string arrays.",
        `${path}.materialNames`
      )
    );
  }

  if (
    !Array.isArray(metadata.textureNames) ||
    metadata.textureNames.some((name) => typeof name !== "string")
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-model-asset-texture-names",
        "Model asset texture names must be string arrays.",
        `${path}.textureNames`
      )
    );
  }

  if (
    !Array.isArray(metadata.animationNames) ||
    metadata.animationNames.some((name) => typeof name !== "string")
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-model-asset-animation-names",
        "Model asset animation names must be string arrays.",
        `${path}.animationNames`
      )
    );
  }

  validateProjectAssetBoundingBox(
    metadata.boundingBox,
    `${path}.boundingBox`,
    diagnostics
  );

  if (
    !Array.isArray(metadata.warnings) ||
    metadata.warnings.some((warning) => typeof warning !== "string")
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-model-asset-warnings",
        "Model asset warnings must be string arrays.",
        `${path}.warnings`
      )
    );
  }
}

function validateImageAssetMetadata(
  metadata: ImageAssetMetadata,
  path: string,
  diagnostics: SceneDiagnostic[]
) {
  if (!isPositiveFiniteNumber(metadata.width)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-image-asset-width",
        "Image asset width must be finite and greater than zero.",
        `${path}.width`
      )
    );
  }

  if (!isPositiveFiniteNumber(metadata.height)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-image-asset-height",
        "Image asset height must be finite and greater than zero.",
        `${path}.height`
      )
    );
  }

  if (!isBoolean(metadata.hasAlpha)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-image-asset-alpha",
        "Image asset alpha flags must be booleans.",
        `${path}.hasAlpha`
      )
    );
  }

  if (
    !Array.isArray(metadata.warnings) ||
    metadata.warnings.some((warning) => typeof warning !== "string")
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-image-asset-warnings",
        "Image asset warnings must be string arrays.",
        `${path}.warnings`
      )
    );
  }
}

function validateAudioAssetMetadata(
  metadata: AudioAssetMetadata,
  path: string,
  diagnostics: SceneDiagnostic[]
) {
  if (
    metadata.durationSeconds !== null &&
    !isNonNegativeFiniteNumber(metadata.durationSeconds)
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-audio-asset-duration",
        "Audio asset durations must be finite and zero or greater when authored.",
        `${path}.durationSeconds`
      )
    );
  }

  if (
    metadata.channelCount !== null &&
    !isPositiveFiniteNumber(metadata.channelCount)
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-audio-asset-channel-count",
        "Audio asset channel counts must be finite and greater than zero when authored.",
        `${path}.channelCount`
      )
    );
  }

  if (
    metadata.sampleRateHz !== null &&
    !isPositiveFiniteNumber(metadata.sampleRateHz)
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-audio-asset-sample-rate",
        "Audio asset sample rates must be finite and greater than zero when authored.",
        `${path}.sampleRateHz`
      )
    );
  }

  if (
    !Array.isArray(metadata.warnings) ||
    metadata.warnings.some((warning) => typeof warning !== "string")
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-audio-asset-warnings",
        "Audio asset warnings must be string arrays.",
        `${path}.warnings`
      )
    );
  }
}

function validateProjectAsset(
  asset: ProjectAssetRecord,
  path: string,
  diagnostics: SceneDiagnostic[]
) {
  if (asset.sourceName.trim().length === 0) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-asset-source-name",
        "Asset source names must be non-empty strings.",
        `${path}.sourceName`
      )
    );
  }

  if (asset.mimeType.trim().length === 0) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-asset-mime-type",
        "Asset mime types must be non-empty strings.",
        `${path}.mimeType`
      )
    );
  }

  if (asset.storageKey.trim().length === 0) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-asset-storage-key",
        "Asset storage keys must be non-empty strings.",
        `${path}.storageKey`
      )
    );
  }

  if (!isPositiveFiniteNumber(asset.byteLength)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-asset-byte-length",
        "Asset byte lengths must be finite and greater than zero.",
        `${path}.byteLength`
      )
    );
  }

  switch (asset.kind) {
    case "model":
      validateModelAssetMetadata(
        asset.metadata,
        `${path}.metadata`,
        diagnostics
      );
      break;
    case "image":
      validateImageAssetMetadata(
        asset.metadata,
        `${path}.metadata`,
        diagnostics
      );
      break;
    case "audio":
      validateAudioAssetMetadata(
        asset.metadata,
        `${path}.metadata`,
        diagnostics
      );
      break;
  }
}

function validateModelInstance(
  modelInstance: ModelInstance,
  path: string,
  document: SceneDocument,
  diagnostics: SceneDiagnostic[]
) {
  if (
    modelInstance.name !== undefined &&
    modelInstance.name.trim().length === 0
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-model-instance-name",
        "Model instance names must be non-empty when authored.",
        `${path}.name`
      )
    );
  }

  if (!isFiniteVec3(modelInstance.position)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-model-instance-position",
        "Model instance positions must remain finite on every axis.",
        `${path}.position`
      )
    );
  }

  if (!isFiniteVec3(modelInstance.rotationDegrees)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-model-instance-rotation",
        "Model instance rotations must remain finite on every axis.",
        `${path}.rotationDegrees`
      )
    );
  }

  if (!hasPositiveFiniteVec3(modelInstance.scale)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-model-instance-scale",
        "Model instance scales must remain finite and positive on every axis.",
        `${path}.scale`
      )
    );
  }

  if (!isModelInstanceCollisionMode(modelInstance.collision.mode)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-model-instance-collision-mode",
        "Model instance collision mode must be one of none, terrain, static, static-simple, dynamic, or simple.",
        `${path}.collision.mode`
      )
    );
  }

  if (!isBoolean(modelInstance.collision.visible)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-model-instance-collision-visibility",
        "Model instance collision visibility must be a boolean.",
        `${path}.collision.visible`
      )
    );
  }

  if (!isBoolean(modelInstance.visible)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-model-instance-visible",
        "Model instance visible must be a boolean.",
        `${path}.visible`
      )
    );
  }

  if (!isBoolean(modelInstance.enabled)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-model-instance-enabled",
        "Model instance enabled must be a boolean.",
        `${path}.enabled`
      )
    );
  }

  const asset = document.assets[modelInstance.assetId];

  if (asset === undefined) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "missing-model-instance-asset",
        `Model instance asset ${modelInstance.assetId} does not exist.`,
        `${path}.assetId`
      )
    );
    return;
  }

  if (asset.kind !== "model") {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-model-instance-asset-kind",
        "Model instances may only reference model assets.",
        `${path}.assetId`
      )
    );
  }
}

function validateEntityName(
  name: string | undefined,
  path: string,
  diagnostics: SceneDiagnostic[]
) {
  if (name !== undefined && name.trim().length === 0) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-entity-name",
        "Entity names must be non-empty when authored.",
        `${path}.name`
      )
    );
  }
}

function validateScenePath(
  pathValue: ScenePath,
  path: string,
  diagnostics: SceneDiagnostic[]
) {
  if (!isBoolean(pathValue.visible)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-path-visible",
        "Path visible must remain a boolean.",
        `${path}.visible`
      )
    );
  }

  if (!isBoolean(pathValue.enabled)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-path-enabled",
        "Path enabled must remain a boolean.",
        `${path}.enabled`
      )
    );
  }

  if (pathValue.name !== undefined && pathValue.name.trim().length === 0) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-path-name",
        "Path names must be non-empty when authored.",
        `${path}.name`
      )
    );
  }

  if (!isBoolean(pathValue.loop)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-path-loop",
        "Path loop must remain a boolean.",
        `${path}.loop`
      )
    );
  }

  if (pathValue.points.length < MIN_SCENE_PATH_POINT_COUNT) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-path-point-count",
        `Paths must define at least ${MIN_SCENE_PATH_POINT_COUNT} points.`,
        `${path}.points`
      )
    );
  }

  const seenPointIds = new Set<string>();

  for (const [pointIndex, point] of pathValue.points.entries()) {
    const pointPath = `${path}.points.${pointIndex}`;

    if (point.id.trim().length === 0) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-path-point-id",
          "Path point ids must be non-empty strings.",
          `${pointPath}.id`
        )
      );
    } else if (seenPointIds.has(point.id)) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "duplicate-path-point-id",
          `Path point id ${point.id} is already used within this path.`,
          `${pointPath}.id`
        )
      );
    } else {
      seenPointIds.add(point.id);
    }

    if (!isFiniteVec3(point.position)) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-path-point-position",
          "Path point positions must remain finite on every axis.",
          `${pointPath}.position`
        )
      );
    }
  }
}

function validateTerrain(
  terrain: Terrain,
  path: string,
  document: SceneDocument,
  diagnostics: SceneDiagnostic[]
) {
  if (!isBoolean(terrain.visible)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-terrain-visible",
        "Terrain visible must remain a boolean.",
        `${path}.visible`
      )
    );
  }

  if (!isBoolean(terrain.enabled)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-terrain-enabled",
        "Terrain enabled must remain a boolean.",
        `${path}.enabled`
      )
    );
  }

  if (terrain.name !== undefined && terrain.name.trim().length === 0) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-terrain-name",
        "Terrain names must be non-empty when authored.",
        `${path}.name`
      )
    );
  }

  if (!isFiniteVec3(terrain.position)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-terrain-position",
        "Terrain positions must remain finite on every axis.",
        `${path}.position`
      )
    );
  }

  if (!isBoolean(terrain.collisionEnabled)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-terrain-collision-enabled",
        "Terrain collisionEnabled must remain a boolean.",
        `${path}.collisionEnabled`
      )
    );
  }

  if (
    !isPositiveInteger(terrain.sampleCountX) ||
    terrain.sampleCountX < MIN_TERRAIN_SAMPLE_COUNT
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-terrain-sample-count-x",
        `Terrain sampleCountX must be an integer greater than or equal to ${MIN_TERRAIN_SAMPLE_COUNT}.`,
        `${path}.sampleCountX`
      )
    );
  }

  if (
    !isPositiveInteger(terrain.sampleCountZ) ||
    terrain.sampleCountZ < MIN_TERRAIN_SAMPLE_COUNT
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-terrain-sample-count-z",
        `Terrain sampleCountZ must be an integer greater than or equal to ${MIN_TERRAIN_SAMPLE_COUNT}.`,
        `${path}.sampleCountZ`
      )
    );
  }

  if (!isPositiveFiniteNumber(terrain.cellSize)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-terrain-cell-size",
        "Terrain cellSize must be a positive finite number.",
        `${path}.cellSize`
      )
    );
  }

  if (terrain.heights.length !== terrain.sampleCountX * terrain.sampleCountZ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-terrain-height-count",
        "Terrain heights must contain exactly one sample per grid point.",
        `${path}.heights`
      )
    );
  }

  for (let index = 0; index < terrain.heights.length; index += 1) {
    if (isFiniteNumber(terrain.heights[index])) {
      continue;
    }

    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-terrain-height",
        "Terrain heights must remain finite.",
        `${path}.heights.${index}`
      )
    );
  }

  if (terrain.layers.length !== TERRAIN_LAYER_COUNT) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-terrain-layer-count",
        `Terrain layers must contain exactly ${TERRAIN_LAYER_COUNT} authored layer slots.`,
        `${path}.layers`
      )
    );
  }

  for (let index = 0; index < terrain.layers.length; index += 1) {
    const layer = terrain.layers[index];

    if (layer.materialId === null) {
      continue;
    }

    if (document.materials[layer.materialId] === undefined) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-terrain-layer-material",
          `Terrain layer material reference ${layer.materialId} does not exist in the document material registry.`,
          `${path}.layers.${index}.materialId`
        )
      );
    }
  }

  const expectedPaintWeightCount =
    terrain.sampleCountX * terrain.sampleCountZ * (TERRAIN_LAYER_COUNT - 1);

  if (terrain.paintWeights.length !== expectedPaintWeightCount) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-terrain-paint-weight-count",
        `Terrain paint weights must contain exactly ${expectedPaintWeightCount} values.`,
        `${path}.paintWeights`
      )
    );
  }

  for (let index = 0; index < terrain.paintWeights.length; index += 1) {
    const paintWeight = terrain.paintWeights[index];

    if (isFiniteNumber(paintWeight) && paintWeight >= 0 && paintWeight <= 1) {
      continue;
    }

    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-terrain-paint-weight",
        "Terrain paint weights must remain finite values between 0 and 1.",
        `${path}.paintWeights.${index}`
      )
    );
  }
}

function validateAuthoredEntityState(
  entity: EntityInstance,
  path: string,
  diagnostics: SceneDiagnostic[]
) {
  if (!isBoolean(entity.visible)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-entity-visible",
        "Entity visible must remain a boolean.",
        `${path}.visible`
      )
    );
  }

  if (!isBoolean(entity.enabled)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-entity-enabled",
        "Entity enabled must remain a boolean.",
        `${path}.enabled`
      )
    );
  }
}

function validatePlayerStartEntity(
  entity: PlayerStartEntity,
  path: string,
  diagnostics: SceneDiagnostic[]
) {
  validateAuthoredEntityState(entity, path, diagnostics);

  if (!isFiniteVec3(entity.position)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-position",
        "Player Start position must remain finite on every axis.",
        `${path}.position`
      )
    );
  }

  if (!isFiniteNumber(entity.yawDegrees)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-yaw",
        "Player Start yaw must remain a finite number.",
        `${path}.yawDegrees`
      )
    );
  }

  if (!isPlayerStartNavigationMode(entity.navigationMode)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-navigation-mode",
        "Player Start navigation mode must be firstPerson or thirdPerson.",
        `${path}.navigationMode`
      )
    );
  }

  if (
    !isFiniteNumber(entity.interactionReachMeters) ||
    entity.interactionReachMeters <= 0
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-interaction-reach",
        "Player Start interaction reach must remain a finite number greater than zero.",
        `${path}.interactionReachMeters`
      )
    );
  }

  if (
    !isFiniteNumber(entity.interactionAngleDegrees) ||
    entity.interactionAngleDegrees <= 0 ||
    entity.interactionAngleDegrees >= 180
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-interaction-angle",
        "Player Start interaction angle must remain a finite number greater than zero and less than 180.",
        `${path}.interactionAngleDegrees`
      )
    );
  }

  if (typeof entity.allowLookInputTargetSwitch !== "boolean") {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-look-input-target-switch",
        "Player Start allowLookInputTargetSwitch must remain a boolean.",
        `${path}.allowLookInputTargetSwitch`
      )
    );
  }

  if (typeof entity.targetButtonCyclesActiveTarget !== "boolean") {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-target-button-cycles-active-target",
        "Player Start targetButtonCyclesActiveTarget must remain a boolean.",
        `${path}.targetButtonCyclesActiveTarget`
      )
    );
  }

  if (!isPlayerStartMovementTemplateKind(entity.movementTemplate?.kind)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-movement-template-kind",
        "Player Start movement template must be a supported typed template.",
        `${path}.movementTemplate.kind`
      )
    );
  }

  if (
    !isFiniteNumber(entity.movementTemplate?.moveSpeed) ||
    (entity.movementTemplate?.moveSpeed ?? 0) <= 0
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-movement-speed",
        "Player Start movement template move speed must remain a finite number greater than zero.",
        `${path}.movementTemplate.moveSpeed`
      )
    );
  }

  if (!isNonNegativeFiniteNumber(entity.movementTemplate?.maxSpeed)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-max-speed",
        "Player Start max speed must remain a finite number zero or greater.",
        `${path}.movementTemplate.maxSpeed`
      )
    );
  }

  if (!isNonNegativeFiniteNumber(entity.movementTemplate?.maxStepHeight)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-max-step-height",
        "Player Start max step height must remain a finite number zero or greater.",
        `${path}.movementTemplate.maxStepHeight`
      )
    );
  }

  if (typeof entity.movementTemplate?.capabilities?.jump !== "boolean") {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-jump-capability",
        "Player Start movement template jump capability must be a boolean.",
        `${path}.movementTemplate.capabilities.jump`
      )
    );
  }

  if (typeof entity.movementTemplate?.capabilities?.sprint !== "boolean") {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-sprint-capability",
        "Player Start movement template sprint capability must be a boolean.",
        `${path}.movementTemplate.capabilities.sprint`
      )
    );
  }

  if (typeof entity.movementTemplate?.capabilities?.crouch !== "boolean") {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-crouch-capability",
        "Player Start movement template crouch capability must be a boolean.",
        `${path}.movementTemplate.capabilities.crouch`
      )
    );
  }

  if (
    !isFiniteNumber(entity.movementTemplate?.jump?.speed) ||
    (entity.movementTemplate?.jump?.speed ?? 0) <= 0
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-jump-speed",
        "Player Start jump speed must remain a finite number greater than zero.",
        `${path}.movementTemplate.jump.speed`
      )
    );
  }

  if (!isNonNegativeFiniteNumber(entity.movementTemplate?.jump?.bufferMs)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-jump-buffer-ms",
        "Player Start jump buffer must remain a finite number zero or greater.",
        `${path}.movementTemplate.jump.bufferMs`
      )
    );
  }

  if (!isNonNegativeFiniteNumber(entity.movementTemplate?.jump?.coyoteTimeMs)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-coyote-time-ms",
        "Player Start coyote time must remain a finite number zero or greater.",
        `${path}.movementTemplate.jump.coyoteTimeMs`
      )
    );
  }

  if (!isBoolean(entity.movementTemplate?.jump?.variableHeight)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-variable-jump-height",
        "Player Start variable jump height setting must be a boolean.",
        `${path}.movementTemplate.jump.variableHeight`
      )
    );
  }

  if (
    !isFiniteNumber(entity.movementTemplate?.jump?.maxHoldMs) ||
    (entity.movementTemplate?.jump?.maxHoldMs ?? 0) <= 0
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-variable-jump-max-hold-ms",
        "Player Start variable jump max hold must remain a finite number greater than zero.",
        `${path}.movementTemplate.jump.maxHoldMs`
      )
    );
  }

  if (!isBoolean(entity.movementTemplate?.jump?.moveWhileJumping)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-move-while-jumping",
        "Player Start move while jumping setting must be a boolean.",
        `${path}.movementTemplate.jump.moveWhileJumping`
      )
    );
  }

  if (!isBoolean(entity.movementTemplate?.jump?.moveWhileFalling)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-move-while-falling",
        "Player Start move while falling setting must be a boolean.",
        `${path}.movementTemplate.jump.moveWhileFalling`
      )
    );
  }

  if (!isBoolean(entity.movementTemplate?.jump?.directionOnly)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-air-direction-only",
        "Player Start air direction only setting must be a boolean.",
        `${path}.movementTemplate.jump.directionOnly`
      )
    );
  }

  if (!isBoolean(entity.movementTemplate?.jump?.bunnyHop)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-bunny-hop",
        "Player Start bunny hop setting must be a boolean.",
        `${path}.movementTemplate.jump.bunnyHop`
      )
    );
  }

  if (
    !isNonNegativeFiniteNumber(entity.movementTemplate?.jump?.bunnyHopBoost)
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-bunny-hop-boost",
        "Player Start bunny hop boost must remain a finite number zero or greater.",
        `${path}.movementTemplate.jump.bunnyHopBoost`
      )
    );
  }

  if (
    !isFiniteNumber(entity.movementTemplate?.sprint?.speedMultiplier) ||
    (entity.movementTemplate?.sprint?.speedMultiplier ?? 0) <= 0
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-sprint-speed-multiplier",
        "Player Start sprint speed multiplier must remain a finite number greater than zero.",
        `${path}.movementTemplate.sprint.speedMultiplier`
      )
    );
  }

  if (
    !isFiniteNumber(entity.movementTemplate?.crouch?.speedMultiplier) ||
    (entity.movementTemplate?.crouch?.speedMultiplier ?? 0) <= 0
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-crouch-speed-multiplier",
        "Player Start crouch speed multiplier must remain a finite number greater than zero.",
        `${path}.movementTemplate.crouch.speedMultiplier`
      )
    );
  }

  if (
    !isPlayerStartKeyboardBindingCode(
      entity.inputBindings?.keyboard.moveForward
    )
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-move-forward-keyboard-binding",
        "Player Start move-forward keyboard binding must be a supported key code.",
        `${path}.inputBindings.keyboard.moveForward`
      )
    );
  }

  if (
    !isPlayerStartKeyboardBindingCode(
      entity.inputBindings?.keyboard.moveBackward
    )
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-move-backward-keyboard-binding",
        "Player Start move-backward keyboard binding must be a supported key code.",
        `${path}.inputBindings.keyboard.moveBackward`
      )
    );
  }

  if (
    !isPlayerStartKeyboardBindingCode(entity.inputBindings?.keyboard.moveLeft)
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-move-left-keyboard-binding",
        "Player Start move-left keyboard binding must be a supported key code.",
        `${path}.inputBindings.keyboard.moveLeft`
      )
    );
  }

  if (
    !isPlayerStartKeyboardBindingCode(entity.inputBindings?.keyboard.moveRight)
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-move-right-keyboard-binding",
        "Player Start move-right keyboard binding must be a supported key code.",
        `${path}.inputBindings.keyboard.moveRight`
      )
    );
  }

  if (!isPlayerStartKeyboardBindingCode(entity.inputBindings?.keyboard.jump)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-jump-keyboard-binding",
        "Player Start jump keyboard binding must be a supported key code.",
        `${path}.inputBindings.keyboard.jump`
      )
    );
  }

  if (
    !isPlayerStartKeyboardBindingCode(entity.inputBindings?.keyboard.sprint)
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-sprint-keyboard-binding",
        "Player Start sprint keyboard binding must be a supported key code.",
        `${path}.inputBindings.keyboard.sprint`
      )
    );
  }

  if (
    !isPlayerStartKeyboardBindingCode(entity.inputBindings?.keyboard.crouch)
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-crouch-keyboard-binding",
        "Player Start crouch keyboard binding must be a supported key code.",
        `${path}.inputBindings.keyboard.crouch`
      )
    );
  }

  if (
    !isPlayerStartKeyboardBindingCode(entity.inputBindings?.keyboard.interact)
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-interact-keyboard-binding",
        "Player Start interact keyboard binding must be a supported key or mouse code.",
        `${path}.inputBindings.keyboard.interact`
      )
    );
  }

  if (
    !isPlayerStartKeyboardBindingCode(entity.inputBindings?.keyboard.interact)
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-interact-keyboard-binding",
        "Player Start interact keyboard binding must be a supported key code.",
        `${path}.inputBindings.keyboard.interact`
      )
    );
  }

  if (
    !isPlayerStartKeyboardBindingCode(
      entity.inputBindings?.keyboard.clearTarget
    )
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-clear-target-keyboard-binding",
        "Player Start clear-target keyboard binding must be a supported key code.",
        `${path}.inputBindings.keyboard.clearTarget`
      )
    );
  }

  if (
    !isPlayerStartKeyboardBindingCode(entity.inputBindings?.keyboard.pauseTime)
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-pause-keyboard-binding",
        "Player Start pause keyboard binding must be a supported key code.",
        `${path}.inputBindings.keyboard.pauseTime`
      )
    );
  }

  if (!isPlayerStartGamepadBinding(entity.inputBindings?.gamepad.moveForward)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-move-forward-gamepad-binding",
        "Player Start move-forward gamepad binding must be a supported standard-gamepad input.",
        `${path}.inputBindings.gamepad.moveForward`
      )
    );
  }

  if (
    !isPlayerStartGamepadBinding(entity.inputBindings?.gamepad.moveBackward)
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-move-backward-gamepad-binding",
        "Player Start move-backward gamepad binding must be a supported standard-gamepad input.",
        `${path}.inputBindings.gamepad.moveBackward`
      )
    );
  }

  if (!isPlayerStartGamepadBinding(entity.inputBindings?.gamepad.moveLeft)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-move-left-gamepad-binding",
        "Player Start move-left gamepad binding must be a supported standard-gamepad input.",
        `${path}.inputBindings.gamepad.moveLeft`
      )
    );
  }

  if (!isPlayerStartGamepadBinding(entity.inputBindings?.gamepad.moveRight)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-move-right-gamepad-binding",
        "Player Start move-right gamepad binding must be a supported standard-gamepad input.",
        `${path}.inputBindings.gamepad.moveRight`
      )
    );
  }

  if (!isPlayerStartGamepadActionBinding(entity.inputBindings?.gamepad.jump)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-jump-gamepad-binding",
        "Player Start jump gamepad binding must be a supported standard-gamepad action input.",
        `${path}.inputBindings.gamepad.jump`
      )
    );
  }

  if (
    !isPlayerStartGamepadActionBinding(entity.inputBindings?.gamepad.sprint)
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-sprint-gamepad-binding",
        "Player Start sprint gamepad binding must be a supported standard-gamepad action input.",
        `${path}.inputBindings.gamepad.sprint`
      )
    );
  }

  if (
    !isPlayerStartGamepadActionBinding(entity.inputBindings?.gamepad.crouch)
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-crouch-gamepad-binding",
        "Player Start crouch gamepad binding must be a supported standard-gamepad action input.",
        `${path}.inputBindings.gamepad.crouch`
      )
    );
  }

  if (
    !isPlayerStartGamepadActionBinding(entity.inputBindings?.gamepad.interact)
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-interact-gamepad-binding",
        "Player Start interact gamepad binding must be a supported standard-gamepad action input.",
        `${path}.inputBindings.gamepad.interact`
      )
    );
  }

  if (
    !isPlayerStartGamepadActionBinding(entity.inputBindings?.gamepad.interact)
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-interact-gamepad-binding",
        "Player Start interact gamepad binding must be a supported standard-gamepad action input.",
        `${path}.inputBindings.gamepad.interact`
      )
    );
  }

  if (
    !isPlayerStartGamepadActionBinding(
      entity.inputBindings?.gamepad.clearTarget
    )
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-clear-target-gamepad-binding",
        "Player Start clear-target gamepad binding must be a supported standard-gamepad action input.",
        `${path}.inputBindings.gamepad.clearTarget`
      )
    );
  }

  if (
    !isPlayerStartGamepadActionBinding(entity.inputBindings?.gamepad.pauseTime)
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-pause-gamepad-binding",
        "Player Start pause gamepad binding must be a supported standard-gamepad action input.",
        `${path}.inputBindings.gamepad.pauseTime`
      )
    );
  }

  if (
    !isPlayerStartGamepadCameraLookBinding(
      entity.inputBindings?.gamepad.cameraLook
    )
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-camera-look-gamepad-binding",
        "Player Start camera-look gamepad binding must be a supported standard-gamepad camera input.",
        `${path}.inputBindings.gamepad.cameraLook`
      )
    );
  }

  if (!isPlayerStartColliderMode(entity.collider.mode)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-collider-mode",
        "Player Start collider mode must be capsule, box, or none.",
        `${path}.collider.mode`
      )
    );
  }

  if (
    !isFiniteNumber(entity.collider.eyeHeight) ||
    entity.collider.eyeHeight <= 0
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-eye-height",
        "Player Start eye height must remain a finite number greater than zero.",
        `${path}.collider.eyeHeight`
      )
    );
  }

  if (
    !isFiniteNumber(entity.collider.capsuleRadius) ||
    entity.collider.capsuleRadius <= 0
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-capsule-radius",
        "Player Start capsule radius must remain a finite number greater than zero.",
        `${path}.collider.capsuleRadius`
      )
    );
  }

  if (
    !isFiniteNumber(entity.collider.capsuleHeight) ||
    entity.collider.capsuleHeight <= 0
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-capsule-height",
        "Player Start capsule height must remain a finite number greater than zero.",
        `${path}.collider.capsuleHeight`
      )
    );
  }

  if (
    !isFiniteVec3(entity.collider.boxSize) ||
    entity.collider.boxSize.x <= 0 ||
    entity.collider.boxSize.y <= 0 ||
    entity.collider.boxSize.z <= 0
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-box-size",
        "Player Start box size must remain finite and positive on every axis.",
        `${path}.collider.boxSize`
      )
    );
  }

  if (entity.collider.capsuleHeight < entity.collider.capsuleRadius * 2) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-capsule-proportions",
        "Player Start capsule height must be at least twice the capsule radius.",
        `${path}.collider.capsuleHeight`
      )
    );
  }

  const colliderHeight = getPlayerStartColliderHeight(entity.collider);

  if (colliderHeight !== null && entity.collider.eyeHeight > colliderHeight) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-player-start-eye-height",
        "Player Start eye height must fit within the authored collider height.",
        `${path}.collider.eyeHeight`
      )
    );
  }
}

function validateSoundEmitterAudioAsset(
  entity: SoundEmitterEntity,
  path: string,
  document: SceneDocument,
  diagnostics: SceneDiagnostic[],
  missingSeverity: SceneDiagnosticSeverity
): ProjectAssetRecord | null {
  if (entity.audioAssetId === null) {
    diagnostics.push(
      createDiagnostic(
        missingSeverity,
        "missing-sound-emitter-audio-asset",
        entity.autoplay
          ? "Sound Emitter autoplay requires an assigned audio asset."
          : "Sound Emitter has no audio asset assigned yet.",
        `${path}.audioAssetId`
      )
    );
    return null;
  }

  const asset = document.assets[entity.audioAssetId];

  if (asset === undefined) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "missing-sound-emitter-audio-asset",
        `Sound Emitter audio asset ${entity.audioAssetId} does not exist.`,
        `${path}.audioAssetId`
      )
    );
    return null;
  }

  if (asset.kind !== "audio") {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-sound-emitter-audio-asset-kind",
        "Sound Emitter audioAssetId must reference an audio asset.",
        `${path}.audioAssetId`
      )
    );
    return null;
  }

  return asset;
}

function validateSoundEmitterEntity(
  entity: SoundEmitterEntity,
  path: string,
  document: SceneDocument,
  diagnostics: SceneDiagnostic[]
) {
  validateAuthoredEntityState(entity, path, diagnostics);

  if (!isFiniteVec3(entity.position)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-sound-emitter-position",
        "Sound Emitter position must remain finite on every axis.",
        `${path}.position`
      )
    );
  }

  if (!isNonNegativeFiniteNumber(entity.volume)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-sound-emitter-volume",
        "Sound Emitter volume must remain a finite number zero or greater.",
        `${path}.volume`
      )
    );
  }

  if (!isPositiveFiniteNumber(entity.refDistance)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-sound-emitter-ref-distance",
        "Sound Emitter ref distance must remain a finite number greater than zero.",
        `${path}.refDistance`
      )
    );
  }

  if (!isPositiveFiniteNumber(entity.maxDistance)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-sound-emitter-max-distance",
        "Sound Emitter max distance must remain a finite number greater than zero.",
        `${path}.maxDistance`
      )
    );
  }

  if (
    isPositiveFiniteNumber(entity.refDistance) &&
    isPositiveFiniteNumber(entity.maxDistance) &&
    entity.maxDistance < entity.refDistance
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-sound-emitter-distance-range",
        "Sound Emitter max distance must be greater than or equal to ref distance.",
        `${path}.maxDistance`
      )
    );
  }

  if (!isBoolean(entity.autoplay)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-sound-emitter-autoplay-flag",
        "Sound Emitter autoplay must remain a boolean.",
        `${path}.autoplay`
      )
    );
  }

  if (!isBoolean(entity.loop)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-sound-emitter-loop-flag",
        "Sound Emitter loop must remain a boolean.",
        `${path}.loop`
      )
    );
  }

  validateSoundEmitterAudioAsset(
    entity,
    path,
    document,
    diagnostics,
    entity.autoplay === true ? "error" : "warning"
  );
}

function validateCharacterColliderSettings(
  collider: CharacterColliderSettings,
  path: string,
  diagnostics: SceneDiagnostic[],
  options: {
    codePrefix: string;
    label: string;
    getHeight: (collider: CharacterColliderSettings) => number | null;
  }
) {
  if (!isPlayerStartColliderMode(collider.mode)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        `invalid-${options.codePrefix}-collider-mode`,
        `${options.label} collider mode must be capsule, box, or none.`,
        `${path}.collider.mode`
      )
    );
  }

  if (!isPositiveFiniteNumber(collider.eyeHeight)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        `invalid-${options.codePrefix}-eye-height`,
        `${options.label} eye height must remain finite and greater than zero.`,
        `${path}.collider.eyeHeight`
      )
    );
  }

  if (!isPositiveFiniteNumber(collider.capsuleRadius)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        `invalid-${options.codePrefix}-capsule-radius`,
        `${options.label} capsule radius must remain finite and greater than zero.`,
        `${path}.collider.capsuleRadius`
      )
    );
  }

  if (!isPositiveFiniteNumber(collider.capsuleHeight)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        `invalid-${options.codePrefix}-capsule-height`,
        `${options.label} capsule height must remain finite and greater than zero.`,
        `${path}.collider.capsuleHeight`
      )
    );
  }

  if (
    !isFiniteVec3(collider.boxSize) ||
    collider.boxSize.x <= 0 ||
    collider.boxSize.y <= 0 ||
    collider.boxSize.z <= 0
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        `invalid-${options.codePrefix}-box-size`,
        `${options.label} box size must remain finite and positive on every axis.`,
        `${path}.collider.boxSize`
      )
    );
  }

  if (collider.capsuleHeight < collider.capsuleRadius * 2) {
    diagnostics.push(
      createDiagnostic(
        "error",
        `invalid-${options.codePrefix}-capsule-proportions`,
        `${options.label} capsule height must be at least twice the capsule radius.`,
        `${path}.collider.capsuleHeight`
      )
    );
  }

  const colliderHeight = options.getHeight(collider);

  if (colliderHeight !== null && collider.eyeHeight > colliderHeight) {
    diagnostics.push(
      createDiagnostic(
        "error",
        `invalid-${options.codePrefix}-eye-height`,
        `${options.label} eye height must fit within the authored collider height.`,
        `${path}.collider.eyeHeight`
      )
    );
  }
}

function validateTriggerVolumeEntity(
  entity: TriggerVolumeEntity,
  path: string,
  diagnostics: SceneDiagnostic[]
) {
  validateAuthoredEntityState(entity, path, diagnostics);

  if (!isFiniteVec3(entity.position)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-trigger-volume-position",
        "Trigger Volume position must remain finite on every axis.",
        `${path}.position`
      )
    );
  }

  if (!hasPositiveFiniteVec3(entity.size)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-trigger-volume-size",
        "Trigger Volume size must remain finite and positive on every axis.",
        `${path}.size`
      )
    );
  }

  if (!isBoolean(entity.triggerOnEnter)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-trigger-volume-enter-flag",
        "Trigger Volume triggerOnEnter must remain a boolean.",
        `${path}.triggerOnEnter`
      )
    );
  }

  if (!isBoolean(entity.triggerOnExit)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-trigger-volume-exit-flag",
        "Trigger Volume triggerOnExit must remain a boolean.",
        `${path}.triggerOnExit`
      )
    );
  }
}

function validateTeleportTargetEntity(
  entity: TeleportTargetEntity,
  path: string,
  diagnostics: SceneDiagnostic[]
) {
  validateAuthoredEntityState(entity, path, diagnostics);

  if (!isFiniteVec3(entity.position)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-teleport-target-position",
        "Teleport Target position must remain finite on every axis.",
        `${path}.position`
      )
    );
  }

  if (!isFiniteNumber(entity.yawDegrees)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-teleport-target-yaw",
        "Teleport Target yaw must remain a finite number.",
        `${path}.yawDegrees`
      )
    );
  }
}

function validateInteractableEntity(
  entity: InteractableEntity,
  path: string,
  diagnostics: SceneDiagnostic[]
) {
  validateAuthoredEntityState(entity, path, diagnostics);

  if (!isFiniteVec3(entity.position)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-interactable-position",
        "Interactable position must remain finite on every axis.",
        `${path}.position`
      )
    );
  }

  if (!isPositiveFiniteNumber(entity.radius)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-interactable-radius",
        "Interactable radius must remain finite and greater than zero.",
        `${path}.radius`
      )
    );
  }

  if (typeof entity.prompt !== "string" || entity.prompt.trim().length === 0) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-interactable-prompt",
        "Interactable prompt must remain a non-empty string.",
        `${path}.prompt`
      )
    );
  }

  if (!isBoolean(entity.interactionEnabled)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-interactable-interaction-enabled",
        "Interactable interactionEnabled must remain a boolean.",
        `${path}.interactionEnabled`
      )
    );
  }
}

function validateSceneEntryEntity(
  entity: SceneEntryEntity,
  path: string,
  diagnostics: SceneDiagnostic[]
) {
  validateAuthoredEntityState(entity, path, diagnostics);

  if (!isFiniteVec3(entity.position)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-scene-entry-position",
        "Scene Entry position must remain finite on every axis.",
        `${path}.position`
      )
    );
  }

  if (!isFiniteNumber(entity.yawDegrees)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-scene-entry-yaw",
        "Scene Entry yaw must remain a finite number.",
        `${path}.yawDegrees`
      )
    );
  }
}

function validateNpcModelAssetId(
  entity: NpcEntity,
  path: string,
  document: SceneDocument,
  diagnostics: SceneDiagnostic[]
) {
  if (entity.modelAssetId === null) {
    return;
  }

  if (
    typeof entity.modelAssetId !== "string" ||
    entity.modelAssetId.trim().length === 0
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-npc-model-asset-id",
        "NPC modelAssetId must be null or reference a non-empty model asset id.",
        `${path}.modelAssetId`
      )
    );
    return;
  }

  const asset = document.assets[entity.modelAssetId];

  if (asset === undefined) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "missing-npc-model-asset",
        `NPC model asset ${entity.modelAssetId} does not exist.`,
        `${path}.modelAssetId`
      )
    );
    return;
  }

  if (asset.kind !== "model") {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-npc-model-asset-kind",
        "NPC modelAssetId must reference a model asset.",
        `${path}.modelAssetId`
      )
    );
  }
}

function validateNpcPresence(
  presence: NpcPresence | undefined,
  path: string,
  diagnostics: SceneDiagnostic[]
) {
  if (
    presence === undefined ||
    typeof presence !== "object" ||
    presence === null ||
    !("mode" in presence)
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "missing-npc-presence",
        "NPC presence must remain explicitly authored.",
        path
      )
    );
    return;
  }

  if (!isNpcPresenceMode(presence.mode)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-npc-presence-mode",
        "NPC presence mode must be always or timeWindow.",
        `${path}.mode`
      )
    );
    return;
  }

  if (presence.mode !== "timeWindow") {
    return;
  }

  if (!isFiniteNumber(presence.startHour)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-npc-presence-start-hour",
        "NPC presence window start hour must be a finite number.",
        `${path}.startHour`
      )
    );
  } else if (presence.startHour < 0 || presence.startHour >= HOURS_PER_DAY) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-npc-presence-start-range",
        "NPC presence window start hour must stay within the 0..24 hour range.",
        `${path}.startHour`
      )
    );
  }

  if (!isFiniteNumber(presence.endHour)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-npc-presence-end-hour",
        "NPC presence window end hour must be a finite number.",
        `${path}.endHour`
      )
    );
  } else if (presence.endHour < 0 || presence.endHour >= HOURS_PER_DAY) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-npc-presence-end-range",
        "NPC presence window end hour must stay within the 0..24 hour range.",
        `${path}.endHour`
      )
    );
  }

  if (
    isFiniteNumber(presence.startHour) &&
    isFiniteNumber(presence.endHour) &&
    presence.startHour === presence.endHour
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-npc-presence-zero-window",
        "NPC presence time windows must span at least part of the day.",
        `${path}.startHour`
      )
    );
  }
}

function validateNpcEntity(
  entity: NpcEntity,
  path: string,
  document: SceneDocument,
  diagnostics: SceneDiagnostic[]
) {
  validateAuthoredEntityState(entity, path, diagnostics);

  if (!isFiniteVec3(entity.position)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-npc-position",
        "NPC position must remain finite on every axis.",
        `${path}.position`
      )
    );
  }

  if (!isFiniteNumber(entity.yawDegrees)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-npc-yaw",
        "NPC yaw must remain a finite number.",
        `${path}.yawDegrees`
      )
    );
  }

  if (
    typeof entity.actorId !== "string" ||
    entity.actorId.trim().length === 0
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-npc-actor-id",
        "NPC actorId must remain a non-empty string.",
        `${path}.actorId`
      )
    );
  }

  validateNpcPresence(entity.presence, `${path}.presence`, diagnostics);
  validateNpcModelAssetId(entity, path, document, diagnostics);
  const seenNpcDialogueIds = new Map<string, string>();

  for (const [dialogueIndex, dialogue] of entity.dialogues.entries()) {
    const dialoguePath = `${path}.dialogues.${dialogueIndex}`;
    registerAuthoredId(
      dialogue.id,
      dialoguePath,
      seenNpcDialogueIds,
      diagnostics
    );
    validateProjectDialogue(
      dialogue,
      dialoguePath,
      seenNpcDialogueIds,
      diagnostics
    );
  }

  if (
    entity.defaultDialogueId !== null &&
    !entity.dialogues.some(
      (dialogue) => dialogue.id === entity.defaultDialogueId
    )
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "missing-npc-default-dialogue",
        `NPC default dialogue ${entity.defaultDialogueId} does not exist on this NPC.`,
        `${path}.defaultDialogueId`
      )
    );
  }
  validateCharacterColliderSettings(entity.collider, path, diagnostics, {
    codePrefix: "npc",
    label: "NPC",
    getHeight: getNpcColliderHeight
  });
}

function validateLightControlTarget(
  target: LightControlTargetRef,
  path: string,
  document: SceneDocument,
  diagnostics: SceneDiagnostic[]
) {
  const targetEntity = document.entities[target.entityId];

  if (targetEntity === undefined) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "missing-control-light-entity",
        `Light control target entity ${target.entityId} does not exist.`,
        `${path}.entityId`
      )
    );
    return;
  }

  if (
    targetEntity.kind !== target.entityKind ||
    (targetEntity.kind !== "pointLight" && targetEntity.kind !== "spotLight")
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-control-light-target-kind",
        "Light control effects must target a Point Light or Spot Light entity of the authored target kind.",
        `${path}.entityKind`
      )
    );
  }
}

function validateCameraRigControlTarget(
  target: CameraRigControlTargetRef,
  path: string,
  document: SceneDocument,
  diagnostics: SceneDiagnostic[]
) {
  const targetEntity = document.entities[target.entityId];

  if (targetEntity === undefined) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "missing-control-camera-rig-entity",
        `Camera control target entity ${target.entityId} does not exist.`,
        `${path}.entityId`
      )
    );
    return;
  }

  if (
    targetEntity.kind !== target.entityKind ||
    targetEntity.kind !== "cameraRig"
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-control-camera-rig-target-kind",
        "Camera control effects must target a Camera Rig entity of the authored target kind.",
        `${path}.entityKind`
      )
    );
  }
}

function validateActorControlTarget(
  target: ActorControlTargetRef,
  path: string,
  document: SceneDocument,
  diagnostics: SceneDiagnostic[]
) {
  const matchingActor = Object.values(document.entities).find(
    (entity) => entity.kind === "npc" && entity.actorId === target.actorId
  );

  if (matchingActor !== undefined) {
    return;
  }

  diagnostics.push(
    createDiagnostic(
      "error",
      "missing-control-actor-target",
      `Actor control target ${target.actorId} does not exist in this document.`,
      `${path}.actorId`
    )
  );
}

function validateInteractionControlTarget(
  target: InteractionControlTargetRef,
  path: string,
  document: SceneDocument,
  diagnostics: SceneDiagnostic[]
) {
  const targetEntity = document.entities[target.entityId];

  if (targetEntity === undefined) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "missing-control-interaction-entity",
        `Interaction control target entity ${target.entityId} does not exist.`,
        `${path}.entityId`
      )
    );
    return;
  }

  if (
    targetEntity.kind !== target.interactionKind ||
    targetEntity.kind !== "interactable"
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-control-interaction-target-kind",
        "Interaction control effects must target an Interactable entity of the authored target kind.",
        `${path}.interactionKind`
      )
    );
  }
}

function validateModelInstanceControlTarget(
  target: ModelInstanceControlTargetRef,
  path: string,
  document: SceneDocument,
  diagnostics: SceneDiagnostic[]
) {
  if (document.modelInstances[target.modelInstanceId] !== undefined) {
    return;
  }

  diagnostics.push(
    createDiagnostic(
      "error",
      "missing-control-model-instance-target",
      `Control model instance target ${target.modelInstanceId} does not exist.`,
      `${path}.modelInstanceId`
    )
  );
}

function validateSoundEmitterControlTarget(
  target: SoundEmitterControlTargetRef,
  path: string,
  document: SceneDocument,
  diagnostics: SceneDiagnostic[],
  options: { requireAudioAsset: boolean }
) {
  const targetEntity = document.entities[target.entityId];

  if (targetEntity === undefined) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "missing-control-sound-emitter-entity",
        `Control sound emitter entity ${target.entityId} does not exist.`,
        `${path}.entityId`
      )
    );
    return;
  }

  if (
    targetEntity.kind !== target.entityKind ||
    targetEntity.kind !== "soundEmitter"
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-control-sound-emitter-kind",
        "Control sound effects must target a Sound Emitter entity.",
        `${path}.entityKind`
      )
    );
    return;
  }

  if (options.requireAudioAsset && targetEntity.audioAssetId === null) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "missing-control-sound-emitter-audio-asset",
        "Control sound playback effects require a Sound Emitter that references an audio asset.",
        `${path}.entityId`
      )
    );
  }
}

function validateSceneControlTarget(
  target: SceneControlTargetRef,
  path: string,
  diagnostics: SceneDiagnostic[]
) {
  if (target.kind === "scene" && target.scope === "activeScene") {
    return;
  }

  diagnostics.push(
    createDiagnostic(
      "error",
      "invalid-control-scene-target",
      "Scene control effects must target the active scene scope.",
      `${path}.scope`
    )
  );
}

function validateControlEffect(
  effect: ControlEffect,
  path: string,
  document: SceneDocument,
  diagnostics: SceneDiagnostic[]
) {
  switch (effect.type) {
    case "setActorPresence":
      validateActorControlTarget(
        effect.target,
        `${path}.target`,
        document,
        diagnostics
      );
      if (!isBoolean(effect.active)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-actor-active",
            "Actor presence control values must remain boolean.",
            `${path}.active`
          )
        );
      }
      return;
    case "activateCameraRigOverride":
    case "clearCameraRigOverride":
      validateCameraRigControlTarget(
        effect.target,
        `${path}.target`,
        document,
        diagnostics
      );
      return;
    case "playActorAnimation":
    case "followActorPath":
      diagnostics.push(
        createDiagnostic(
          "error",
          "unsupported-scene-control-actor-routine-effect",
          "Actor animation and actor path routine effects are scheduler-owned in this slice and are not supported on scene interaction control actions.",
          `${path}.type`
        )
      );
      return;
    case "playModelAnimation": {
      const targetModelInstance =
        document.modelInstances[effect.target.modelInstanceId];

      if (targetModelInstance === undefined) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "missing-control-play-animation-target-instance",
            `Control play animation target model instance ${effect.target.modelInstanceId} does not exist.`,
            `${path}.target.modelInstanceId`
          )
        );
        return;
      }

      if (effect.clipName.trim().length === 0) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-play-animation-clip-name",
            "Control play animation clip name must be non-empty.",
            `${path}.clipName`
          )
        );
        return;
      }

      const targetAsset = document.assets[targetModelInstance.assetId];

      if (targetAsset === undefined || targetAsset.kind !== "model") {
        return;
      }

      if (!targetAsset.metadata.animationNames.includes(effect.clipName)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "missing-control-play-animation-clip",
            `Control play animation clip ${effect.clipName} does not exist on model asset ${targetAsset.id}.`,
            `${path}.clipName`
          )
        );
      }
      return;
    }
    case "stopModelAnimation":
      validateModelInstanceControlTarget(
        effect.target,
        `${path}.target`,
        document,
        diagnostics
      );
      return;
    case "setModelInstanceVisible":
      validateModelInstanceControlTarget(
        effect.target,
        `${path}.target`,
        document,
        diagnostics
      );
      if (!isBoolean(effect.visible)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-model-instance-visible",
            "Model visibility control values must remain boolean.",
            `${path}.visible`
          )
        );
      }
      return;
    case "playSound":
    case "stopSound":
      validateSoundEmitterControlTarget(
        effect.target,
        `${path}.target`,
        document,
        diagnostics,
        { requireAudioAsset: true }
      );
      return;
    case "setSoundVolume":
      validateSoundEmitterControlTarget(
        effect.target,
        `${path}.target`,
        document,
        diagnostics,
        { requireAudioAsset: false }
      );
      if (!isNonNegativeFiniteNumber(effect.volume)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-sound-volume",
            "Sound control volume must remain finite and zero or greater.",
            `${path}.volume`
          )
        );
      }
      return;
    case "setInteractionEnabled":
      validateInteractionControlTarget(
        effect.target,
        `${path}.target`,
        document,
        diagnostics
      );
      if (!isBoolean(effect.enabled)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-interaction-enabled",
            "Interaction control enabled must remain a boolean.",
            `${path}.enabled`
          )
        );
      }
      return;
    case "setLightEnabled":
      validateLightControlTarget(
        effect.target,
        `${path}.target`,
        document,
        diagnostics
      );
      if (!isBoolean(effect.enabled)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-light-enabled",
            "Light control enabled must remain a boolean.",
            `${path}.enabled`
          )
        );
      }
      return;
    case "setLightIntensity":
      validateLightControlTarget(
        effect.target,
        `${path}.target`,
        document,
        diagnostics
      );
      if (!isNonNegativeFiniteNumber(effect.intensity)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-light-intensity",
            "Light control intensity must remain finite and zero or greater.",
            `${path}.intensity`
          )
        );
      }
      return;
    case "setLightColor":
      validateLightControlTarget(
        effect.target,
        `${path}.target`,
        document,
        diagnostics
      );
      if (!isHexColorString(effect.colorHex)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-light-color",
            "Light control color must remain a valid hex color string.",
            `${path}.colorHex`
          )
        );
      }
      return;
    case "setAmbientLightIntensity":
      validateSceneControlTarget(effect.target, `${path}.target`, diagnostics);
      if (!isNonNegativeFiniteNumber(effect.intensity)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-ambient-light-intensity",
            "Ambient light control intensity must remain finite and zero or greater.",
            `${path}.intensity`
          )
        );
      }
      return;
    case "setAmbientLightColor":
      validateSceneControlTarget(effect.target, `${path}.target`, diagnostics);
      if (!isHexColorString(effect.colorHex)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-ambient-light-color",
            "Ambient light control color must remain a valid hex color string.",
            `${path}.colorHex`
          )
        );
      }
      return;
    case "setSunLightIntensity":
      validateSceneControlTarget(effect.target, `${path}.target`, diagnostics);
      if (!isNonNegativeFiniteNumber(effect.intensity)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-sun-light-intensity",
            "Sun light control intensity must remain finite and zero or greater.",
            `${path}.intensity`
          )
        );
      }
      return;
    case "setSunLightColor":
      validateSceneControlTarget(effect.target, `${path}.target`, diagnostics);
      if (!isHexColorString(effect.colorHex)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-sun-light-color",
            "Sun light control color must remain a valid hex color string.",
            `${path}.colorHex`
          )
        );
      }
      return;
  }
}

function validateInteractionLink(
  link: InteractionLink,
  path: string,
  document: SceneDocument,
  diagnostics: SceneDiagnostic[]
) {
  const sourceEntity = document.entities[link.sourceEntityId];

  if (sourceEntity === undefined) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "missing-interaction-source-entity",
        `Interaction source entity ${link.sourceEntityId} does not exist.`,
        `${path}.sourceEntityId`
      )
    );
    return;
  }

  if (
    sourceEntity.kind !== "triggerVolume" &&
    sourceEntity.kind !== "interactable" &&
    sourceEntity.kind !== "npc"
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-interaction-source-kind",
        "Interaction links may only source from Trigger Volume, Interactable, or NPC entities in the current slice.",
        `${path}.sourceEntityId`
      )
    );
  }

  if (sourceEntity.kind === "triggerVolume") {
    if (link.trigger !== "enter" && link.trigger !== "exit") {
      diagnostics.push(
        createDiagnostic(
          "error",
          "unsupported-interaction-trigger",
          "Trigger Volume links may only use enter or exit triggers.",
          `${path}.trigger`
        )
      );
    }
  } else if (sourceEntity.kind === "interactable") {
    if (link.trigger !== "click") {
      diagnostics.push(
        createDiagnostic(
          "error",
          "unsupported-interaction-trigger",
          "Interactable links may only use the click trigger.",
          `${path}.trigger`
        )
      );
    }
  } else if (sourceEntity.kind === "npc") {
    if (link.trigger !== "click") {
      diagnostics.push(
        createDiagnostic(
          "error",
          "unsupported-interaction-trigger",
          "NPC links may only use the click trigger.",
          `${path}.trigger`
        )
      );
    }
  }

  switch (link.action.type) {
    case "teleportPlayer": {
      const targetEntity = document.entities[link.action.targetEntityId];

      if (targetEntity === undefined) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "missing-teleport-target-entity",
            `Teleport target entity ${link.action.targetEntityId} does not exist.`,
            `${path}.action.targetEntityId`
          )
        );
        return;
      }

      if (targetEntity.kind !== "teleportTarget") {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-teleport-target-kind",
            "Teleport player actions must target a Teleport Target entity.",
            `${path}.action.targetEntityId`
          )
        );
      }
      break;
    }
    case "toggleVisibility":
      if (document.brushes[link.action.targetBrushId] === undefined) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "missing-visibility-target-brush",
            `Visibility target brush ${link.action.targetBrushId} does not exist.`,
            `${path}.action.targetBrushId`
          )
        );
      }

      if (
        link.action.visible !== undefined &&
        typeof link.action.visible !== "boolean"
      ) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-visibility-action-visible",
            "Visibility actions must use a boolean visible value when authored.",
            `${path}.action.visible`
          )
        );
      }
      break;
    case "playAnimation": {
      const targetModelInstance =
        document.modelInstances[link.action.targetModelInstanceId];

      if (targetModelInstance === undefined) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "missing-play-animation-target-instance",
            `Play animation target model instance ${link.action.targetModelInstanceId} does not exist.`,
            `${path}.action.targetModelInstanceId`
          )
        );
        return;
      }

      if (link.action.clipName.trim().length === 0) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-play-animation-clip-name",
            "Play animation clip name must be non-empty.",
            `${path}.action.clipName`
          )
        );
        return;
      }

      const targetAsset = document.assets[targetModelInstance.assetId];

      if (targetAsset === undefined || targetAsset.kind !== "model") {
        return;
      }

      if (!targetAsset.metadata.animationNames.includes(link.action.clipName)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "missing-play-animation-clip",
            `Play animation clip ${link.action.clipName} does not exist on model asset ${targetAsset.id}.`,
            `${path}.action.clipName`
          )
        );
      }

      break;
    }
    case "stopAnimation":
      // Validate that the target model instance exists in the document
      if (
        document.modelInstances[link.action.targetModelInstanceId] === undefined
      ) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "missing-stop-animation-target-instance",
            `Stop animation target model instance ${link.action.targetModelInstanceId} does not exist.`,
            `${path}.action.targetModelInstanceId`
          )
        );
      }
      break;
    case "playSound":
    case "stopSound": {
      const targetEntity = document.entities[link.action.targetSoundEmitterId];

      if (targetEntity === undefined) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "missing-sound-emitter-entity",
            `Sound emitter entity ${link.action.targetSoundEmitterId} does not exist.`,
            `${path}.action.targetSoundEmitterId`
          )
        );
        break;
      }

      if (targetEntity.kind !== "soundEmitter") {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-sound-emitter-kind",
            "Sound playback actions must target a Sound Emitter entity.",
            `${path}.action.targetSoundEmitterId`
          )
        );
        break;
      }

      if (targetEntity.audioAssetId === null) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "missing-sound-emitter-audio-asset",
            "Sound playback actions require a Sound Emitter that references an audio asset.",
            `${path}.action.targetSoundEmitterId`
          )
        );
      }

      break;
    }
    case "runSequence": {
      const sequence =
        document.sequences.sequences[link.action.sequenceId] ?? null;

      if (sequence === null) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "missing-sequence-resource",
            `Sequence ${link.action.sequenceId} does not exist in the project sequence library.`,
            `${path}.action.sequenceId`
          )
        );
        break;
      }

      if (getProjectSequenceImpulseSteps(sequence).length === 0) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-link-sequence-no-impulse-steps",
            "Interaction link sequences must include at least one start effect.",
            `${path}.action.sequenceId`
          )
        );
      }
      break;
    }
    case "control":
      validateControlEffect(
        link.action.effect,
        `${path}.action.effect`,
        document,
        diagnostics
      );
      break;
  }
}

function validateProjectScheduler(
  scheduler: ProjectScheduler,
  sequences: ProjectSequenceLibrary,
  context: ProjectSchedulerValidationContext,
  diagnostics: SceneDiagnostic[]
) {
  for (const [routineKey, routine] of Object.entries(scheduler.routines)) {
    const path = `scheduler.routines.${routineKey}`;
    const resolvedHeldSteps = getProjectScheduleRoutineHeldSteps(
      routine,
      sequences
    );
    const resolvedEffects = getHeldSequenceControlEffects(resolvedHeldSteps);

    if (routine.id !== routineKey) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "project-schedule-routine-id-mismatch",
          "Project schedule routine ids must match their registry key.",
          `${path}.id`
        )
      );
    }

    if (routine.title.trim().length === 0) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-project-schedule-routine-title",
          "Project schedule routine titles must be non-empty.",
          `${path}.title`
        )
      );
    }

    if (!isBoolean(routine.enabled)) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-project-schedule-routine-enabled",
          "Project schedule routines must remain explicitly enabled or disabled.",
          `${path}.enabled`
        )
      );
    }

    validateProjectSchedulerControlTarget(
      routine.target,
      `${path}.target`,
      context,
      diagnostics
    );

    if (
      routine.sequenceId !== null &&
      sequences.sequences[routine.sequenceId] === undefined
    ) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "missing-routine-sequence-resource",
          `Sequence ${routine.sequenceId} does not exist in the project sequence library.`,
          `${path}.sequenceId`
        )
      );
    }

    switch (routine.days.mode) {
      case "everyDay":
        break;
      case "selectedDays":
        if (routine.days.days.length === 0) {
          diagnostics.push(
            createDiagnostic(
              "error",
              "invalid-project-schedule-routine-days-empty",
              "Selected-day routines must include at least one weekday.",
              `${path}.days.days`
            )
          );
        }

        for (const [dayIndex, day] of routine.days.days.entries()) {
          if (!isProjectScheduleWeekday(day)) {
            diagnostics.push(
              createDiagnostic(
                "error",
                "invalid-project-schedule-routine-day",
                "Project schedule days must use supported weekday ids.",
                `${path}.days.days.${dayIndex}`
              )
            );
          }
        }
        break;
      default:
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-project-schedule-routine-days-mode",
            "Project schedule day selection must use everyDay or selectedDays.",
            `${path}.days.mode`
          )
        );
        break;
    }

    if (!isFiniteNumber(routine.startHour)) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-project-schedule-start-hour",
          "Project schedule start hours must be finite numbers.",
          `${path}.startHour`
        )
      );
    } else if (routine.startHour < 0 || routine.startHour >= HOURS_PER_DAY) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-project-schedule-start-range",
          "Project schedule start hours must stay within the 0..24 hour range.",
          `${path}.startHour`
        )
      );
    }

    if (!isFiniteNumber(routine.endHour)) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-project-schedule-end-hour",
          "Project schedule end hours must be finite numbers.",
          `${path}.endHour`
        )
      );
    } else if (routine.endHour < 0 || routine.endHour >= HOURS_PER_DAY) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-project-schedule-end-range",
          "Project schedule end hours must stay within the 0..24 hour range.",
          `${path}.endHour`
        )
      );
    }

    if (
      isFiniteNumber(routine.startHour) &&
      isFiniteNumber(routine.endHour) &&
      routine.startHour === routine.endHour
    ) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-project-schedule-zero-window",
          "Project schedule routines must span at least part of the day.",
          `${path}.startHour`
        )
      );
    }

    if (
      !isFiniteNumber(routine.priority) ||
      !Number.isInteger(routine.priority)
    ) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-project-schedule-priority",
          "Project schedule priorities must remain finite integers.",
          `${path}.priority`
        )
      );
    }

    const resolvedImpulseEffects =
      routine.sequenceId === null
        ? []
        : getProjectSequenceImpulseSteps(
            sequences.sequences[routine.sequenceId] ?? {
              id: "",
              title: "",
              effects: []
            }
          );

    if (resolvedEffects.length === 0) {
      if (
        routine.target.kind === "global" &&
        resolvedImpulseEffects.length > 0
      ) {
        continue;
      }

      if (routine.target.kind === "actor") {
        continue;
      }

      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-project-schedule-routine-effects-empty",
          "Project sequencer placements must resolve at least one timeline control effect unless they only use start effects.",
          routine.sequenceId === null ? `${path}.effects` : `${path}.sequenceId`
        )
      );
      continue;
    }

    if (routine.target.kind !== "actor" && resolvedEffects.length !== 1) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-project-schedule-non-actor-effect-count",
          "Non-actor sequencer placements must currently resolve exactly one timeline control effect.",
          routine.sequenceId === null ? `${path}.effects` : `${path}.sequenceId`
        )
      );
    }

    const seenResolutionKeys = new Set<string>();

    for (const [effectIndex, effect] of resolvedEffects.entries()) {
      const effectPath =
        routine.sequenceId === null
          ? `${path}.effects.${effectIndex}`
          : `${path}.sequenceId`;

      if (
        getControlTargetRefKey(effect.target) !==
        getControlTargetRefKey(routine.target)
      ) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "project-schedule-effect-target-mismatch",
            "Project schedule effect targets must match the authored routine target.",
            `${effectPath}.target`
          )
        );
      }

      const resolutionKey = getControlEffectResolutionKey(effect);

      if (seenResolutionKeys.has(resolutionKey)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-project-schedule-duplicate-effect",
            "Project schedule routines cannot author duplicate effects for the same resolved control slot.",
            effectPath
          )
        );
      } else {
        seenResolutionKeys.add(resolutionKey);
      }

      if (routine.sequenceId === null) {
        validateProjectSchedulerEffect(
          effect,
          effectPath,
          context,
          diagnostics
        );
      }
    }
  }
}

interface ProjectSchedulerValidationContext {
  actorIds: Set<string>;
  actorUsagesById: Map<string, ProjectSchedulerActorValidationUsage[]>;
  brushCounts: Map<string, number>;
  entityCounts: Map<string, number>;
  entityKindsById: Map<string, Set<EntityInstance["kind"]>>;
  modelInstanceCounts: Map<string, number>;
  modelAnimationNamesById: Map<string, string[]>;
  soundEmitterHasAudioById: Map<string, boolean>;
}

interface ProjectSchedulerActorValidationUsage {
  sceneId: string;
  entityId: string;
  modelAssetId: string | null;
  animationNames: string[];
  pathIds: Set<string>;
  enabledPathIds: Set<string>;
}

function incrementSchedulerValidationCount(
  counts: Map<string, number>,
  id: string
) {
  counts.set(id, (counts.get(id) ?? 0) + 1);
}

function addSchedulerValidationKind<TKey extends string, TValue extends string>(
  collection: Map<TKey, Set<TValue>>,
  key: TKey,
  value: TValue
) {
  const values = collection.get(key) ?? new Set<TValue>();
  values.add(value);
  collection.set(key, values);
}

function createEmptyProjectSchedulerValidationContext(): ProjectSchedulerValidationContext {
  return {
    actorIds: new Set<string>(),
    actorUsagesById: new Map<string, ProjectSchedulerActorValidationUsage[]>(),
    brushCounts: new Map<string, number>(),
    entityCounts: new Map<string, number>(),
    entityKindsById: new Map<string, Set<EntityInstance["kind"]>>(),
    modelInstanceCounts: new Map<string, number>(),
    modelAnimationNamesById: new Map<string, string[]>(),
    soundEmitterHasAudioById: new Map<string, boolean>()
  };
}

function recordProjectSchedulerSceneTargets(
  context: ProjectSchedulerValidationContext,
  scene: Pick<
    SceneDocument,
    "brushes" | "entities" | "modelInstances" | "assets" | "paths"
  >,
  sceneId: string
) {
  const pathIds = new Set(Object.keys(scene.paths));
  const enabledPathIds = new Set(
    Object.values(scene.paths)
      .filter((path) => path.enabled)
      .map((path) => path.id)
  );

  for (const brush of Object.values(scene.brushes)) {
    incrementSchedulerValidationCount(context.brushCounts, brush.id);
  }

  for (const entity of Object.values(scene.entities)) {
    incrementSchedulerValidationCount(context.entityCounts, entity.id);
    addSchedulerValidationKind(context.entityKindsById, entity.id, entity.kind);

    if (entity.kind === "npc") {
      context.actorIds.add(entity.actorId);
      const usages = context.actorUsagesById.get(entity.actorId) ?? [];
      const targetAsset =
        entity.modelAssetId === null
          ? undefined
          : scene.assets[entity.modelAssetId];
      usages.push({
        sceneId,
        entityId: entity.id,
        modelAssetId: entity.modelAssetId,
        animationNames:
          targetAsset !== undefined && targetAsset.kind === "model"
            ? [...targetAsset.metadata.animationNames]
            : [],
        pathIds: new Set(pathIds),
        enabledPathIds: new Set(enabledPathIds)
      });
      context.actorUsagesById.set(entity.actorId, usages);
    }

    if (entity.kind === "soundEmitter") {
      context.soundEmitterHasAudioById.set(
        entity.id,
        entity.audioAssetId !== null
      );
    }
  }

  for (const modelInstance of Object.values(scene.modelInstances)) {
    incrementSchedulerValidationCount(
      context.modelInstanceCounts,
      modelInstance.id
    );

    const targetAsset = scene.assets[modelInstance.assetId];
    const animationNames =
      targetAsset !== undefined && targetAsset.kind === "model"
        ? [...targetAsset.metadata.animationNames]
        : [];

    context.modelAnimationNamesById.set(modelInstance.id, animationNames);
  }
}

function createProjectSchedulerValidationContextFromSceneDocument(
  document: SceneDocument
): ProjectSchedulerValidationContext {
  const context = createEmptyProjectSchedulerValidationContext();
  recordProjectSchedulerSceneTargets(context, document, "activeScene");
  return context;
}

function createProjectSchedulerValidationContextFromProjectDocument(
  document: ProjectDocument
): ProjectSchedulerValidationContext {
  const context = createEmptyProjectSchedulerValidationContext();

  for (const scene of Object.values(document.scenes)) {
    recordProjectSchedulerSceneTargets(
      context,
      {
        brushes: scene.brushes,
        entities: scene.entities,
        modelInstances: scene.modelInstances,
        assets: document.assets,
        paths: scene.paths
      },
      scene.id
    );
  }

  return context;
}

function validateProjectSchedulerActorTarget(
  target: ActorControlTargetRef,
  path: string,
  context: ProjectSchedulerValidationContext,
  diagnostics: SceneDiagnostic[]
) {
  if (context.actorIds.has(target.actorId)) {
    return;
  }

  diagnostics.push(
    createDiagnostic(
      "error",
      "missing-control-actor-target",
      `Actor control target ${target.actorId} does not exist in this document.`,
      `${path}.actorId`
    )
  );
}

function getProjectSchedulerActorValidationUsages(
  context: ProjectSchedulerValidationContext,
  actorId: string
): ProjectSchedulerActorValidationUsage[] {
  return context.actorUsagesById.get(actorId) ?? [];
}

function validateProjectSchedulerSingleActorUsage(
  target: ActorControlTargetRef,
  path: string,
  context: ProjectSchedulerValidationContext,
  diagnostics: SceneDiagnostic[],
  capabilityLabel: string
): ProjectSchedulerActorValidationUsage | null {
  validateProjectSchedulerActorTarget(target, path, context, diagnostics);

  const usages = getProjectSchedulerActorValidationUsages(
    context,
    target.actorId
  );

  if (usages.length === 1) {
    return usages[0] ?? null;
  }

  if (usages.length > 1) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "ambiguous-project-schedule-actor-usage",
        `${capabilityLabel} currently requires an actor with exactly one NPC usage in the project.`,
        `${path}.actorId`
      )
    );
  }

  return null;
}

function validateProjectSchedulerEntityTarget(
  target: ControlTargetRef & { kind: "entity" },
  path: string,
  context: ProjectSchedulerValidationContext,
  diagnostics: SceneDiagnostic[]
) {
  const entityCount = context.entityCounts.get(target.entityId) ?? 0;

  if (entityCount === 0) {
    diagnostics.push(
      createDiagnostic(
        "error",
        target.entityKind === "soundEmitter"
          ? "missing-control-sound-emitter-entity"
          : target.entityKind === "cameraRig"
            ? "missing-control-camera-rig-entity"
            : "missing-control-light-entity",
        `${
          target.entityKind === "soundEmitter"
            ? "Control sound emitter"
            : target.entityKind === "cameraRig"
              ? "Camera control"
              : "Light control"
        } target entity ${target.entityId} does not exist.`,
        `${path}.entityId`
      )
    );
    return;
  }

  if (entityCount > 1) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "ambiguous-project-schedule-entity-target",
        `Project schedule target ${target.entityId} exists in multiple scenes and must be unique to be scheduler-addressable.`,
        `${path}.entityId`
      )
    );
    return;
  }

  const entityKinds = context.entityKindsById.get(target.entityId) ?? new Set();

  if (!entityKinds.has(target.entityKind)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        target.entityKind === "soundEmitter"
          ? "invalid-control-sound-emitter-kind"
          : target.entityKind === "cameraRig"
            ? "invalid-control-camera-rig-target-kind"
            : "invalid-control-light-target-kind",
        target.entityKind === "soundEmitter"
          ? "Control sound effects must target a Sound Emitter entity."
          : target.entityKind === "cameraRig"
            ? "Camera control effects must target a Camera Rig entity of the authored target kind."
            : "Light control effects must target a Point Light or Spot Light entity of the authored target kind.",
        `${path}.entityKind`
      )
    );
  }
}

function validateProjectSchedulerInteractionTarget(
  target: InteractionControlTargetRef,
  path: string,
  context: ProjectSchedulerValidationContext,
  diagnostics: SceneDiagnostic[]
) {
  const entityCount = context.entityCounts.get(target.entityId) ?? 0;

  if (entityCount === 0) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "missing-control-interaction-entity",
        `Interaction control target entity ${target.entityId} does not exist.`,
        `${path}.entityId`
      )
    );
    return;
  }

  if (entityCount > 1) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "ambiguous-project-schedule-interaction-target",
        `Project schedule interaction target ${target.entityId} exists in multiple scenes and must be unique to be scheduler-addressable.`,
        `${path}.entityId`
      )
    );
    return;
  }

  const entityKinds = context.entityKindsById.get(target.entityId) ?? new Set();

  if (!entityKinds.has(target.interactionKind)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-control-interaction-target-kind",
        "Interaction control effects must target an Interactable or Scene Exit entity of the authored target kind.",
        `${path}.interactionKind`
      )
    );
  }
}

function validateProjectSchedulerModelTarget(
  target: ModelInstanceControlTargetRef,
  path: string,
  context: ProjectSchedulerValidationContext,
  diagnostics: SceneDiagnostic[]
) {
  const modelInstanceCount =
    context.modelInstanceCounts.get(target.modelInstanceId) ?? 0;

  if (modelInstanceCount === 0) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "missing-control-model-instance-target",
        `Control model instance target ${target.modelInstanceId} does not exist.`,
        `${path}.modelInstanceId`
      )
    );
    return;
  }

  if (modelInstanceCount > 1) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "ambiguous-project-schedule-model-instance-target",
        `Project schedule model instance target ${target.modelInstanceId} exists in multiple scenes and must be unique to be scheduler-addressable.`,
        `${path}.modelInstanceId`
      )
    );
  }
}

function validateProjectSchedulerSceneTarget(
  target: SceneControlTargetRef,
  path: string,
  diagnostics: SceneDiagnostic[]
) {
  if (target.scope === "activeScene") {
    return;
  }

  diagnostics.push(
    createDiagnostic(
      "error",
      "invalid-control-scene-target",
      "Scene control effects must target the active scene scope.",
      `${path}.scope`
    )
  );
}

function validateProjectSchedulerControlTarget(
  target: ControlTargetRef,
  path: string,
  context: ProjectSchedulerValidationContext,
  diagnostics: SceneDiagnostic[]
) {
  switch (target.kind) {
    case "actor":
      validateProjectSchedulerActorTarget(target, path, context, diagnostics);
      return;
    case "entity":
      validateProjectSchedulerEntityTarget(target, path, context, diagnostics);
      return;
    case "interaction":
      validateProjectSchedulerInteractionTarget(
        target,
        path,
        context,
        diagnostics
      );
      return;
    case "scene":
      validateProjectSchedulerSceneTarget(target, path, diagnostics);
      return;
    case "modelInstance":
      validateProjectSchedulerModelTarget(target, path, context, diagnostics);
      return;
    case "global":
      return;
  }
}

function validateProjectSchedulerSoundEmitterTarget(
  target: SoundEmitterControlTargetRef,
  path: string,
  context: ProjectSchedulerValidationContext,
  diagnostics: SceneDiagnostic[],
  options: { requireAudioAsset: boolean }
) {
  validateProjectSchedulerEntityTarget(target, path, context, diagnostics);

  if (!options.requireAudioAsset) {
    return;
  }

  const entityCount = context.entityCounts.get(target.entityId) ?? 0;

  if (entityCount !== 1) {
    return;
  }

  if (context.soundEmitterHasAudioById.get(target.entityId) === false) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "missing-control-sound-emitter-audio-asset",
        "Control sound playback effects require a Sound Emitter that references an audio asset.",
        `${path}.entityId`
      )
    );
  }
}

function validateProjectSchedulerEffect(
  effect: ControlEffect,
  path: string,
  context: ProjectSchedulerValidationContext,
  diagnostics: SceneDiagnostic[]
) {
  switch (effect.type) {
    case "setActorPresence":
      validateProjectSchedulerActorTarget(
        effect.target,
        `${path}.target`,
        context,
        diagnostics
      );
      if (!isBoolean(effect.active)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-actor-active",
            "Actor presence control values must remain boolean.",
            `${path}.active`
          )
        );
      }
      return;
    case "activateCameraRigOverride":
    case "clearCameraRigOverride":
      validateProjectSchedulerEntityTarget(
        effect.target,
        `${path}.target`,
        context,
        diagnostics
      );
      return;
    case "playActorAnimation": {
      const usage = validateProjectSchedulerSingleActorUsage(
        effect.target,
        `${path}.target`,
        context,
        diagnostics,
        "Actor animation scheduling"
      );

      if (effect.clipName.trim().length === 0) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-actor-animation-clip-name",
            "Actor animation clip names must be non-empty.",
            `${path}.clipName`
          )
        );
        return;
      }

      if (usage === null) {
        return;
      }

      if (!usage.animationNames.includes(effect.clipName)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "missing-control-actor-animation-clip",
            `Actor animation clip ${effect.clipName} does not exist on the uniquely bound NPC model asset.`,
            `${path}.clipName`
          )
        );
      }
      return;
    }
    case "followActorPath": {
      const usage = validateProjectSchedulerSingleActorUsage(
        effect.target,
        `${path}.target`,
        context,
        diagnostics,
        "Actor path scheduling"
      );

      if (effect.pathId.trim().length === 0) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-actor-path-id",
            "Actor path ids must be non-empty.",
            `${path}.pathId`
          )
        );
      }

      if (!isPositiveFiniteNumber(effect.speed)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-actor-path-speed",
            "Actor path speed must remain finite and greater than zero.",
            `${path}.speed`
          )
        );
      }

      if (!isBoolean(effect.loop)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-actor-path-loop",
            "Actor path loop must remain a boolean.",
            `${path}.loop`
          )
        );
      }

      if (!isBoolean(effect.smoothPath)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-actor-path-smooth",
            "Actor path smoothing must remain a boolean.",
            `${path}.smoothPath`
          )
        );
      }

      if (!isActorPathProgressMode(effect.progressMode)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-actor-path-progress-mode",
            "Actor path progress mode must use a supported typed value.",
            `${path}.progressMode`
          )
        );
      }

      if (usage === null) {
        return;
      }

      if (!usage.pathIds.has(effect.pathId)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "missing-control-actor-path",
            `Actor path ${effect.pathId} does not exist in the uniquely bound NPC scene.`,
            `${path}.pathId`
          )
        );
        return;
      }

      if (!usage.enabledPathIds.has(effect.pathId)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "disabled-control-actor-path",
            "Actor follow-path routines require an enabled authored path.",
            `${path}.pathId`
          )
        );
      }
      return;
    }
    case "playModelAnimation": {
      validateProjectSchedulerModelTarget(
        effect.target,
        `${path}.target`,
        context,
        diagnostics
      );

      if (effect.clipName.trim().length === 0) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-play-animation-clip-name",
            "Control play animation clip name must be non-empty.",
            `${path}.clipName`
          )
        );
        return;
      }

      const targetCount =
        context.modelInstanceCounts.get(effect.target.modelInstanceId) ?? 0;

      if (targetCount !== 1) {
        return;
      }

      const animationNames =
        context.modelAnimationNamesById.get(effect.target.modelInstanceId) ??
        [];

      if (
        animationNames.length > 0 &&
        !animationNames.includes(effect.clipName)
      ) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "missing-control-play-animation-clip",
            `Control play animation clip ${effect.clipName} does not exist on the target model asset.`,
            `${path}.clipName`
          )
        );
      }
      return;
    }
    case "stopModelAnimation":
      validateProjectSchedulerModelTarget(
        effect.target,
        `${path}.target`,
        context,
        diagnostics
      );
      return;
    case "setModelInstanceVisible":
      validateProjectSchedulerModelTarget(
        effect.target,
        `${path}.target`,
        context,
        diagnostics
      );
      if (!isBoolean(effect.visible)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-model-instance-visible",
            "Model visibility control values must remain boolean.",
            `${path}.visible`
          )
        );
      }
      return;
    case "playSound":
    case "stopSound":
      validateProjectSchedulerSoundEmitterTarget(
        effect.target,
        `${path}.target`,
        context,
        diagnostics,
        { requireAudioAsset: true }
      );
      return;
    case "setSoundVolume":
      validateProjectSchedulerSoundEmitterTarget(
        effect.target,
        `${path}.target`,
        context,
        diagnostics,
        { requireAudioAsset: false }
      );
      if (!isNonNegativeFiniteNumber(effect.volume)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-sound-volume",
            "Sound control volume must remain finite and zero or greater.",
            `${path}.volume`
          )
        );
      }
      return;
    case "setInteractionEnabled":
      validateProjectSchedulerInteractionTarget(
        effect.target,
        `${path}.target`,
        context,
        diagnostics
      );
      if (!isBoolean(effect.enabled)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-interaction-enabled",
            "Interaction control enabled values must remain boolean.",
            `${path}.enabled`
          )
        );
      }
      return;
    case "setLightEnabled":
      validateProjectSchedulerEntityTarget(
        effect.target,
        `${path}.target`,
        context,
        diagnostics
      );
      if (!isBoolean(effect.enabled)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-light-enabled",
            "Light control enabled values must remain boolean.",
            `${path}.enabled`
          )
        );
      }
      return;
    case "setLightIntensity":
      validateProjectSchedulerEntityTarget(
        effect.target,
        `${path}.target`,
        context,
        diagnostics
      );
      if (!isNonNegativeFiniteNumber(effect.intensity)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-light-intensity",
            "Light control intensity must remain finite and zero or greater.",
            `${path}.intensity`
          )
        );
      }
      return;
    case "setLightColor":
      validateProjectSchedulerEntityTarget(
        effect.target,
        `${path}.target`,
        context,
        diagnostics
      );
      if (!isHexColorString(effect.colorHex)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-light-color",
            "Light control color must remain a valid hex color string.",
            `${path}.colorHex`
          )
        );
      }
      return;
    case "setAmbientLightIntensity":
      validateProjectSchedulerSceneTarget(
        effect.target,
        `${path}.target`,
        diagnostics
      );
      if (!isNonNegativeFiniteNumber(effect.intensity)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-ambient-light-intensity",
            "Ambient light control intensity must remain finite and zero or greater.",
            `${path}.intensity`
          )
        );
      }
      return;
    case "setAmbientLightColor":
      validateProjectSchedulerSceneTarget(
        effect.target,
        `${path}.target`,
        diagnostics
      );
      if (!isHexColorString(effect.colorHex)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-ambient-light-color",
            "Ambient light control color must remain a valid hex color string.",
            `${path}.colorHex`
          )
        );
      }
      return;
    case "setSunLightIntensity":
      validateProjectSchedulerSceneTarget(
        effect.target,
        `${path}.target`,
        diagnostics
      );
      if (!isNonNegativeFiniteNumber(effect.intensity)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-sun-light-intensity",
            "Sun light control intensity must remain finite and zero or greater.",
            `${path}.intensity`
          )
        );
      }
      return;
    case "setSunLightColor":
      validateProjectSchedulerSceneTarget(
        effect.target,
        `${path}.target`,
        diagnostics
      );
      if (!isHexColorString(effect.colorHex)) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-control-sun-light-color",
            "Sun light control color must remain a valid hex color string.",
            `${path}.colorHex`
          )
        );
      }
      return;
  }
}

function registerAuthoredId(
  id: string,
  path: string,
  seenIds: Map<string, string>,
  diagnostics: SceneDiagnostic[]
) {
  const previousPath = seenIds.get(id);

  if (previousPath !== undefined) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "duplicate-authored-id",
        `Duplicate authored id ${id} is already used at ${previousPath}.`,
        path
      )
    );
    return;
  }

  seenIds.set(id, path);
}

function prefixDiagnosticPath(
  prefix: string,
  path?: string
): string | undefined {
  return path === undefined ? undefined : `${prefix}${path}`;
}

function validateProjectDialogue(
  dialogue: ProjectDialogue,
  path: string,
  seenIds: Map<string, string>,
  diagnostics: SceneDiagnostic[]
) {
  if (dialogue.id.trim().length === 0) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-dialogue-id",
        "Dialogue ids must be non-empty.",
        `${path}.id`
      )
    );
  }

  if (dialogue.title.trim().length === 0) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-dialogue-title",
        "Dialogue titles must be non-empty.",
        `${path}.title`
      )
    );
  }

  if (dialogue.lines.length === 0) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "missing-dialogue-lines",
        "Dialogues must contain at least one line.",
        `${path}.lines`
      )
    );
    return;
  }

  for (const [lineIndex, line] of dialogue.lines.entries()) {
    const linePath = `${path}.lines.${lineIndex}`;

    registerAuthoredId(line.id, linePath, seenIds, diagnostics);

    if (line.text.trim().length === 0) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-dialogue-line-text",
          "Dialogue line text must be non-empty.",
          `${linePath}.text`
        )
      );
    }
  }
}

function validateProjectSequence(
  sequence: ProjectSequence,
  path: string,
  projectResources: Pick<ProjectDocument, "scenes"> & {
    currentSceneEntities?: SceneDocument["entities"];
  },
  context: ProjectSchedulerValidationContext,
  diagnostics: SceneDiagnostic[]
) {
  const projectScenes = projectResources.scenes ?? {};
  const currentSceneEntities = projectResources.currentSceneEntities ?? {};

  if (sequence.title.trim().length === 0) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-project-sequence-title",
        "Project sequence titles must be non-empty.",
        `${path}.title`
      )
    );
  }

  if (sequence.effects.length === 0) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-project-sequence-effects-empty",
        "Project sequences must contain at least one effect.",
        `${path}.effects`
      )
    );
    return;
  }

  for (const [effectIndex, effect] of sequence.effects.entries()) {
    const effectPath = `${path}.effects.${effectIndex}`;

    switch (effect.type) {
      case "controlEffect":
        validateProjectSchedulerEffect(
          effect.effect,
          `${effectPath}.effect`,
          context,
          diagnostics
        );
        break;
      case "makeNpcTalk": {
        let targetNpc: NpcEntity | null = null;

        for (const scene of Object.values(projectScenes)) {
          const candidate = scene.entities[effect.npcEntityId];

          if (candidate?.kind === "npc") {
            targetNpc = candidate;
            break;
          }
        }

        if (targetNpc === null) {
          const candidate = currentSceneEntities[effect.npcEntityId];

          if (candidate?.kind === "npc") {
            targetNpc = candidate;
          }
        }

        if (targetNpc === null) {
          diagnostics.push(
            createDiagnostic(
              "error",
              "missing-sequence-npc-dialogue-target",
              `NPC ${effect.npcEntityId} does not exist in this project.`,
              `${effectPath}.npcEntityId`
            )
          );
          break;
        }

        if (
          effect.dialogueId !== null &&
          !targetNpc.dialogues.some(
            (dialogue) => dialogue.id === effect.dialogueId
          )
        ) {
          diagnostics.push(
            createDiagnostic(
              "error",
              "missing-sequence-npc-dialogue",
              `Dialogue ${effect.dialogueId} does not exist on NPC ${effect.npcEntityId}.`,
              `${effectPath}.dialogueId`
            )
          );
        }
        break;
      }
      case "teleportPlayer":
        break;
      case "startSceneTransition": {
        if (Object.keys(projectScenes).length === 0) {
          break;
        }

        const targetScene = projectScenes[effect.targetSceneId] ?? null;

        if (targetScene === null) {
          diagnostics.push(
            createDiagnostic(
              "error",
              "missing-sequence-transition-target-scene",
              `Scene transition target scene ${effect.targetSceneId} does not exist in this project.`,
              `${effectPath}.targetSceneId`
            )
          );
          break;
        }

        const targetEntry =
          targetScene.entities[effect.targetEntryEntityId] ?? null;

        if (targetEntry === null) {
          diagnostics.push(
            createDiagnostic(
              "error",
              "missing-sequence-transition-target-entry",
              `Scene transition target entry ${effect.targetEntryEntityId} does not exist in scene ${targetScene.name}.`,
              `${effectPath}.targetEntryEntityId`
            )
          );
          break;
        }

        if (targetEntry.kind !== "sceneEntry") {
          diagnostics.push(
            createDiagnostic(
              "error",
              "invalid-sequence-transition-target-entry-kind",
              `Scene transition target ${effect.targetEntryEntityId} in scene ${targetScene.name} is not a Scene Entry.`,
              `${effectPath}.targetEntryEntityId`
            )
          );
        }
        break;
      }
      case "setVisibility":
        if (effect.target.kind === "brush") {
          if ((context.brushCounts.get(effect.target.brushId) ?? 0) === 0) {
            diagnostics.push(
              createDiagnostic(
                "error",
                "missing-sequence-visibility-target-brush",
                `Sequence visibility target brush ${effect.target.brushId} does not exist.`,
                `${effectPath}.target.brushId`
              )
            );
          }
        } else if (
          (context.modelInstanceCounts.get(effect.target.modelInstanceId) ??
            0) === 0
        ) {
          diagnostics.push(
            createDiagnostic(
              "error",
              "missing-sequence-visibility-target-model-instance",
              `Sequence visibility target model instance ${effect.target.modelInstanceId} does not exist.`,
              `${effectPath}.target.modelInstanceId`
            )
          );
        }
        break;
    }
  }
}

function validateProjectResources(
  document: Pick<
    ProjectDocument,
    "materials" | "assets" | "sequences" | "scenes"
  >,
  context: ProjectSchedulerValidationContext,
  diagnostics: SceneDiagnostic[]
) {
  const seenIds = new Map<string, string>();

  for (const [materialKey, material] of Object.entries(document.materials)) {
    const path = `materials.${materialKey}`;

    if (material.id !== materialKey) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "material-id-mismatch",
          "Material ids must match their registry key.",
          `${path}.id`
        )
      );
    }

    registerAuthoredId(material.id, path, seenIds, diagnostics);
  }

  for (const [assetKey, asset] of Object.entries(document.assets)) {
    const path = `assets.${assetKey}`;

    if (asset.id !== assetKey) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "asset-id-mismatch",
          "Asset ids must match their registry key.",
          `${path}.id`
        )
      );
    }

    registerAuthoredId(asset.id, path, seenIds, diagnostics);
    validateProjectAsset(asset, path, diagnostics);
  }

  for (const [sequenceKey, sequence] of Object.entries(
    document.sequences.sequences
  )) {
    const path = `sequences.sequences.${sequenceKey}`;

    if (sequence.id !== sequenceKey) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "sequence-id-mismatch",
          "Sequence ids must match their registry key.",
          `${path}.id`
        )
      );
    }

    registerAuthoredId(sequence.id, path, seenIds, diagnostics);
    validateProjectSequence(
      sequence,
      path,
      { scenes: document.scenes },
      context,
      diagnostics
    );
  }
}

function filterProjectSceneDiagnostics(
  diagnostics: SceneDiagnostic[]
): SceneDiagnostic[] {
  return diagnostics.filter(
    (diagnostic) =>
      diagnostic.path === undefined ||
      (!diagnostic.path.startsWith("materials.") &&
        !diagnostic.path.startsWith("time.") &&
        !diagnostic.path.startsWith("assets.") &&
        !diagnostic.path.startsWith("dialogues.") &&
        !diagnostic.path.startsWith("sequences."))
  );
}

function validateProjectSceneLoadingScreen(
  scene: ProjectDocument["scenes"][string],
  scenePath: string,
  diagnostics: SceneDiagnostic[]
) {
  if (!isHexColorString(scene.loadingScreen.colorHex)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-scene-loading-color",
        "Scene loading overlays must use #RRGGBB colors.",
        `${scenePath}.loadingScreen.colorHex`
      )
    );
  }

  if (
    scene.loadingScreen.headline !== null &&
    scene.loadingScreen.headline.trim().length === 0
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-scene-loading-headline",
        "Scene loading overlay headlines must be non-empty when authored.",
        `${scenePath}.loadingScreen.headline`
      )
    );
  }

  if (
    scene.loadingScreen.description !== null &&
    scene.loadingScreen.description.trim().length === 0
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-scene-loading-description",
        "Scene loading overlay descriptions must be non-empty when authored.",
        `${scenePath}.loadingScreen.description`
      )
    );
  }
}

function validateProjectSceneEditorPreferences(
  scene: ProjectDocument["scenes"][string],
  scenePath: string,
  diagnostics: SceneDiagnostic[]
) {
  const preferences = scene.editorPreferences;

  if (!WHITEBOX_SELECTION_MODES.includes(preferences.whiteboxSelectionMode)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-scene-editor-selection-mode",
        "Scene editor selection mode must be one of object, face, edge, or vertex.",
        `${scenePath}.editorPreferences.whiteboxSelectionMode`
      )
    );
  }

  if (
    preferences.viewportLayoutMode !== "single" &&
    preferences.viewportLayoutMode !== "quad"
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-scene-editor-layout-mode",
        "Scene editor viewport layout must be single or quad.",
        `${scenePath}.editorPreferences.viewportLayoutMode`
      )
    );
  }

  if (
    preferences.activeViewportPanelId !== "topLeft" &&
    preferences.activeViewportPanelId !== "topRight" &&
    preferences.activeViewportPanelId !== "bottomLeft" &&
    preferences.activeViewportPanelId !== "bottomRight"
  ) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-scene-editor-active-panel",
        "Scene editor active viewport panel must reference a supported panel id.",
        `${scenePath}.editorPreferences.activeViewportPanelId`
      )
    );
  }

  if (!isPositiveFiniteNumber(preferences.whiteboxSnapStep)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-scene-editor-snap-step",
        "Scene editor snap step must be greater than zero.",
        `${scenePath}.editorPreferences.whiteboxSnapStep`
      )
    );
  }

  if (!isFiniteNumber(preferences.viewportQuadSplit.x)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-scene-editor-quad-split-x",
        "Scene editor quad split X must be finite.",
        `${scenePath}.editorPreferences.viewportQuadSplit.x`
      )
    );
  }

  if (!isFiniteNumber(preferences.viewportQuadSplit.y)) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-scene-editor-quad-split-y",
        "Scene editor quad split Y must be finite.",
        `${scenePath}.editorPreferences.viewportQuadSplit.y`
      )
    );
  }

  for (const [panelId, panelPreferences] of Object.entries(
    preferences.viewportPanels
  )) {
    if (
      panelPreferences.viewMode !== "perspective" &&
      panelPreferences.viewMode !== "top" &&
      panelPreferences.viewMode !== "front" &&
      panelPreferences.viewMode !== "side"
    ) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-scene-editor-panel-view-mode",
          "Scene editor panel view mode must be perspective, top, front, or side.",
          `${scenePath}.editorPreferences.viewportPanels.${panelId}.viewMode`
        )
      );
    }

    if (
      panelPreferences.displayMode !== "normal" &&
      panelPreferences.displayMode !== "authoring" &&
      panelPreferences.displayMode !== "wireframe"
    ) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-scene-editor-panel-display-mode",
          "Scene editor panel display mode must be normal, authoring, or wireframe.",
          `${scenePath}.editorPreferences.viewportPanels.${panelId}.displayMode`
        )
      );
    }
  }
}

export function formatSceneDiagnostic(diagnostic: SceneDiagnostic): string {
  return diagnostic.path === undefined
    ? diagnostic.message
    : `${diagnostic.path}: ${diagnostic.message}`;
}

export function formatSceneDiagnosticSummary(
  diagnostics: SceneDiagnostic[],
  limit = 3
): string {
  if (diagnostics.length === 0) {
    return "No diagnostics.";
  }

  const visibleDiagnostics = diagnostics.slice(0, Math.max(1, limit));
  const summary = visibleDiagnostics
    .map((diagnostic) => formatSceneDiagnostic(diagnostic))
    .join("; ");
  const remainingCount = diagnostics.length - visibleDiagnostics.length;

  return remainingCount > 0 ? `${summary}; +${remainingCount} more` : summary;
}

export function validateSceneDocument(
  document: SceneDocument
): SceneDocumentValidationResult {
  const diagnostics: SceneDiagnostic[] = [];
  const seenIds = new Map<string, string>();
  const projectSchedulerValidationContext =
    createProjectSchedulerValidationContextFromSceneDocument(document);

  validateProjectTimeSettings(document.time, diagnostics);
  validateWorldSettings(document.world, document, diagnostics);

  for (const [materialKey, material] of Object.entries(document.materials)) {
    const path = `materials.${materialKey}`;

    if (material.id !== materialKey) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "material-id-mismatch",
          "Material ids must match their registry key.",
          `${path}.id`
        )
      );
    }

    registerAuthoredId(material.id, path, seenIds, diagnostics);
  }

  for (const [assetKey, asset] of Object.entries(document.assets)) {
    const path = `assets.${assetKey}`;

    if (asset.id !== assetKey) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "asset-id-mismatch",
          "Asset ids must match their registry key.",
          `${path}.id`
        )
      );
    }

    registerAuthoredId(asset.id, path, seenIds, diagnostics);
    validateProjectAsset(asset, path, diagnostics);
  }

  for (const [sequenceKey, sequence] of Object.entries(
    document.sequences.sequences
  )) {
    const path = `sequences.sequences.${sequenceKey}`;

    if (sequence.id !== sequenceKey) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "sequence-id-mismatch",
          "Sequence ids must match their registry key.",
          `${path}.id`
        )
      );
    }

    registerAuthoredId(sequence.id, path, seenIds, diagnostics);
    validateProjectSequence(
      sequence,
      path,
      { scenes: {}, currentSceneEntities: document.entities },
      projectSchedulerValidationContext,
      diagnostics
    );
  }

  for (const [brushKey, brush] of Object.entries(document.brushes)) {
    const path = `brushes.${brushKey}`;

    if (brush.id !== brushKey) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "brush-id-mismatch",
          "Brush ids must match their registry key.",
          `${path}.id`
        )
      );
    }

    registerAuthoredId(brush.id, path, seenIds, diagnostics);

    if (!isBoolean(brush.visible)) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-box-visible",
          "Box brush visible must remain a boolean.",
          `${path}.visible`
        )
      );
    }

    if (!isBoolean(brush.enabled)) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-box-enabled",
          "Box brush enabled must remain a boolean.",
          `${path}.enabled`
        )
      );
    }

    if (brush.name !== undefined && brush.name.trim().length === 0) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-box-name",
          "Box brush names must be non-empty when authored.",
          `${path}.name`
        )
      );
    }

    if (!isFiniteVec3(brush.center)) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-box-center",
          "Box brush centers must remain finite on every axis.",
          `${path}.center`
        )
      );
    }

    if (!isFiniteVec3(brush.rotationDegrees)) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-box-rotation",
          "Box brush rotations must remain finite on every axis.",
          `${path}.rotationDegrees`
        )
      );
    }

    if (!isFiniteVec3(brush.size) || !hasPositiveBoxSize(brush.size)) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-box-size",
          "Box brush sizes must remain finite and positive on every axis.",
          `${path}.size`
        )
      );
    }

    if (brush.kind === "radialPrism") {
      try {
        normalizeRadialPrismSideCount(brush.sideCount);
      } catch (error) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-radial-prism-side-count",
            error instanceof Error
              ? error.message
              : "Radial prism side count must be valid.",
            `${path}.sideCount`
          )
        );
      }
    }

    if (brush.kind === "cone") {
      try {
        normalizeConeSideCount(brush.sideCount);
      } catch (error) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-cone-side-count",
            error instanceof Error
              ? error.message
              : "Cone side count must be valid.",
            `${path}.sideCount`
          )
        );
      }
    }

    if (brush.kind === "torus") {
      try {
        normalizeTorusMajorSegmentCount(brush.majorSegmentCount);
      } catch (error) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-torus-major-segment-count",
            error instanceof Error
              ? error.message
              : "Torus major segment count must be valid.",
            `${path}.majorSegmentCount`
          )
        );
      }

      try {
        normalizeTorusTubeSegmentCount(brush.tubeSegmentCount);
      } catch (error) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-torus-tube-segment-count",
            error instanceof Error
              ? error.message
              : "Torus tube segment count must be valid.",
            `${path}.tubeSegmentCount`
          )
        );
      }
    }

    for (const vertexId of getBrushVertexIds(brush)) {
      if (!isFiniteVec3(brush.geometry.vertices[vertexId])) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-box-geometry-vertex",
            "Box brush geometry vertices must remain finite on every axis.",
            `${path}.geometry.vertices.${vertexId}`
          )
        );
      }
    }

    for (const faceId of getBrushFaceIds(brush)) {
      const materialId = brush.faces[faceId].materialId;

      if (materialId !== null && document.materials[materialId] === undefined) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "missing-material-ref",
            `Face material reference ${materialId} does not exist in the document material registry.`,
            `${path}.faces.${faceId}.materialId`
          )
        );
      }
    }

    const volume = brush.volume as Record<string, unknown>;

    if (!isBoxBrushVolumeMode(volume.mode)) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-box-volume-mode",
          "Box volume mode must be none, water, fog, or light.",
          `${path}.volume.mode`
        )
      );
      continue;
    }

    if (brush.kind !== "box" && volume.mode !== "none") {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-non-box-volume-mode",
          "Only whitebox boxes support water, fog, or light volume modes.",
          `${path}.volume.mode`
        )
      );
      continue;
    }

    if (volume.mode === "water") {
      const water = volume.water as Record<string, unknown> | undefined;

      if (water === undefined) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-box-water-settings",
            "Water volumes must define water settings.",
            `${path}.volume.water`
          )
        );
      } else {
        if (
          typeof water.colorHex !== "string" ||
          !isHexColorString(water.colorHex)
        ) {
          diagnostics.push(
            createDiagnostic(
              "error",
              "invalid-box-water-color",
              "Water volume color must use #RRGGBB format.",
              `${path}.volume.water.colorHex`
            )
          );
        }

        if (!isNonNegativeFiniteNumber(water.surfaceOpacity)) {
          diagnostics.push(
            createDiagnostic(
              "error",
              "invalid-box-water-surface-opacity",
              "Water surface opacity must be a non-negative finite number.",
              `${path}.volume.water.surfaceOpacity`
            )
          );
        }

        if (!isNonNegativeFiniteNumber(water.waveStrength)) {
          diagnostics.push(
            createDiagnostic(
              "error",
              "invalid-box-water-wave-strength",
              "Water wave strength must be a non-negative finite number.",
              `${path}.volume.water.waveStrength`
            )
          );
        }

        if (
          !isPositiveIntegerInRange(
            water.foamContactLimit,
            MAX_BOX_BRUSH_WATER_FOAM_CONTACT_LIMIT
          )
        ) {
          diagnostics.push(
            createDiagnostic(
              "error",
              "invalid-box-water-foam-contact-limit",
              `Water foam contact limit must be a positive integer between 1 and ${MAX_BOX_BRUSH_WATER_FOAM_CONTACT_LIMIT}.`,
              `${path}.volume.water.foamContactLimit`
            )
          );
        }

        if (typeof water.surfaceDisplacementEnabled !== "boolean") {
          diagnostics.push(
            createDiagnostic(
              "error",
              "invalid-box-water-surface-displacement-enabled",
              "Water surface displacement must be enabled or disabled explicitly.",
              `${path}.volume.water.surfaceDisplacementEnabled`
            )
          );
        }
      }
    }

    if (volume.mode === "fog") {
      const fog = volume.fog as Record<string, unknown> | undefined;

      if (fog === undefined) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-box-fog-settings",
            "Fog volumes must define fog settings.",
            `${path}.volume.fog`
          )
        );
      } else {
        if (
          typeof fog.colorHex !== "string" ||
          !isHexColorString(fog.colorHex)
        ) {
          diagnostics.push(
            createDiagnostic(
              "error",
              "invalid-box-fog-color",
              "Fog volume color must use #RRGGBB format.",
              `${path}.volume.fog.colorHex`
            )
          );
        }

        if (!isNonNegativeFiniteNumber(fog.density)) {
          diagnostics.push(
            createDiagnostic(
              "error",
              "invalid-box-fog-density",
              "Fog volume density must be a non-negative finite number.",
              `${path}.volume.fog.density`
            )
          );
        }

        if (!isNonNegativeFiniteNumber(fog.padding)) {
          diagnostics.push(
            createDiagnostic(
              "error",
              "invalid-box-fog-padding",
              "Fog volume padding must be a non-negative finite number.",
              `${path}.volume.fog.padding`
            )
          );
        }
      }
    }

    if (volume.mode === "light") {
      const light = volume.light as Record<string, unknown> | undefined;

      if (light === undefined) {
        diagnostics.push(
          createDiagnostic(
            "error",
            "invalid-box-light-settings",
            "Light volumes must define light settings.",
            `${path}.volume.light`
          )
        );
      } else {
        if (
          typeof light.colorHex !== "string" ||
          !isHexColorString(light.colorHex)
        ) {
          diagnostics.push(
            createDiagnostic(
              "error",
              "invalid-box-light-color",
              "Light volume color must use #RRGGBB format.",
              `${path}.volume.light.colorHex`
            )
          );
        }

        if (!isNonNegativeFiniteNumber(light.intensity)) {
          diagnostics.push(
            createDiagnostic(
              "error",
              "invalid-box-light-intensity",
              "Light volume intensity must be a non-negative finite number.",
              `${path}.volume.light.intensity`
            )
          );
        }

        if (!isNonNegativeFiniteNumber(light.padding)) {
          diagnostics.push(
            createDiagnostic(
              "error",
              "invalid-box-light-padding",
              "Light volume padding must be a non-negative finite number.",
              `${path}.volume.light.padding`
            )
          );
        }

        if (!isBoxBrushLightFalloffMode(light.falloff)) {
          diagnostics.push(
            createDiagnostic(
              "error",
              "invalid-box-light-falloff",
              "Light volume falloff must be linear or smoothstep.",
              `${path}.volume.light.falloff`
            )
          );
        }
      }
    }
  }

  for (const [pathKey, pathValue] of Object.entries(document.paths)) {
    const path = `paths.${pathKey}`;

    if (pathValue.id !== pathKey) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "path-id-mismatch",
          "Path ids must match their registry key.",
          `${path}.id`
        )
      );
    }

    registerAuthoredId(pathValue.id, path, seenIds, diagnostics);
    validateScenePath(pathValue, path, diagnostics);
  }

  for (const [terrainKey, terrain] of Object.entries(document.terrains)) {
    const path = `terrains.${terrainKey}`;

    if (terrain.id !== terrainKey) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "terrain-id-mismatch",
          "Terrain ids must match their registry key.",
          `${path}.id`
        )
      );
    }

    registerAuthoredId(terrain.id, path, seenIds, diagnostics);
    validateTerrain(terrain, path, document, diagnostics);
  }

  for (const [modelInstanceKey, modelInstance] of Object.entries(
    document.modelInstances
  )) {
    const path = `modelInstances.${modelInstanceKey}`;

    if (modelInstance.id !== modelInstanceKey) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "model-instance-id-mismatch",
          "Model instance ids must match their registry key.",
          `${path}.id`
        )
      );
    }

    registerAuthoredId(modelInstance.id, path, seenIds, diagnostics);
    validateModelInstance(modelInstance, path, document, diagnostics);
  }

  const seenNpcActorIds = new Map<string, string>();

  for (const [entityKey, entity] of Object.entries(document.entities)) {
    const path = `entities.${entityKey}`;

    if (entity.id !== entityKey) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "entity-id-mismatch",
          "Entity ids must match their registry key.",
          `${path}.id`
        )
      );
    }

    registerAuthoredId(entity.id, path, seenIds, diagnostics);
    validateEntityName(entity.name, path, diagnostics);

    switch (entity.kind) {
      case "pointLight":
        validatePointLightEntity(entity, path, diagnostics);
        break;
      case "spotLight":
        validateSpotLightEntity(entity, path, diagnostics);
        break;
      case "cameraRig":
        validateCameraRigEntity(entity, path, document, diagnostics);
        break;
      case "playerStart":
        validatePlayerStartEntity(entity, path, diagnostics);
        break;
      case "sceneEntry":
        validateSceneEntryEntity(entity, path, diagnostics);
        break;
      case "npc": {
        validateNpcEntity(entity, path, document, diagnostics);

        const normalizedActorId =
          typeof entity.actorId === "string" ? entity.actorId.trim() : "";

        if (normalizedActorId.length > 0) {
          const previousPath = seenNpcActorIds.get(normalizedActorId);

          if (previousPath !== undefined) {
            diagnostics.push(
              createDiagnostic(
                "error",
                "duplicate-npc-actor-id",
                `NPC actorId ${normalizedActorId} is already used by ${previousPath}.`,
                `${path}.actorId`
              )
            );
          } else {
            seenNpcActorIds.set(normalizedActorId, path);
          }
        }
        break;
      }
      case "soundEmitter":
        validateSoundEmitterEntity(entity, path, document, diagnostics);
        break;
      case "triggerVolume":
        validateTriggerVolumeEntity(entity, path, diagnostics);
        break;
      case "teleportTarget":
        validateTeleportTargetEntity(entity, path, diagnostics);
        break;
      case "interactable":
        validateInteractableEntity(entity, path, diagnostics);
        break;
      default:
        diagnostics.push(
          createDiagnostic(
            "error",
            "unsupported-entity-kind",
            `Unsupported entity kind ${(entity as { kind: string }).kind}.`,
            `${path}.kind`
          )
        );
        break;
    }
  }

  for (const [linkKey, link] of Object.entries(document.interactionLinks)) {
    const path = `interactionLinks.${linkKey}`;

    if (link.id !== linkKey) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "interaction-link-id-mismatch",
          "Interaction link ids must match their registry key.",
          `${path}.id`
        )
      );
    }

    registerAuthoredId(link.id, path, seenIds, diagnostics);
    validateInteractionLink(link, path, document, diagnostics);
  }

  validateProjectScheduler(
    document.scheduler,
    document.sequences,
    projectSchedulerValidationContext,
    diagnostics
  );

  return {
    diagnostics,
    errors: diagnostics.filter((diagnostic) => diagnostic.severity === "error"),
    warnings: diagnostics.filter(
      (diagnostic) => diagnostic.severity === "warning"
    )
  };
}

export function assertSceneDocumentIsValid(document: SceneDocument) {
  const validation = validateSceneDocument(document);

  if (validation.errors.length > 0) {
    throw new Error(
      `Scene document has ${validation.errors.length} validation error(s): ${formatSceneDiagnosticSummary(validation.errors)}`
    );
  }
}

export function validateProjectDocument(
  document: ProjectDocument
): SceneDocumentValidationResult {
  const diagnostics: SceneDiagnostic[] = [];
  const projectSchedulerValidationContext =
    createProjectSchedulerValidationContextFromProjectDocument(document);

  if (document.name.trim().length === 0) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "invalid-project-name",
        "Project names must be non-empty.",
        "name"
      )
    );
  }

  if (Object.keys(document.scenes).length === 0) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "missing-project-scenes",
        "Project documents must contain at least one scene.",
        "scenes"
      )
    );
  }

  if (document.scenes[document.activeSceneId] === undefined) {
    diagnostics.push(
      createDiagnostic(
        "error",
        "missing-active-scene",
        `Project active scene ${document.activeSceneId} does not exist.`,
        "activeSceneId"
      )
    );
  }

  validateProjectTimeSettings(document.time, diagnostics);
  validateProjectResources(
    document,
    projectSchedulerValidationContext,
    diagnostics
  );

  validateProjectScheduler(
    document.scheduler,
    document.sequences,
    projectSchedulerValidationContext,
    diagnostics
  );

  for (const [sceneKey, scene] of Object.entries(document.scenes)) {
    const scenePath = `scenes.${sceneKey}`;

    if (scene.id !== sceneKey) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "scene-id-mismatch",
          "Scene ids must match their registry key.",
          `${scenePath}.id`
        )
      );
    }

    if (scene.name.trim().length === 0) {
      diagnostics.push(
        createDiagnostic(
          "error",
          "invalid-scene-name",
          "Scene names must be non-empty.",
          `${scenePath}.name`
        )
      );
    }

    validateProjectSceneLoadingScreen(scene, scenePath, diagnostics);
    validateProjectSceneEditorPreferences(scene, scenePath, diagnostics);

    const sceneDocument = {
      ...createSceneDocumentFromProject(document, sceneKey),
      scheduler: createEmptyProjectScheduler()
    };

    for (const diagnostic of filterProjectSceneDiagnostics(
      validateSceneDocument(sceneDocument).diagnostics
    )) {
      diagnostics.push({
        ...diagnostic,
        path: prefixDiagnosticPath(`${scenePath}.`, diagnostic.path)
      });
    }
  }

  return {
    diagnostics,
    errors: diagnostics.filter((diagnostic) => diagnostic.severity === "error"),
    warnings: diagnostics.filter(
      (diagnostic) => diagnostic.severity === "warning"
    )
  };
}

export function assertProjectDocumentIsValid(document: ProjectDocument) {
  const validation = validateProjectDocument(document);

  if (validation.errors.length > 0) {
    throw new Error(
      `Project document has ${validation.errors.length} validation error(s): ${formatSceneDiagnosticSummary(validation.errors)}`
    );
  }
}
