# Execution Mode Contracts - Contract Definitions
# Provides type contracts for all execution mode schemas

let lib = import "../lib/main.ncl" in
let oci_contracts = import "../oci_registry/contracts.ncl" in

{
  # Authentication type enum (documented via comments)
  # Values: "none" | "token" | "mtls" | "oauth" | "kms"
  AuthType = fun label value =>
    if std.array.elem value ["none", "token", "mtls", "oauth", "kms"] then
      value
    else
      std.contract.blame_with_message "auth_type must be one of: none, token, mtls, oauth, kms" label,

  # Deployment type enum
  # Values: "local" | "remote" | "k8s" | "disabled"
  DeploymentType = fun label value =>
    if std.array.elem value ["local", "remote", "k8s", "disabled"] then
      value
    else
      std.contract.blame_with_message "deployment must be one of: local, remote, k8s, disabled" label,

  # Mode name enum
  # Values: "solo" | "multi-user" | "cicd" | "enterprise"
  ModeName = fun label value =>
    if std.array.elem value ["solo", "multi-user", "cicd", "enterprise"] then
      value
    else
      std.contract.blame_with_message "mode_name must be one of: solo, multi-user, cicd, enterprise" label,

  # Extension source enum
  # Values: "local" | "gitea" | "oci" | "mixed"
  ExtensionSource = fun label value =>
    if std.array.elem value ["local", "gitea", "oci", "mixed"] then
      value
    else
      std.contract.blame_with_message "source must be one of: local, gitea, oci, mixed" label,

  # Locking strategy enum
  # Values: "disabled" | "enabled" | "required"
  LockingStrategy = fun label value =>
    if std.array.elem value ["disabled", "enabled", "required"] then
      value
    else
      std.contract.blame_with_message "locking must be one of: disabled, enabled, required" label,

  # Git integration enum
  # Values: "disabled" | "optional" | "required"
  GitIntegration = fun label value =>
    if std.array.elem value ["disabled", "optional", "required"] then
      value
    else
      std.contract.blame_with_message "git_integration must be one of: disabled, optional, required" label,

  # Isolation level enum
  # Values: "none" | "user" | "strict"
  IsolationLevel = fun label value =>
    if std.array.elem value ["none", "user", "strict"] then
      value
    else
      std.contract.blame_with_message "isolation must be one of: none, user, strict" label,

  # DNS modification enum
  # Values: "none" | "coredns" | "system"
  DnsModification = fun label value =>
    if std.array.elem value ["none", "coredns", "system"] then
      value
    else
      std.contract.blame_with_message "dns_modification must be one of: none, coredns, system" label,

  # Token format enum
  # Values: "jwt" | "opaque"
  TokenFormat = fun label value =>
    if std.array.elem value ["jwt", "opaque"] then
      value
    else
      std.contract.blame_with_message "token_format must be one of: jwt, opaque" label,

  # Image pull policy enum
  # Values: "Always" | "IfNotPresent" | "Never"
  ImagePullPolicy = fun label value =>
    if std.array.elem value ["Always", "IfNotPresent", "Never"] then
      value
    else
      std.contract.blame_with_message "image_pull_policy must be one of: Always, IfNotPresent, Never" label,

  TokenConfig = {
    token_path | String,
    token_format | TokenFormat | optional = "jwt",
    expiry_seconds | lib.PositiveNumber | optional = 86400,
    refresh_enabled | Bool | optional = true,
  },

  MTLSConfig = {
    client_cert_path | String,
    client_key_path | String,
    ca_cert_path | String,
    verify_server | Bool | optional = true,
  },

  OAuthConfig = {
    provider_url | String,
    client_id | String,
    client_secret_path | String,
    scopes | Array String | optional = ["read", "write"],
    redirect_uri | String | optional,
  },

  AuthenticationStrategy = {
    auth_type | AuthType,
    token_config | TokenConfig | optional,
    mtls_config | MTLSConfig | optional,
    oauth_config | OAuthConfig | optional,
    ssh_key_storage | String | optional = "local",
  },

  HealthCheck = {
    enabled | Bool | optional = true,
    endpoint | String | optional = "/health",
    interval | lib.PositiveNumber | optional = 10,
    timeout | lib.PositiveNumber | optional = 5,
    healthy_threshold | lib.PositiveNumber | optional = 2,
    unhealthy_threshold | lib.PositiveNumber | optional = 3,
  },

  LocalServiceConfig = {
    binary_path | String | optional,
    config_path | String | optional,
    data_dir | String,
    port | lib.PortNumber,
    bind_address | String | optional = "127.0.0.1",
    tls_enabled | Bool | optional = false,
  },

  RemoteServiceConfig = {
    endpoint | String,
    port | lib.PortNumber | optional,
    tls_enabled | Bool | optional = true,
    verify_ssl | Bool | optional = true,
    timeout | lib.PositiveNumber | optional = 30,
    retries | lib.PositiveNumber | optional = 3,
  },

  K8sResources = {
    cpu_request | String | optional = "100m",
    cpu_limit | String | optional = "500m",
    memory_request | String | optional = "128Mi",
    memory_limit | String | optional = "512Mi",
  },

  K8sServiceConfig = {
    namespace | String | optional = "provisioning",
    deployment_name | String,
    service_name | String,
    replicas | lib.PositiveNumber | optional = 1,
    image | String,
    image_pull_policy | ImagePullPolicy | optional = "IfNotPresent",
    resources | K8sResources | optional,
  },

  ServiceConfig = {
    deployment | DeploymentType,
    local_config | LocalServiceConfig | optional,
    remote_config | RemoteServiceConfig | optional,
    k8s_config | K8sServiceConfig | optional,
    auto_start | Bool | optional = false,
    health_check | HealthCheck | optional,
  },

  ServiceDeployments = {
    orchestrator | ServiceConfig,
    control_center | ServiceConfig | optional,
    coredns | ServiceConfig | optional,
    gitea | ServiceConfig | optional,
    oci_registry | oci_contracts.OCIRegistryConfig,
    custom_services | {_: ServiceConfig} | optional,
  },

  GiteaConfig = {
    url | String,
    organization | String | optional = "provisioning",
    username | String | optional,
    token_path | String | optional,
    verify_ssl | Bool | optional = true,
  },

  OCIExtensionConfig = {
    enabled | Bool | optional = true,
    endpoint | String,
    namespace | String | optional = "provisioning-extensions",
    auth_token_path | String | optional,
    tls_enabled | Bool | optional = true,
    verify_ssl | Bool | optional = true,
    cache_dir | String | optional = "~/.provisioning/oci-cache",
  },

  ExtensionConfig = {
    source | ExtensionSource,
    local_path | String | optional,
    gitea_config | GiteaConfig | optional,
    oci_registry | OCIExtensionConfig | optional,
    allow_mixed | Bool | optional = false,
  },

  WorkspacePolicy = {
    locking | LockingStrategy,
    lock_provider | String | optional,
    git_integration | GitIntegration,
    isolation | IsolationLevel | optional = "user",
    max_workspaces_per_user | lib.PositiveNumber | optional,
  },

  SecurityConfig = {
    encryption_at_rest | Bool | optional = false,
    encryption_in_transit | Bool | optional = false,
    secret_provider | {..} | optional,
    dns_modification | DnsModification | optional = "none",
    audit_logging | Bool | optional = false,
    audit_log_path | String | optional,
    network_isolation | Bool | optional = false,
  },

  ResourceLimits = {
    max_servers_per_user | lib.PositiveNumber | optional = 10,
    max_cpu_cores_per_user | lib.PositiveNumber | optional = 32,
    max_memory_gb_per_user | lib.PositiveNumber | optional = 128,
    max_storage_gb_per_user | lib.PositiveNumber | optional = 500,
    max_total_servers | lib.PositiveNumber | optional,
    max_total_cpu_cores | lib.PositiveNumber | optional,
    max_total_memory_gb | lib.PositiveNumber | optional,
  },

  ExecutionMode = {
    mode_name | ModeName,
    description | String,
    authentication | AuthenticationStrategy,
    services | ServiceDeployments,
    extensions | ExtensionConfig,
    workspaces | WorkspacePolicy,
    security | SecurityConfig,
    resource_limits | ResourceLimits | optional,
  },
}
