/// A complete, validated set of delivery defaults for one runtime target.
///
/// The selector keeps atlas, engine, quality, and manifest settings together
/// so a build cannot accidentally mix a mobile atlas with a desktop runtime.
/// The values are chosen from the curated presets exposed by this package.

///|
pub struct DeliveryProfiles {
  atlas : AtlasProfile
  engine : EngineProfile
  quality : QualityProfile
  runtime : RuntimePreset
} derive(Debug, Eq, ToJson, FromJson)

/// Select the first compatible delivery configuration for a sheet.
///
/// `mobile` controls the atlas family, while `target` controls both the
/// engine limits and the output manifest. An unknown quality name returns
/// `None` instead of silently falling back to a permissive quality gate.

///|
pub fn select_delivery_profiles(
  sheet : SpriteSheet,
  target~ : RuntimeTarget,
  mobile~ : Bool,
  quality~ : String,
) -> DeliveryProfiles? {
  let atlas = best_atlas_profile(sheet, mobile)
  let engine = best_engine_profile(sheet, target)
  let quality_profile = quality_profile_named(quality)
  let runtime = runtime_presets_for(target).get(0)
  match (atlas, engine, quality_profile, runtime) {
    (Some(atlas), Some(engine), Some(quality), Some(runtime)) => {
      let selection = { atlas, engine, quality, runtime }
      if profile_selection_is_compatible(selection) {
        Some(selection)
      } else {
        None
      }
    }
    _ => None
  }
}

/// Check cross-profile invariants that are independent of a concrete sheet.

///|
pub fn profile_selection_is_compatible(selection : DeliveryProfiles) -> Bool {
  selection.engine.target == selection.runtime.target &&
  selection.atlas.max_width <= selection.engine.max_texture &&
  selection.engine.max_frames > 0 &&
  selection.atlas.padding >= 0 &&
  selection.runtime.extension != ""
}

/// Return a stable, human-readable summary suitable for build logs.

///|
pub fn profile_selection_summary(selection : DeliveryProfiles) -> String {
  "atlas=" +
  selection.atlas.name +
  ", engine=" +
  selection.engine.name +
  ", quality=" +
  selection.quality.name +
  ", runtime=" +
  target_name(selection.runtime.target)
}

/// Convert the selected atlas and runtime settings into workflow options.

///|
pub fn DeliveryProfiles::workflow_options(
  self : DeliveryProfiles,
  name : String,
) -> WorkflowOptions {
  let mode = if self.quality.name == "development" {
    Development
  } else {
    Release
  }
  {
    name,
    mode,
    atlas_strategy: self.atlas.strategy,
    max_width: self.atlas.max_width,
    padding: self.atlas.padding,
    runtime: self.runtime.target,
    include_diagnostics: self.quality.require_tags ||
    self.quality.max_warnings > 0,
  }
}

/// Return runtime export options matching the selected manifest preset.

///|
pub fn DeliveryProfiles::runtime_options(
  self : DeliveryProfiles,
) -> RuntimeOptions {
  self.runtime.options()
}

/// Return the names in a stable order for logs, caches, and snapshot tests.

///|
pub fn DeliveryProfiles::names(self : DeliveryProfiles) -> Array[String] {
  [self.atlas.name, self.engine.name, self.quality.name, self.runtime.name]
}

/// Select a target-specific configuration and build its workflow in one step.

///|
pub fn build_delivery_workflow(
  sheet : SpriteSheet,
  name : String,
  target~ : RuntimeTarget,
  mobile~ : Bool,
  quality~ : String,
) -> WorkflowReport? {
  match select_delivery_profiles(sheet, target~, mobile~, quality~) {
    Some(selection) =>
      Some(build_workflow(sheet, selection.workflow_options(name)))
    None => None
  }
}

/// List profile sets that can accept a sheet for a target.
///
/// This is useful to UIs that want to show valid deployment choices before
/// asking the user to select a quality gate.

///|
pub fn compatible_delivery_targets(
  sheet : SpriteSheet,
  mobile~ : Bool,
) -> Array[RuntimeTarget] {
  runtime_targets().filter(fn(target) {
    engine_profiles_for(target).any(fn(engine) {
      engine.usable_for(sheet) &&
      atlas_profiles().any(fn(atlas) {
        atlas.mobile == mobile &&
        atlas.fits(sheet) &&
        atlas.max_width <= engine.max_texture
      })
    })
  })
}