# Deployment Schema - Docker Compose and Kubernetes deployment configurations
# Version: 1.0.0

{
  # Docker Compose configuration
  DockerComposeConfig = {
    enabled
      | Bool
      | doc "Enable Docker Compose deployment"
      | default = true,

    version
      | [| 'v3_8, 'v3_9 |]
      | doc "Docker Compose file format version (v3_8 = 3.8, v3_9 = 3.9)"
      | default = 'v3_8,

    project_name
      | String
      | doc "Docker Compose project name"
      | optional,

    env_file
      | String
      | doc "Path to environment file"
      | default = ".env",

    profiles
      | Array String
      | doc "Docker Compose profiles to enable"
      | default = [],

    extends
      | {
        file
          | String
          | doc "Path to base compose file",

        service
          | String
          | doc "Service to extend",
      }
      | doc "Extend from another compose file"
      | optional,
  },

  # Kubernetes namespace configuration
  KubernetesNamespace = {
    name
      | String
      | doc "Namespace name"
      | {
        label = "valid namespace",
        predicate = fun s =>
          std.string.is_match "^[a-z0-9-]+$" s &&
          std.string.length s >= 1 && std.string.length s <= 63
      },

    labels
      | {_: String}
      | doc "Namespace labels"
      | default = {},

    annotations
      | {_: String}
      | doc "Namespace annotations"
      | default = {},
  },

  # Kubernetes Ingress configuration
  IngressRule = {
    host
      | String
      | doc "Hostname for the rule"
      | optional,

    http
      | {
        paths
          | Array {
            path
              | String
              | doc "URL path pattern",

            path_type
              | [| 'Prefix, 'Exact, 'ImplementationSpecific |]
              | doc "Path matching type"
              | default = 'Prefix,

            backend
              | {
                service
                  | {
                    name
                      | String
                      | doc "Service name",

                    port
                      | {
                        number
                          | Number
                          | doc "Service port number"
                          | optional,

                        name
                          | String
                          | doc "Service port name"
                          | optional,
                      }
                      | doc "Service port",
                  }
                  | doc "Service backend",
              }
              | doc "Backend configuration",
          }
          | doc "HTTP path rules",
      }
      | doc "HTTP routing rules",
  },

  IngressConfig = {
    enabled
      | Bool
      | doc "Enable Ingress resource"
      | default = false,

    name
      | String
      | doc "Ingress name"
      | {
        label = "valid name",
        predicate = fun s =>
          std.string.is_match "^[a-z0-9-]+$" s &&
          std.string.length s >= 1 && std.string.length s <= 63
      }
      | optional,

    class_name
      | String
      | doc "Ingress class name (e.g., 'nginx', 'traefik')"
      | default = "nginx",

    rules
      | Array IngressRule
      | doc "Ingress routing rules"
      | default = [],

    tls
      | Array {
        hosts
          | Array String
          | doc "Hosts covered by TLS certificate",

        secret_name
          | String
          | doc "Name of secret containing TLS cert/key"
          | optional,
      }
      | doc "TLS configuration"
      | default = [],

    annotations
      | {_: String}
      | doc "Ingress annotations"
      | default = {},
  },

  # Kubernetes Service configuration
  KubernetesServiceConfig = {
    type
      | [| 'ClusterIP, 'NodePort, 'LoadBalancer, 'ExternalName |]
      | doc "Kubernetes Service type"
      | default = 'ClusterIP,

    cluster_ip
      | String
      | doc "Cluster IP address (for ClusterIP type)"
      | optional,

    external_ips
      | Array String
      | doc "External IP addresses"
      | default = [],

    load_balancer_ip
      | String
      | doc "LoadBalancer IP address"
      | optional,

    load_balancer_source_ranges
      | Array String
      | doc "Allowed source IP ranges for LoadBalancer"
      | default = [],

    external_traffic_policy
      | [| 'Cluster, 'Local |]
      | doc "External traffic policy"
      | optional,

    session_affinity
      | [| 'None, 'ClientIP |]
      | doc "Session affinity"
      | default = 'None,

    annotations
      | {_: String}
      | doc "Service annotations"
      | default = {},
  },

  # Kubernetes Deployment strategy
  DeploymentStrategy = {
    type
      | [| 'RollingUpdate, 'Recreate |]
      | doc "Deployment strategy type"
      | default = 'RollingUpdate,

    rolling_update
      | {
        max_surge
          | String
          | doc "Max additional pods during update (number or percentage)"
          | default = "25%",

        max_unavailable
          | String
          | doc "Max unavailable pods during update (number or percentage)"
          | default = "25%",
      }
      | doc "Rolling update strategy parameters"
      | optional,
  },

  # Kubernetes HorizontalPodAutoscaler
  HpaConfig = {
    enabled
      | Bool
      | doc "Enable Horizontal Pod Autoscaler"
      | default = false,

    min_replicas
      | Number
      | doc "Minimum number of replicas"
      | {
        label = "valid min replicas",
        predicate = fun n => n >= 1 && n <= 100
      }
      | default = 1,

    max_replicas
      | Number
      | doc "Maximum number of replicas"
      | {
        label = "valid max replicas",
        predicate = fun n => n >= 1 && n <= 100
      }
      | default = 10,

    target_cpu_utilization
      | Number
      | doc "Target CPU utilization percentage (0-100)"
      | {
        label = "valid CPU utilization",
        predicate = fun n => n > 0 && n <= 100
      }
      | default = 80,

    target_memory_utilization
      | Number
      | doc "Target memory utilization percentage (0-100)"
      | {
        label = "valid memory utilization",
        predicate = fun n => n > 0 && n <= 100
      }
      | optional,

    custom_metrics
      | Array {
        type
          | [| 'Pods, 'Object, 'External |]
          | doc "Metric type",

        metric_name
          | String
          | doc "Metric name",

        target_value
          | String
          | doc "Target value for the metric",
      }
      | doc "Custom metrics for autoscaling"
      | default = [],
  },

  # Kubernetes ConfigMap
  ConfigMapConfig = {
    name
      | String
      | doc "ConfigMap name"
      | {
        label = "valid name",
        predicate = fun s =>
          std.string.is_match "^[a-z0-9-]+$" s &&
          std.string.length s >= 1 && std.string.length s <= 63
      },

    data
      | {_: String}
      | doc "Configuration data as key-value pairs"
      | default = {},

    binary_data
      | {_: String}
      | doc "Binary data (base64 encoded)"
      | default = {},

    from_files
      | Array String
      | doc "Paths to files to include in ConfigMap"
      | default = [],
  },

  # Main Kubernetes configuration
  KubernetesConfig = {
    enabled
      | Bool
      | doc "Enable Kubernetes deployment"
      | default = false,

    namespace
      | String
      | doc "Target namespace for deployments"
      | {
        label = "valid namespace",
        predicate = fun s =>
          std.string.is_match "^[a-z0-9-]+$" s &&
          std.string.length s >= 1 && std.string.length s <= 63
      }
      | default = "default",

    create_namespace
      | Bool
      | doc "Create namespace if it doesn't exist"
      | default = false,

    namespace_config
      | KubernetesNamespace
      | doc "Namespace configuration"
      | optional,

    service
      | KubernetesServiceConfig
      | doc "Kubernetes Service configuration"
      | default = {type = 'ClusterIP},

    ingress
      | IngressConfig
      | doc "Ingress configuration"
      | default = {enabled = false},

    deployment_strategy
      | DeploymentStrategy
      | doc "Deployment strategy"
      | default = {type = 'RollingUpdate},

    hpa
      | HpaConfig
      | doc "Horizontal Pod Autoscaler configuration"
      | default = {enabled = false},

    configmaps
      | Array ConfigMapConfig
      | doc "ConfigMaps to create"
      | default = [],

    pod_annotations
      | {_: String}
      | doc "Annotations for pod template"
      | default = {},

    pod_labels
      | {_: String}
      | doc "Labels for pod template"
      | default = {},

    service_account
      | String
      | doc "Service account name for pods"
      | optional,

    image_pull_secrets
      | Array String
      | doc "Names of secrets for pulling images"
      | default = [],

    node_selector
      | {_: String}
      | doc "Node selector for pod scheduling"
      | default = {},

    tolerations
      | Array {
        key
          | String
          | doc "Toleration key"
          | optional,

        operator
          | [| 'Exists, 'Equal |]
          | doc "Toleration operator"
          | default = 'Equal,

        value
          | String
          | doc "Toleration value"
          | optional,

        effect
          | [| 'NoSchedule, 'PreferNoSchedule, 'NoExecute |]
          | doc "Toleration effect"
          | optional,

        toleration_seconds
          | Number
          | doc "Seconds before eviction (for NoExecute)"
          | optional,
      }
      | doc "Pod tolerations"
      | default = [],

    affinity
      | {
        node_affinity
          | {_: _}
          | doc "Node affinity rules"
          | optional,

        pod_affinity
          | {_: _}
          | doc "Pod affinity rules"
          | optional,

        pod_anti_affinity
          | {_: _}
          | doc "Pod anti-affinity rules"
          | optional,
      }
      | doc "Pod affinity/anti-affinity"
      | optional,
  },

  # Main deployment configuration
  DeploymentConfig = {
    docker_compose
      | DockerComposeConfig
      | doc "Docker Compose deployment configuration"
      | optional,

    kubernetes
      | KubernetesConfig
      | doc "Kubernetes deployment configuration"
      | optional,

    target
      | [| 'docker, 'kubernetes, 'both |]
      | doc "Deployment target platform"
      | default = 'docker,
  },
}
