# Variables ====================================================================

variable "name_prefix" {
  description = "Prefix prepended to resource names created by this module."
  type        = string

  validation {
    condition     = length(trimspace(var.name_prefix)) > 0
    error_message = "name_prefix must not be empty."
  }
}

variable "name_suffix" {
  description = "Suffix appended to the load balancer resource name to distinguish it within name_prefix."
  type        = string

  validation {
    condition     = length(trimspace(var.name_suffix)) > 0
    error_message = "name_suffix must not be empty."
  }
}

variable "tags" {
  description = "Tags applied to all resources in this module."
  type        = map(string)
  default     = {}
}

variable "load_balancer_type" {
  description = "Load balancer type — application or network."
  type        = string
  default     = "application"

  validation {
    condition     = contains(["application", "network"], var.load_balancer_type)
    error_message = "load_balancer_type must be application or network."
  }
}

variable "internal" {
  description = "Create an internal (non-internet-facing) load balancer."
  type        = bool
  default     = false
}

variable "subnet_ids" {
  description = "Subnet IDs for the load balancer. Must span at least two AZs."
  type        = list(string)

  validation {
    condition     = length(var.subnet_ids) >= 2
    error_message = "subnet_ids must include at least two subnets across different AZs."
  }
}

variable "security_group_ids" {
  description = "Security group IDs to attach to the load balancer's ENIs. Supported on ALB always, and on NLB in regions/accounts with the 2023 NLB security groups feature enabled."
  type        = list(string)
  default     = []
}

variable "cross_zone_load_balancing" {
  description = "Enable cross-zone load balancing. Valid for NLB only — ALB always has this enabled and it is not configurable."
  type        = bool
  default     = true
}

variable "access_logs_bucket" {
  description = "S3 bucket for access logs (optional)."
  type        = string
  default     = null
}

variable "access_logs_prefix" {
  description = "S3 prefix for access logs."
  type        = string
  default     = "lb"
}

variable "deletion_protection" {
  description = "Enable deletion protection."
  type        = bool
  default     = true
}

variable "idle_timeout" {
  description = "Idle timeout in seconds. Valid for ALB only — NLB connections do not have a configurable idle timeout."
  type        = number
  default     = 60
}

variable "waf_web_acl_arn" {
  description = "WAF Web ACL ARN to associate with the load balancer. Valid for ALB only — WAFv2 does not support NLB as an association target."
  type        = string
  default     = null
}

variable "target_groups" {
  description = <<-EOT
    Map of target group definitions.

    - name_suffix is combined with name_prefix and region to build the target group name.
    - protocol must be TCP/UDP/TCP_UDP for NLB target groups, HTTP/HTTPS for ALB.
    - stickiness.type must be source_ip for NLB, lb_cookie or app_cookie for ALB.
    - targets is a map of instance IDs (target_type = "instance") or IP addresses
      (target_type = "ip") to attach. port overrides the target group's port for
      that specific target; leave null to use the target group's port.
  EOT
  type = map(object({
    name_suffix          = string
    port                 = number
    protocol             = string
    target_type          = optional(string, "instance")
    vpc_id               = string
    deregistration_delay = optional(number, 30)
    tags                 = optional(map(string), {})
    targets = optional(map(object({
      id   = string
      port = optional(number, null)
    })), {})
    health_check = optional(object({
      enabled             = optional(bool, true)
      path                = optional(string, "/health")
      protocol            = optional(string, "HTTP")
      matcher             = optional(string, "200")
      interval            = optional(number, 30)
      timeout             = optional(number, 5)
      healthy_threshold   = optional(number, 2)
      unhealthy_threshold = optional(number, 2)
    }), {})
    stickiness = optional(object({
      enabled         = optional(bool, false)
      cookie_duration = optional(number, 86400)
      type            = optional(string, "lb_cookie")
    }), null)
  }))
  default = {}

  validation {
    condition = alltrue([
      for k, v in var.target_groups : v.deregistration_delay >= 0 && v.deregistration_delay <= 3600
    ])
    error_message = "deregistration_delay must be between 0 and 3600 seconds."
  }

  validation {
    condition = alltrue([
      for k, v in var.target_groups : length(trimspace(v.name_suffix)) > 0
    ])
    error_message = "Every target group must set a non-empty name_suffix."
  }

  validation {
    condition = alltrue([
      for k, v in var.target_groups :
      contains(["HTTP", "HTTPS", "TCP", "UDP", "TCP_UDP", "TLS", "GENEVE"], v.protocol)
    ])
    error_message = "Target group protocol must be one of HTTP, HTTPS, TCP, UDP, TCP_UDP, TLS, GENEVE."
  }

  validation {
    condition = alltrue([
      for k, v in var.target_groups :
      v.stickiness == null || contains(["lb_cookie", "app_cookie", "source_ip"], v.stickiness.type)
    ])
    error_message = "stickiness.type must be lb_cookie, app_cookie, or source_ip."
  }
}

variable "listeners" {
  description = <<-EOT
    Map of load balancer listener definitions.

    - redirect actions are only valid on ALB listeners — NLB does not support the redirect action type.
    - certificate_arn is only meaningful for HTTPS/TLS protocol listeners.
  EOT
  type = map(object({
    port                = number
    protocol            = string
    certificate_arn     = optional(string, null)
    ssl_policy          = optional(string, "ELBSecurityPolicy-TLS13-1-2-2021-06")
    default_action_type = optional(string, "forward")
    target_group_key    = optional(string, null)
    redirect = optional(object({
      port        = optional(string, "443")
      protocol    = optional(string, "HTTPS")
      status_code = optional(string, "HTTP_301")
    }), null)
  }))
  default = {}

  validation {
    condition = alltrue([
      for k, v in var.listeners :
      contains(["HTTP", "HTTPS", "TCP", "UDP", "TCP_UDP", "TLS"], v.protocol)
    ])
    error_message = "Listener protocol must be one of HTTP, HTTPS, TCP, UDP, TCP_UDP, TLS."
  }

  validation {
    condition = alltrue([
      for k, v in var.listeners :
      !(v.protocol == "HTTPS" || v.protocol == "TLS") || v.certificate_arn != null
    ])
    error_message = "Listeners using HTTPS or TLS protocol must set certificate_arn."
  }

  validation {
    condition = alltrue([
      for k, v in var.listeners :
      v.redirect != null || v.target_group_key != null
    ])
    error_message = "Every listener must set either target_group_key or redirect."
  }
}
