# ---------------------------------------------------------------------------
# Public ALB for the API service: HTTPS (443) -> api target group, HTTP (80)
# -> redirect to HTTPS. WebSocket (Socket.io) rides the same listener;
# idle_timeout is raised.
#
# DNS is managed externally (Cloudflare): Terraform creates NO Route53 / DNS
# records. The certificate is operator-provided (already ISSUED) via
# acm_certificate_arn. After apply, CNAME your API hostname to the
# `alb_dns_name` output in Cloudflare.
# ---------------------------------------------------------------------------

resource "aws_lb" "this" {
  name                       = "${var.name_prefix}-alb"
  internal                   = false
  load_balancer_type         = "application"
  security_groups            = [var.security_group_id]
  subnets                    = var.public_subnet_ids
  idle_timeout               = var.idle_timeout
  enable_deletion_protection = var.enable_deletion_protection
  drop_invalid_header_fields = true

  tags = var.tags
}

resource "aws_lb_target_group" "api" {
  name        = "${var.name_prefix}-api-tg"
  port        = var.api_container_port
  protocol    = "HTTP"
  vpc_id      = var.vpc_id
  target_type = "ip"

  # Active-active: no stickiness (default off). 8s polling fallback + Redis
  # Socket.io adapter make sticky sessions unnecessary.
  deregistration_delay = 125 # >= api stopTimeout (120s) so BullMQ drains

  health_check {
    enabled             = true
    path                = var.api_health_check_path
    protocol            = "HTTP"
    matcher             = "200"
    interval            = 15
    timeout             = 5
    healthy_threshold   = 2
    unhealthy_threshold = 3
  }

  tags = var.tags
}

resource "aws_lb_listener" "https" {
  load_balancer_arn = aws_lb.this.arn
  port              = 443
  protocol          = "HTTPS"
  ssl_policy        = "ELBSecurityPolicy-TLS13-1-2-2021-06"
  certificate_arn   = var.acm_certificate_arn

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

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

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

# ---------------------------------------------------------------------------
# Frontend routing (app.<domain> + *.<domain>) — gated on the wildcard cert.
# When disabled (empty arn) none of this exists and api remains the listener
# default. The api cert stays the listener default; the wildcard cert is added
# as an additional listener certificate and selected by SNI.
# ---------------------------------------------------------------------------
locals {
  frontend_enabled = var.frontend_acm_certificate_arn != ""
}

resource "aws_lb_target_group" "frontend" {
  count       = local.frontend_enabled ? 1 : 0
  name        = "${var.name_prefix}-frontend-tg"
  port        = var.frontend_container_port
  protocol    = "HTTP"
  vpc_id      = var.vpc_id
  target_type = "ip"

  deregistration_delay = 30

  health_check {
    enabled             = true
    path                = var.frontend_health_check_path
    protocol            = "HTTP"
    matcher             = "200"
    interval            = 15
    timeout             = 5
    healthy_threshold   = 2
    unhealthy_threshold = 3
  }

  tags = var.tags
}

resource "aws_lb_listener_certificate" "frontend" {
  count           = local.frontend_enabled ? 1 : 0
  listener_arn    = aws_lb_listener.https.arn
  certificate_arn = var.frontend_acm_certificate_arn
}

# Rule priority is load-bearing: the explicit api.<domain> rule (p10) MUST
# precede the *.<domain> wildcard (p30) or the wildcard would also match the
# API host and route it to the frontend. app.<domain> (p20) is explicit for
# clarity (the wildcard would otherwise cover it). Default action is unchanged
# (= api target group).
resource "aws_lb_listener_rule" "api_host" {
  count        = local.frontend_enabled ? 1 : 0
  listener_arn = aws_lb_listener.https.arn
  priority     = 10

  action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.api.arn
  }
  condition {
    host_header {
      values = ["${var.api_subdomain}.${var.domain_name}"]
    }
  }
}

resource "aws_lb_listener_rule" "frontend_app_host" {
  count        = local.frontend_enabled ? 1 : 0
  listener_arn = aws_lb_listener.https.arn
  priority     = 20

  action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.frontend[0].arn
  }
  condition {
    host_header {
      values = ["${var.app_subdomain}.${var.domain_name}"]
    }
  }
}

resource "aws_lb_listener_rule" "frontend_wildcard_host" {
  count        = local.frontend_enabled ? 1 : 0
  listener_arn = aws_lb_listener.https.arn
  priority     = 30

  action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.frontend[0].arn
  }
  condition {
    host_header {
      values = ["*.${var.domain_name}"]
    }
  }
}
