# Unified Site Configuration Contracts
#
# Type contracts for site.ncl — validates the complete site configuration
# including site metadata, paths, themes, content types, and routes with
# embedded multilingual menu data.
#
# JSON output of site.ncl is deserialized by build_config::site_config::UnifiedSiteConfig.

{
  SiteMetadata = {
    name
      | String
      | doc "Site display name",

    languages
      | Array String
      | doc "Supported language codes (ISO 639-1, e.g. ['en', 'es'])",

    default_language
      | String
      | doc "Default language code when none is specified in URL",
  },

  SitePaths = {
    i18n
      | String
      | doc "Path to i18n/FTL locales directory",

    content
      | String
      | doc "Path to content directory",

    themes
      | String
      | doc "Path to themes configuration directory",

    assets
      | String
      | doc "Path to public assets directory",

    migrations
      | String
      | doc "Path to SQL migration files directory (server-only)"
      | optional,

    email_templates
      | String
      | doc "Path to email template files directory (server-only)"
      | optional,

    work
      | String
      | doc "Path to work-in-progress / staging assets directory (implementation-specific)"
      | optional,
  },

  ThemeConfig = {
    default
      | String
      | doc "Default theme name",

    available
      | Array String
      | doc "List of available theme names",
  },

  ContentTypeFeatures = {
    style_mode
      | String
      | doc "Display style: 'row' or 'grid'",

    use_feature
      | Bool
      | doc "Enable featured content at top of index",

    use_categories
      | Bool
      | default = true,

    use_tags
      | Bool
      | default = true,

    use_emojis
      | Bool
      | default = false,

    cta_view
      | String
      | doc "CTA component name (e.g. 'BlogCTAView')",

    default_page_size
      | Number
      | default = 10,

    # Allow additional feature fields without breaking the contract
    ..
  },

  ContentType = {
    name
      | String
      | doc "Content type identifier (e.g. 'blog', 'recipes')",

    directory
      | String
      | doc "Directory name under content path",

    enabled
      | Bool
      | default = true,

    features
      | ContentTypeFeatures
      | doc "Content display and pagination settings",
  },

  # Database connection configuration.
  # Structural settings (type, path, pool sizing) belong here.
  # Credentials and full overrides go in .env via DATABASE_URL.
  DatabaseConfig = {
    url
      | String
      | doc "Database connection URL (e.g. 'sqlite:data/dev.db' or 'postgres://...')",

    create_if_missing
      | Bool
      | doc "Create the SQLite database file if it does not exist"
      | default = true,

    max_connections
      | Number
      | doc "Maximum number of connections in the pool"
      | default = 5,

    min_connections
      | Number
      | doc "Minimum number of idle connections in the pool"
      | default = 1,

    connect_timeout
      | Number
      | doc "Connection acquisition timeout in seconds"
      | default = 30,

    idle_timeout
      | Number
      | doc "Maximum idle connection duration in seconds"
      | default = 600,

    max_lifetime
      | Number
      | doc "Maximum connection lifetime in seconds"
      | default = 1800,
  },

  # Footer metadata — absorbed inline into SiteConfig.
  FooterMetadata = {
    title
      | String
      | doc "Footer title (language-neutral, e.g. author name)",

    company_desc
      | { _ : String }
      | doc "Company description keyed by language code",

    copyright_text
      | { _ : String }
      | doc "Copyright notice keyed by language code",

    social_links
      | Array {
          name      | String,
          url       | String,
          icon      | String,
        }
      | default = [],
  },

  # Menu configuration embedded directly in Route.
  # At least one of label_key or labels must be present (validated by Nickel contracts
  # plus runtime assertion in Rust loader).
  MenuEntry = {
    enabled
      | Bool
      | doc "Whether this route appears in navigation"
      | default = false,

    order
      | Number
      | doc "Display order (lower = first)"
      | optional,

    icon
      | String
      | doc "Icon identifier (e.g. 'home', 'fas fa-user')"
      | optional,

    label_key
      | String
      | doc "Primary: FTL i18n key for label (e.g. 'nav-home')"
      | optional,

    labels
      | { _ : String }
      | doc "Fallback inline labels keyed by language code"
      | optional,

    visible_in
      | Array String
      | doc "Language codes this item is visible in. Empty = all languages."
      | default = [],

    use_in
      | Array String
      | doc "Navigation zones: ['header'], ['footer'], or ['header','footer']"
      | default = ["header"],
  },

  # A unified route entry covering all languages in a single record.
  # paths maps language code → URL path (e.g. { en = '/', es = '/inicio' }).
  Route = {
    component
      | String
      | doc "Page component name (e.g. 'HomePage', 'ContentIndex')",

    paths
      | { _ : String }
      | doc "URL paths keyed by language code",

    priority
      | Number
      | doc "SEO/sitemap priority (0.0–1.0)"
      | default = 0.8,

    content_type
      | String
      | doc "Content type for dynamic routes (e.g. 'blog')"
      | optional,

    menu
      | MenuEntry
      | doc "Navigation menu configuration for this route",

    props
      | { _ : Dyn }
      | doc "Additional route-specific properties passed to component"
      | optional,

  },

  LogoConfig = {
    light_src
      | String
      | doc "Path to light-mode logo image",

    dark_src
      | String
      | doc "Path to dark-mode logo image (empty string disables dark variant)",

    alt
      | String
      | doc "Alt text for the logo image",

    show_in_nav
      | Bool
      | doc "Whether to show the logo in the navigation bar",

    show_in_footer
      | Bool
      | doc "Whether to show the logo in the footer",

    width
      | optional
      | doc "Optional logo width (CSS value or null)",

    height
      | optional
      | doc "Optional logo height (CSS value or null)",
  },

  SiteConfig = {
    site
      | SiteMetadata,

    paths
      | SitePaths,

    themes
      | ThemeConfig,

    logo
      | LogoConfig,

    content_types
      | Array ContentType,

    database
      | DatabaseConfig
      | doc "Database connection and pool configuration",

    footer
      | FooterMetadata,

    routes
      | Array Route,
  },
}
