# Rustelo Implementation Dependency Contracts
#
# Schema for rustelo.deps.ncl — declares which framework artifacts this
# implementation uses, overrides, or replaces with local implementations.
#
# NOTE: Cargo dependencies (crate versions, features) are NOT declared here.
#       Only artifact resolution: pages, components, i18n and Nickel config
#       layering — things Cargo cannot express.
#
# NOTE: This file will move to rustelo/nickel/deps/contracts.ncl once the
#       framework/implementation boundary is formalized.

let ValidArtifactSource = std.contract.from_predicate (fun s =>
  s == "framework" || s == "local" || s == "override"
) in

let ValidFrameworkStrategy = std.contract.from_predicate (fun s =>
  s == "path" || s == "git" || s == "crates.io"
) in

let ValidI18nStrategy = std.contract.from_predicate (fun s =>
  s == "merge" || s == "replace" || s == "framework-only"
) in

let ValidNickelStrategy = std.contract.from_predicate (fun s =>
  s == "merge" || s == "replace"
) in

{
  # ---------------------------------------------------------------------------
  # Framework source declaration
  # ---------------------------------------------------------------------------

  FrameworkSource = {
    strategy
      | String
      | ValidFrameworkStrategy
      | doc "How the framework is referenced: 'path' | 'git' | 'crates.io'",

    path
      | String
      | doc "Relative path to local framework root (required when strategy = 'path')"
      | optional,

    git
      | String
      | doc "Git repository URL (required when strategy = 'git')"
      | optional,

    branch
      | String
      | doc "Git branch or tag (only when strategy = 'git')"
      | optional,
  },

  # ---------------------------------------------------------------------------
  # Artifact source — how a single page or component is resolved
  # ---------------------------------------------------------------------------

  ArtifactSource = {
    source
      | String
      | ValidArtifactSource
      | doc "Origin: 'framework' | 'local' | 'override'",

    # Required when source = 'local'
    crate
      | String
      | doc "Cargo crate name containing the component (e.g. 'website-pages')"
      | optional,

    component
      | String
      | doc "Rust struct/component name (e.g. 'Services', 'WorkRequest')"
      | optional,

    # Required when source = 'override'
    path
      | String
      | doc "Relative path to the override file (e.g. 'crates/server/src/shell.rs')"
      | optional,
  },

  # ---------------------------------------------------------------------------
  # i18n layering strategy
  # ---------------------------------------------------------------------------

  I18nConfig = {
    strategy
      | String
      | ValidI18nStrategy
      | doc "How FTL bundles are composed: 'merge' | 'replace' | 'framework-only'",

    extend
      | String
      | doc "Path to implementation FTL directory merged on top of framework bundles"
      | optional,
  },

  # ---------------------------------------------------------------------------
  # Nickel config layering strategy
  # ---------------------------------------------------------------------------

  NickelConfig = {
    strategy
      | String
      | ValidNickelStrategy
      | doc "How site config is composed: 'merge' | 'replace'",

    entry
      | String
      | doc "Path to implementation config entry point (e.g. 'site/config/index.ncl')",
  },

  # ---------------------------------------------------------------------------
  # Build generation controls
  # ---------------------------------------------------------------------------

  BuildConfig = {
    generate_routing
      | Bool
      | doc "Generate server_routing.rs and client_routes.rs from declared pages + config"
      | default = true,

    generate_page_provider
      | Bool
      | doc "Generate page_provider_impl.rs from declared pages"
      | default = true,

    generate_shell
      | Bool
      | doc "Generate shell.rs from framework template (set false when shell = 'override')"
      | default = true,

    generate_resource_registry
      | Bool
      | doc "Generate resource_registry.rs for menus, themes, FTL registries"
      | default = true,

    generate_migrations
      | Bool
      | doc "Include framework base migrations alongside implementation migrations"
      | default = true,
  },

  # ---------------------------------------------------------------------------
  # Top-level contract
  # ---------------------------------------------------------------------------

  RusteloImplDeps = {
    framework
      | FrameworkSource
      | doc "How this implementation depends on the Rustelo framework",

    pages
      | { _ : ArtifactSource }
      | doc "Page artifact resolution: which pages come from framework vs local",

    components
      | { _ : ArtifactSource }
      | doc "Component overrides (omit to use framework components directly)"
      | default = {},

    i18n
      | I18nConfig
      | doc "FTL translation bundle layering strategy",

    config
      | NickelConfig
      | doc "Nickel site config layering strategy",

    build
      | BuildConfig
      | doc "Build-time code generation controls"
      | default = {
          generate_routing = true,
          generate_page_provider = true,
          generate_shell = true,
          generate_resource_registry = true,
          generate_migrations = true,
        },
  },
}
