data "aws_caller_identity" "current" {}

data "cloudflare_ip_ranges" "ip_ranges" {}

data "aws_acm_certificate" "theorchard_cert" {
  domain   = "*.${var.domain_name}"
  statuses = ["ISSUED"]
}

resource "aws_security_group" "email_campaigns_public_lb_sg" {
  name        = "${var.environment}-${var.service_name}-public-load-balancer-security-group"
  description = "Allow inbound HTTPS traffic from Cloudflare IPs only"
  vpc_id      = module.vpc_info.vpc_id

  tags = module.default_tags.tags
}

resource "aws_security_group_rule" "allow_https_from_cloudflare" {
  description       = "Allow HTTPS traffic from Cloudflare edge servers"
  type              = "ingress"
  from_port         = 443
  to_port           = 443
  protocol          = "TCP"
  cidr_blocks       = data.cloudflare_ip_ranges.ip_ranges.ipv4_cidrs
  security_group_id = aws_security_group.email_campaigns_public_lb_sg.id
}

resource "aws_security_group_rule" "public_lb_to_fargate" {
  description              = "Allow public ALB to communicate with Fargate tasks"
  type                     = "egress"
  from_port                = 8080
  to_port                  = 8080
  protocol                 = "TCP"
  source_security_group_id = module.ows_service_fargate_environment.fargate_security_group_id
  security_group_id        = aws_security_group.email_campaigns_public_lb_sg.id
}

resource "aws_security_group_rule" "fargate_from_public_lb" {
  description              = "Allow Fargate tasks to receive traffic from public ALB"
  type                     = "ingress"
  from_port                = 8080
  to_port                  = 8080
  protocol                 = "TCP"
  source_security_group_id = aws_security_group.email_campaigns_public_lb_sg.id
  security_group_id        = module.ows_service_fargate_environment.fargate_security_group_id
}

resource "aws_lb" "email_campaigns_public_lb" {
  name                       = "${var.environment}-${var.service_name}-public"
  internal                   = false
  load_balancer_type         = "application"
  subnets                    = module.vpc_info.default_public_subnet_ids
  security_groups            = [aws_security_group.email_campaigns_public_lb_sg.id]
  enable_deletion_protection = false

  access_logs {
    enabled = true
    bucket  = "shared-orcd-lb-logs"
    prefix  = "${data.aws_caller_identity.current.account_id}/${var.environment}-fansifter-${var.service_name}-public"
  }

  tags = module.default_tags.tags
}

resource "aws_lb_target_group" "email_campaigns_public_tg" {
  # checkov:skip=CKV_AWS_378:Ensure AWS Load Balancer doesn't use HTTP protocol
  name                 = "${var.environment}-${var.service_name}-public"
  port                 = 8080
  protocol             = "HTTP"
  vpc_id               = module.vpc_info.vpc_id
  target_type          = "ip"
  deregistration_delay = 60

  health_check {
    path                = "/hello/"
    interval            = 10
    timeout             = 5
    healthy_threshold   = 3
    unhealthy_threshold = 3
    matcher             = "200"
  }

  stickiness {
    enabled = false
    type    = "lb_cookie"
  }

  tags = module.default_tags.tags
}

resource "aws_lb_listener" "email_campaigns_public_listener" {
  load_balancer_arn = aws_lb.email_campaigns_public_lb.arn
  port              = 443
  protocol          = "HTTPS"
  ssl_policy        = "ELBSecurityPolicy-TLS13-1-3-2021-06"
  certificate_arn   = data.aws_acm_certificate.theorchard_cert.arn

  default_action {
    type = "fixed-response"
    fixed_response {
      content_type = "text/plain"
      message_body = "Forbidden"
      status_code  = "403"
    }
  }
}

# Forward rule for public automated email preview
# Accepts: https://fansifter-emails.theorchard.com/automated-emails-public-preview/{email_id}?pwd={token}
# Forwards as-is to the backend (path matches internal route).
resource "aws_lb_listener_rule" "automated_email_public_preview" {
  listener_arn = aws_lb_listener.email_campaigns_public_listener.arn
  priority     = 5

  action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.email_campaigns_public_tg.arn
  }

  condition {
    path_pattern {
      values = [
        "/automated-emails-public-preview/*",
      ]
    }
  }

  tags = module.default_tags.tags
}

# Forward rule for public email preview
# Accepts: https://fansifter-emails.theorchard.com/{campaign_id}?pwd={token}
# Rewrites to: /campaigns-public-preview/{campaign_id}?pwd={token}
resource "aws_lb_listener_rule" "email_public_preview" {
  listener_arn = aws_lb_listener.email_campaigns_public_listener.arn
  priority     = 10

  transform {
    type = "url-rewrite"

    url_rewrite_config {
      rewrite {
        regex   = "^/(.*)$"
        replace = "/campaigns-public-preview/$1"
      }
    }
  }

  action {
    type             = "forward"
    target_group_arn = aws_lb_target_group.email_campaigns_public_tg.arn
  }

  condition {
    path_pattern {
      values = [
        "/*",
      ]
    }
  }
}

resource "aws_route53_record" "email_campaigns_public_route53" {
  provider = aws.networking

  zone_id = data.aws_route53_zone.route53_zone_networking.zone_id
  name    = "${var.environment}-${var.service_name}-public.theorchard.io"
  type    = "A"

  alias {
    name                   = aws_lb.email_campaigns_public_lb.dns_name
    zone_id                = aws_lb.email_campaigns_public_lb.zone_id
    evaluate_target_health = true
  }
}

resource "aws_wafv2_web_acl_association" "public_alb_waf" {
  resource_arn = aws_lb.email_campaigns_public_lb.arn
  web_acl_arn  = module.custom_waf.waf_blocking_arn_output
}
