///|
/// Theme selection intent. `ThemeSpec` expresses what the user *wants*
/// (preset, light/dark/system, density, contrast, seed, reduced motion); the
/// `ThemeResolver` turns a spec plus the actual system color scheme into a
/// fully resolved, drawable `Theme`. This split fixes the old
/// `Environment::with_color_scheme` bug where flipping the scheme flag did not
/// rebuild the palette/surfaces/shadows.

///|
/// Which design-system preset the user selected. `core` only resolves
/// `Minimal` itself; branded presets (Material/Carbon/Primer/Fluent) are
/// resolved by the `moui_theme` addon, which produces a complete `@core.Theme`
/// (including `components`). The enum lives in `core` so `Environment` can
/// record the user's choice without `core` depending on the addon.
pub(all) enum ThemePreset {
  Minimal
  Material
  Carbon
  Primer
  Fluent
} derive(Eq, Debug, ToJson)

///|
/// Color mode: force light, force dark, or follow the system.
pub(all) enum ColorMode {
  Light
  Dark
  System
} derive(Eq, Debug, ToJson)

///|
/// Density tier. `Compact` shrinks spacing by ~18%, `Comfortable` grows it by
/// ~18%; `Standard` is 1.0.
pub(all) enum ThemeDensity {
  Compact
  Standard
  Comfortable
} derive(Eq, Debug, ToJson)

///|
pub fn ThemeDensity::label(self : ThemeDensity) -> String {
  match self {
    Compact => "compact"
    Standard => "standard"
    Comfortable => "comfortable"
  }
}

///|
pub fn ThemeDensity::multiplier(self : ThemeDensity) -> Double {
  match self {
    Compact => 0.82
    Standard => 1.0
    Comfortable => 1.18
  }
}

///|
/// User theme intent. Built by app code (or by a branded addon helper) and
/// stored on `Environment.theme_spec`; the resolver consumes it whenever the
/// system scheme changes so a `ThemeChanged` event rebuilds the full theme.
pub(all) struct ThemeSpec {
  preset : ThemePreset
  color_mode : ColorMode
  density : ThemeDensity
  contrast : AccessibilityContrast
  // Brand seed color. `None` keeps the preset's default primary; `Some(c)`
  // overrides the primary family. `core` only applies this for `Minimal`;
  // branded addons may use it to seed their own palette generation.
  seed : Color?
  reduced_motion : Bool
} derive(Eq, Debug, ToJson)

///|
/// Default spec: MoUI Minimal, follow the system, standard density, standard
/// contrast, no seed, full motion.
pub fn ThemeSpec::default() -> ThemeSpec {
  {
    preset: ThemePreset::Minimal,
    color_mode: ColorMode::System,
    density: ThemeDensity::Standard,
    contrast: AccessibilityContrast::Standard,
    seed: None,
    reduced_motion: false,
  }
}

///|
/// Minimal-light spec (forced light, used by the legacy `light_theme()` helper).
pub fn ThemeSpec::minimal_light() -> ThemeSpec {
  { ..ThemeSpec::default(), preset: Minimal, color_mode: ColorMode::Light }
}

///|
/// Minimal-dark spec (forced dark, used by the legacy `dark_theme()` helper).
pub fn ThemeSpec::minimal_dark() -> ThemeSpec {
  { ..ThemeSpec::default(), preset: Minimal, color_mode: ColorMode::Dark }
}

///|
/// Resolve the effective color scheme for a spec given the current system
/// scheme. `System` defers to the platform; `Light`/`Dark` override it.
pub fn ThemeSpec::resolve_scheme(
  self : ThemeSpec,
  system_scheme : ColorScheme,
) -> ColorScheme {
  match self.color_mode {
    Light => Light
    Dark => Dark
    System => system_scheme
  }
}

///|
pub fn ThemeSpec::with_preset(
  self : ThemeSpec,
  preset : ThemePreset,
) -> ThemeSpec {
  { ..self, preset, }
}

///|
pub fn ThemeSpec::with_color_mode(
  self : ThemeSpec,
  color_mode : ColorMode,
) -> ThemeSpec {
  { ..self, color_mode, }
}

///|
pub fn ThemeSpec::with_density(
  self : ThemeSpec,
  density : ThemeDensity,
) -> ThemeSpec {
  { ..self, density, }
}

///|
pub fn ThemeSpec::with_contrast(
  self : ThemeSpec,
  contrast : AccessibilityContrast,
) -> ThemeSpec {
  { ..self, contrast, }
}

///|
pub fn ThemeSpec::with_seed(self : ThemeSpec, seed : Color?) -> ThemeSpec {
  { ..self, seed, }
}

///|
pub fn ThemeSpec::with_reduced_motion(
  self : ThemeSpec,
  reduced_motion : Bool,
) -> ThemeSpec {
  { ..self, reduced_motion, }
}