################################################################################
# Module: lb
# Main — AWS Application Load Balancer
#
# - Internet-facing ALB in public subnets
# - HTTPS listener (443) with ACM certificate, TLS 1.2+ enforced
# - HTTP listener (80) redirects permanently to HTTPS — no plaintext traffic
# - Target group pointing to ECS Fargate tasks on the app port
# - Access logs optionally streamed to S3
################################################################################

terraform {
  required_version = ">= 1.6.0"

  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 5.40.0"
    }
  }
}

locals {
  identifier = "${var.project}-${var.environment}"

  common_tags = {
    environment = var.environment
    project     = var.project
    managed_by  = "terraform"
  }
}

################################################################################
# Security Group — ALB allows inbound 80 + 443 from the internet
################################################################################

resource "aws_security_group" "alb" {
  name        = "${local.identifier}-alb-sg"
  description = "ALB security group — inbound 80/443 from internet, outbound to app"
  vpc_id      = var.vpc_id

  ingress {
    description = "HTTP from internet (redirected to HTTPS)"
    from_port   = 80
    to_port     = 80
    protocol    = "tcp"
    cidr_blocks = var.allowed_ingress_cidrs
  }

  ingress {
    description = "HTTPS from internet"
    from_port   = 443
    to_port     = 443
    protocol    = "tcp"
    cidr_blocks = var.allowed_ingress_cidrs
  }

  egress {
    description = "Forward to ECS app tasks"
    from_port   = var.target_group_port
    to_port     = var.target_group_port
    protocol    = "tcp"
    cidr_blocks = ["0.0.0.0/0"]
  }

  tags = merge(local.common_tags, {
    Name = "${local.identifier}-alb-sg"
  })
}

################################################################################
# Application Load Balancer
################################################################################

resource "aws_lb" "main" {
  name               = "${local.identifier}-alb"
  internal           = false
  load_balancer_type = "application"
  security_groups    = [aws_security_group.alb.id]
  subnets            = var.subnet_ids

  idle_timeout               = var.idle_timeout
  enable_deletion_protection = var.enable_deletion_protection

  # HTTP/2 is enabled by default on ALB; leave it on for performance.
  enable_http2 = true

  # Drop invalid header fields to harden against request smuggling.
  drop_invalid_header_fields = true

  dynamic "access_logs" {
    for_each = var.access_logs_bucket != "" ? [1] : []
    content {
      bucket  = var.access_logs_bucket
      prefix  = var.access_logs_prefix
      enabled = true
    }
  }

  tags = merge(local.common_tags, {
    Name = "${local.identifier}-alb"
  })
}

################################################################################
# Target Group — ECS Fargate tasks register here
################################################################################

resource "aws_lb_target_group" "app" {
  name        = "${local.identifier}-tg"
  port        = var.target_group_port
  protocol    = "HTTP"
  vpc_id      = var.vpc_id
  target_type = "ip" # Required for Fargate (awsvpc network mode)

  deregistration_delay = 30

  health_check {
    enabled             = true
    path                = var.target_group_health_check_path
    port                = "traffic-port"
    protocol            = "HTTP"
    interval            = var.target_group_health_check_interval
    timeout             = var.target_group_health_check_timeout
    healthy_threshold   = var.target_group_healthy_threshold
    unhealthy_threshold = var.target_group_unhealthy_threshold
    matcher             = "200"
  }

  stickiness {
    type    = "lb_cookie"
    enabled = false # AgentIdP is stateless (JWT-based); no sticky sessions needed
  }

  tags = merge(local.common_tags, {
    Name = "${local.identifier}-tg"
  })

  lifecycle {
    create_before_destroy = true
  }
}

################################################################################
# HTTPS Listener (port 443) — primary listener
################################################################################

resource "aws_lb_listener" "https" {
  load_balancer_arn = aws_lb.main.arn
  port              = 443
  protocol          = "HTTPS"
  ssl_policy        = var.ssl_policy
  certificate_arn   = var.certificate_arn

  default_action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.app.arn
  }

  tags = local.common_tags
}

################################################################################
# HTTP Listener (port 80) — permanent redirect to HTTPS
################################################################################

resource "aws_lb_listener" "http_redirect" {
  load_balancer_arn = aws_lb.main.arn
  port              = 80
  protocol          = "HTTP"

  default_action {
    type = "redirect"

    redirect {
      port        = "443"
      protocol    = "HTTPS"
      status_code = "HTTP_301"
    }
  }

  tags = local.common_tags
}
