# Service Validator - Service configuration validation
# Version: 1.0.0
#
# Validates service definitions against constraints

let Common = import "common-validator.ncl" in

{
  # Validate service type is allowed
  validate_service_type = fun service_type =>
    Common.validate_one_of ['api, 'worker, 'scheduler, 'frontend, 'backend, 'database, 'cache, 'queue] service_type,

  # Validate service name
  validate_service_name = fun name =>
    Common.validate_pattern "^[a-z0-9-]+$" name &&
    Common.validate_string_length 1 32 name,

  # Validate replica count
  validate_replicas = fun replicas =>
    Common.validate_number_range 1 100 replicas,

  # Validate port configuration
  validate_port = {
    container_port
      | {
        label = "valid container port",
        predicate = Common.validate_port
      },

    host_port
      | {
        label = "valid host port",
        predicate = Common.validate_host_port
      },

    protocol
      | {
        label = "valid protocol",
        predicate = Common.validate_one_of ['tcp, 'udp, 'sctp]
      },
  },

  # Validate health check configuration
  validate_healthcheck = {
    enabled | Bool,

    endpoint
      | String
      | {
        label = "valid endpoint",
        predicate = fun s => std.string.starts_with "/" s
      }
      | optional,

    interval
      | Number
      | {
        label = "valid interval",
        predicate = Common.validate_number_range 5 300
      },

    timeout
      | Number
      | {
        label = "valid timeout",
        predicate = Common.validate_number_range 1 60
      },

    retries
      | Number
      | {
        label = "valid retries",
        predicate = Common.validate_number_range 1 10
      },

    start_period
      | Number
      | {
        label = "valid start period",
        predicate = Common.validate_number_range 0 300
      },
  },

  # Validate image configuration
  validate_image = {
    name
      | String
      | {
        label = "valid image name",
        predicate = Common.validate_image_name
      },

    tag
      | String
      | {
        label = "valid image tag",
        predicate = Common.validate_image_tag
      },

    build_context
      | String
      | optional,

    dockerfile
      | String
      | optional,
  },

  # Validate resource configuration
  validate_resources = {
    cpu_limit
      | String
      | {
        label = "valid CPU limit",
        predicate = Common.validate_cpu_limit
      }
      | optional,

    cpu_request
      | String
      | {
        label = "valid CPU request",
        predicate = Common.validate_cpu_limit
      }
      | optional,

    memory_limit
      | String
      | {
        label = "valid memory limit",
        predicate = Common.validate_memory_limit
      }
      | optional,

    memory_request
      | String
      | {
        label = "valid memory request",
        predicate = Common.validate_memory_limit
      }
      | optional,
  },

  # Validate restart policy
  validate_restart_policy = fun policy =>
    Common.validate_one_of ['no, 'always, 'on-failure, 'unless-stopped] policy,

  # Validate environment variables
  validate_environment = fun env =>
    std.record.values env
    |> std.array.all (fun v => std.is_string v && std.string.length v <= 4096),

  # Validate depends_on array
  validate_depends_on = fun deps =>
    std.array.all (fun s =>
      Common.validate_pattern "^[a-z0-9-]+$" s
    ) deps,

  # Validate volume mounts
  validate_volumes = fun volumes =>
    std.array.all (fun v =>
      std.is_string v &&
      std.string.length v >= 3
    ) volumes,

  # Validate networks
  validate_networks = fun networks =>
    std.array.all (fun n =>
      Common.validate_pattern "^[a-z0-9-]+$" n
    ) networks,

  # Complete service validation
  validate_service = {
    type
      | {
        label = "valid service type",
        predicate = validate_service_type
      },

    image | validate_image,

    ports
      | Array validate_port
      | default = [],

    environment
      | {_: String}
      | {
        label = "valid environment",
        predicate = validate_environment
      }
      | default = {},

    env_file
      | Array String
      | default = [],

    healthcheck
      | validate_healthcheck
      | default = {enabled = true},

    resources
      | validate_resources
      | optional,

    depends_on
      | Array String
      | {
        label = "valid dependencies",
        predicate = validate_depends_on
      }
      | default = [],

    replicas
      | Number
      | {
        label = "valid replica count",
        predicate = validate_replicas
      }
      | default = 1,

    restart_policy
      | {
        label = "valid restart policy",
        predicate = validate_restart_policy
      }
      | default = 'unless-stopped,

    command
      | Array String
      | optional,

    entrypoint
      | Array String
      | optional,

    working_dir
      | String
      | optional,

    user
      | String
      | optional,

    volumes
      | Array String
      | {
        label = "valid volumes",
        predicate = validate_volumes
      }
      | default = [],

    networks
      | Array String
      | {
        label = "valid networks",
        predicate = validate_networks
      }
      | default = [],

    labels
      | {_: String}
      | default = {},
  },
}
