# Infrastructure - Kubernetes Schema
# Defines type-safe Kubernetes manifest configuration
# Validates Deployments, Services, ConfigMaps, and resource constraints

{
  # Kubernetes resource limits and requests
  ResourceQuantity = {
    cpu | String | optional,
    memory | String | optional,
    storage | String | optional,
  },

  # Container port specification
  ContainerPort = {
    name | String | optional,
    container_port | Number,
    protocol | [| 'TCP, 'UDP |] | default = 'TCP',
  },

  # Container resource constraints
  ContainerResources = {
    requests | ResourceQuantity | doc "Minimum resources" | default = {},
    limits | ResourceQuantity | doc "Maximum resources" | default = {},
  },

  # Environment variable reference
  EnvVarSource = {
    field_path | String | optional,
    config_map_key_ref | {
      name | String,
      key | String,
    } | optional,
    secret_key_ref | {
      name | String,
      key | String,
    } | optional,
  },

  # Environment variable
  EnvVar = {
    name | String,
    value | String | optional,
    value_from | EnvVarSource | optional,
  },

  # Liveness and readiness probes
  Probe = {
    exec | {
      command | Array String,
    } | optional,
    http_get | {
      path | String,
      port | Number,
      scheme | [| 'HTTP, 'HTTPS |] | default = 'HTTP',
    } | optional,
    tcp_socket | {
      port | Number,
    } | optional,
    initial_delay_seconds | Number | default = 10,
    timeout_seconds | Number | default = 5,
    period_seconds | Number | default = 10,
    success_threshold | Number | default = 1,
    failure_threshold | Number | default = 3,
  },

  # Container specification
  Container = {
    name | String,
    image | String,
    image_pull_policy | [| 'Always, 'Never, 'IfNotPresent |] | default = 'IfNotPresent',
    ports | Array ContainerPort | default = [],
    env | Array EnvVar | default = [],
    resources | ContainerResources | default = {
      requests = {},
      limits = {},
    },
    liveness_probe | Probe | optional,
    readiness_probe | Probe | optional,
    volume_mounts | Array {
      name | String,
      mount_path | String,
      read_only | Bool | default = false,
    } | default = [],
  },

  # Pod template specification
  PodTemplateSpec = {
    metadata | {
      labels | {_ | String} | default = {},
      annotations | {_ | String} | default = {},
    } | default = {
      labels = {},
      annotations = {},
    },
    spec = {
      containers | Array Container,
      restart_policy | [| 'Always, 'OnFailure, 'Never |] | default = 'Always',
      termination_grace_period_seconds | Number | default = 30,
      volumes | Array {
        name | String,
        config_map | {
          name | String,
          optional | Bool | default = false,
        } | optional,
        secret | {
          secret_name | String,
          optional | Bool | default = false,
        } | optional,
      } | default = [],
      node_selector | {_ | String} | default = {},
      tolerations | Array {
        key | String | optional,
        operator | [| 'Equal, 'Exists |] | default = 'Equal',
        value | String | optional,
        effect | [| 'NoSchedule, 'NoExecute, 'PreferNoSchedule |] | optional,
      } | default = [],
    },
  },

  # Deployment strategy
  Strategy = {
    type | [| 'RollingUpdate, 'Recreate |] | default = 'RollingUpdate',
    rolling_update | {
      max_surge | Number | default = 1,
      max_unavailable | Number | default = 0,
    } | optional,
  },

  # Kubernetes Deployment
  Deployment = {
    api_version | String | default = "apps/v1",
    kind | String | default = "Deployment",
    metadata = {
      name | String,
      namespace | String | default = "default",
      labels | {_ | String} | default = {app = ""},
      annotations | {_ | String} | default = {},
    },
    spec = {
      replicas | Number | default = 1,
      selector = {
        match_labels | {_ | String},
      },
      template | PodTemplateSpec,
      strategy | Strategy | default = {type = 'RollingUpdate'},
    },
  },

  # Kubernetes Service
  Service = {
    api_version | String | default = "v1",
    kind | String | default = "Service",
    metadata = {
      name | String,
      namespace | String | default = "default",
      labels | {_ | String} | default = {},
    },
    spec = {
      type | [| 'ClusterIP, 'NodePort, 'LoadBalancer, 'ExternalName |] | default = 'ClusterIP',
      selector | {_ | String},
      ports | Array {
        name | String | optional,
        port | Number,
        target_port | Number,
        protocol | [| 'TCP, 'UDP |] | default = 'TCP',
      },
      cluster_ip | String | optional,
    },
  },

  # Kubernetes ConfigMap
  ConfigMap = {
    api_version | String | default = "v1",
    kind | String | default = "ConfigMap",
    metadata = {
      name | String,
      namespace | String | default = "default",
    },
    data | {_ | String},
  },

  # Solo mode presets
  soloDeploymentPreset = fun name image replicas port =>
    {
      api_version = "apps/v1",
      kind = "Deployment",
      metadata = {
        name = name,
        namespace = "provisioning",
        labels = {app = name},
      },
      spec = {
        replicas = replicas,
        selector = {match_labels = {app = name}},
        template = {
          metadata = {
            labels = {app = name},
          },
          spec = {
            containers = [
              {
                name = name,
                image = "provisioning/%{name}:latest",
                image_pull_policy = 'Always',
                ports = [{
                  name = "http",
                  container_port = port,
                }],
                env = [{
                  name = "PROVISIONING_MODE",
                  value = "solo",
                }],
                resources = {
                  requests = {
                    cpu = "100m",
                    memory = "128Mi",
                  },
                  limits = {
                    cpu = "500m",
                    memory = "512Mi",
                  },
                },
                readiness_probe = {
                  http_get = {
                    path = "/health",
                    port = port,
                  },
                  initial_delay_seconds = 10,
                  period_seconds = 5,
                },
              }
            ],
            restart_policy = 'Always',
          },
        },
      },
    },

  # Enterprise mode presets (with HA replicas)
  enterpriseDeploymentPreset = fun name image replicas port =>
    {
      api_version = "apps/v1",
      kind = "Deployment",
      metadata = {
        name = name,
        namespace = "provisioning",
        labels = {
          app = name,
          tier = "production",
        },
      },
      spec = {
        replicas = replicas,
        selector = {match_labels = {app = name}},
        strategy = {
          type = 'RollingUpdate',
          rolling_update = {
            max_surge = 1,
            max_unavailable = 0,
          },
        },
        template = {
          metadata = {
            labels = {
              app = name,
              version = "1.0.0",
            },
            annotations = {
              "prometheus.io/scrape" = "true",
              "prometheus.io/port" = "%{port}",
            },
          },
          spec = {
            containers = [
              {
                name = name,
                image = "provisioning/%{name}:latest",
                image_pull_policy = 'IfNotPresent',
                ports = [{
                  name = "http",
                  container_port = port,
                }],
                env = [
                  {
                    name = "PROVISIONING_MODE",
                    value = "enterprise",
                  },
                  {
                    name = "POD_NAME",
                    value_from = {
                      field_path = "metadata.name",
                    },
                  },
                ],
                resources = {
                  requests = {
                    cpu = "500m",
                    memory = "512Mi",
                  },
                  limits = {
                    cpu = "2000m",
                    memory = "2048Mi",
                  },
                },
                liveness_probe = {
                  http_get = {
                    path = "/health",
                    port = port,
                  },
                  initial_delay_seconds = 30,
                  period_seconds = 10,
                  failure_threshold = 3,
                },
                readiness_probe = {
                  http_get = {
                    path = "/ready",
                    port = port,
                  },
                  initial_delay_seconds = 5,
                  period_seconds = 5,
                },
              }
            ],
            restart_policy = 'Always',
            termination_grace_period_seconds = 60,
            node_selector = {
              "workload-type" = "provisioning",
            },
          },
        },
      },
    },

  # Solo mode service preset
  soloServicePreset = fun name port =>
    {
      api_version = "v1",
      kind = "Service",
      metadata = {
        name = name,
        namespace = "provisioning",
        labels = {app = name},
      },
      spec = {
        type = 'ClusterIP',
        selector = {app = name},
        ports = [{
          name = "http",
          port = port,
          target_port = port,
        }],
      },
    },

  # Enterprise mode service preset (with NodePort)
  enterpriseServicePreset = fun name port node_port =>
    {
      api_version = "v1",
      kind = "Service",
      metadata = {
        name = name,
        namespace = "provisioning",
        labels = {
          app = name,
          tier = "production",
        },
      },
      spec = {
        type = 'NodePort',
        selector = {app = name},
        ports = [{
          name = "http",
          port = port,
          target_port = port,
          node_port = node_port,
        }],
      },
    },
}
