# Deployment Validators
# Deployment mode, resource allocation, and HA configuration validation

let constraints = import "../constraints/constraints.toml" in
let common = import "./common-validator.ncl" in
let resource_val = import "./resource-validator.ncl" in

{
  # Validate deployment mode
  ValidDeploymentMode = fun mode =>
    let valid_modes = ['solo, 'multiuser, 'cicd, 'enterprise] in
    common.ValidEnum valid_modes mode,

  # Validate cloud provider
  ValidCloudProvider = fun provider =>
    let valid_providers = ['aws, 'gcp, 'azure, 'digitalocean, 'linode, 'custom] in
    common.ValidEnum valid_providers provider,

  # Validate deployment target type
  ValidDeploymentTarget = fun target =>
    let valid_targets = ['local, 'docker, 'kubernetes, 'vm, 'bare_metal] in
    common.ValidEnum valid_targets target,

  # Validate resource consistency for solo mode
  ValidSoloModeResources = fun resources =>
    let cpu_valid = resource_val.ValidCpuCores 'solo resources.cpu_cores in
    let mem_valid = resource_val.ValidMemoryMb 'solo resources.memory_mb in
    let disk_valid = resource_val.ValidDiskGb 'solo resources.disk_gb in
    if cpu_valid && mem_valid && disk_valid then
      resources
    else
      std.contract.blame_with_message "Solo mode resource constraints violated" resources,

  # Validate resource consistency for multiuser mode
  ValidMultiUserModeResources = fun resources =>
    let cpu_valid = resource_val.ValidCpuCores 'multiuser resources.cpu_cores in
    let mem_valid = resource_val.ValidMemoryMb 'multiuser resources.memory_mb in
    let disk_valid = resource_val.ValidDiskGb 'multiuser resources.disk_gb in
    if cpu_valid && mem_valid && disk_valid then
      resources
    else
      std.contract.blame_with_message "MultiUser mode resource constraints violated" resources,

  # Validate resource consistency for cicd mode
  ValidCicdModeResources = fun resources =>
    let cpu_valid = resource_val.ValidCpuCores 'cicd resources.cpu_cores in
    let mem_valid = resource_val.ValidMemoryMb 'cicd resources.memory_mb in
    let disk_valid = resource_val.ValidDiskGb 'cicd resources.disk_gb in
    if cpu_valid && mem_valid && disk_valid then
      resources
    else
      std.contract.blame_with_message "CI/CD mode resource constraints violated" resources,

  # Validate resource consistency for enterprise mode
  ValidEnterpriseModeResources = fun resources =>
    let cpu_valid = resource_val.ValidCpuCores 'enterprise resources.cpu_cores in
    let mem_valid = resource_val.ValidMemoryMb 'enterprise resources.memory_mb in
    let disk_valid = resource_val.ValidDiskGb 'enterprise resources.disk_gb in
    if cpu_valid && mem_valid && disk_valid then
      resources
    else
      std.contract.blame_with_message "Enterprise mode resource constraints violated" resources,

  # Validate HA replica count for enterprise
  ValidHaReplicaCount = fun replicas =>
    let mode_constraints = constraints.deployment.enterprise in
    if replicas < mode_constraints.replicas.min then
      std.contract.blame_with_message
        "HA replicas must be >= %{std.to_string mode_constraints.replicas.min} (minimum for quorum)"
        replicas
    else if replicas > mode_constraints.replicas.max then
      std.contract.blame_with_message
        "HA replicas must be <= %{std.to_string mode_constraints.replicas.max}"
        replicas
    else
      replicas,

  # Validate installation method
  ValidInstallationMethod = fun method =>
    let valid_methods = ['docker_compose, 'kubernetes, 'shell_script, 'terraform] in
    common.ValidEnum valid_methods method,

  # Validate deployment strategy
  ValidDeploymentStrategy = fun strategy =>
    let valid_strategies = ['rolling, 'blue_green, 'canary] in
    common.ValidEnum valid_strategies strategy,

  # Validate upgrade strategy
  ValidUpgradeStrategy = fun strategy =>
    let valid_strategies = ['rolling, 'blue_green, 'canary] in
    common.ValidEnum valid_strategies strategy,

  # Validate installation timeout in minutes
  ValidInstallationTimeout = fun timeout =>
    if timeout < 5 then
      std.contract.blame_with_message "Installation timeout must be >= 5 minutes" timeout
    else if timeout > 600 then
      std.contract.blame_with_message "Installation timeout must be <= 600 minutes (10 hours)" timeout
    else
      timeout,

  # Validate parallel services count
  ValidParallelServices = fun count =>
    if count < 1 then
      std.contract.blame_with_message "Parallel services must be >= 1" count
    else if count > 10 then
      std.contract.blame_with_message "Parallel services must be <= 10" count
    else
      count,

  # Validate backup retention days
  ValidBackupRetentionDays = fun days =>
    if days < 1 then
      std.contract.blame_with_message "Backup retention must be >= 1 day" days
    else if days > 3650 then
      std.contract.blame_with_message "Backup retention must be <= 3650 days (10 years)" days
    else
      days,

  # Validate database backend for mode
  ValidDatabaseBackendForMode = fun mode backend =>
    if mode == 'solo && (backend == 'postgres || backend == 'surrealdb_server) then
      std.contract.blame_with_message
        "Solo mode cannot use server-based databases (postgres, surrealdb_server)"
        backend
    else if mode == 'enterprise && backend == 'filesystem then
      std.contract.blame_with_message
        "Enterprise mode must use robust database (not filesystem)"
        backend
    else
      backend,

  # Validate HA configuration consistency
  ValidHaConfiguration = fun ha_config =>
    if ha_config.enabled && ha_config.replicas < 3 then
      std.contract.blame_with_message
        "HA configuration requires at least 3 replicas, got %{std.to_string ha_config.replicas}"
        ha_config
    else if !ha_config.enabled && ha_config.replicas > 1 then
      std.contract.blame_with_message
        "HA is disabled but replicas > 1"
        ha_config
    else
      ha_config,
}
