data "aws_subnets" "public" {
  filter {
    name   = "vpc-id"
    values = [module.vpc_info.vpc_id]
  }

  tags = {
    Name = "public0*"
  }
}

data "aws_subnet" "public" {
  for_each = toset(data.aws_subnets.public.ids)
  id       = each.value
}

data "aws_wafv2_web_acl" "service_waf" {
  name  = "${var.environment}-orcd-waf-block"
  scope = "REGIONAL"
}

data "aws_s3_bucket" "load_balancer_access_logs_bucket" {
  bucket = var.load_balancer_access_logs_bucket_name
}

data "aws_acm_certificate" "acm_certificate" {
  domain   = var.acm_certificate_domain
  statuses = ["ISSUED"]
}

data "aws_route53_zone" "route53_zone" {
  name = var.route53_dns_zone
}

data "aws_route53_zone" "route53_zone_networking" {
  provider = aws.networking

  name = var.route53_dns_zone
}

resource "aws_security_group" "load_balancer_security_group" {
  name        = "${local.load_balancer_name}-alb-security-group"
  description = "Security Group for ${local.load_balancer_name} ALB."
  vpc_id      = module.vpc_info.vpc_id

  tags = local.tags
}

resource "aws_security_group_rule" "load_balancer_security_group_ingress_https_rule" {
  type     = "ingress"
  protocol = "tcp"
  cidr_blocks = concat(
    var.trusted_cidr_blocks,
    [for s in data.aws_subnet.public : s.cidr_block],
  )
  from_port         = 443
  to_port           = 443
  security_group_id = aws_security_group.load_balancer_security_group.id
}

resource "aws_security_group_rule" "load_balancer_security_group_egress_rule" {
  type              = "egress"
  protocol          = "-1"
  cidr_blocks       = ["0.0.0.0/0"]
  from_port         = 0
  to_port           = 0
  security_group_id = aws_security_group.load_balancer_security_group.id
}

resource "aws_lb" "load_balancer" {
  name               = local.load_balancer_name
  load_balancer_type = "application"
  internal           = false

  subnets         = data.aws_subnets.public.ids
  security_groups = [aws_security_group.load_balancer_security_group.id]

  access_logs {
    enabled = true
    bucket  = data.aws_s3_bucket.load_balancer_access_logs_bucket.bucket
    prefix  = local.load_balancer_name
  }

  tags = local.tags
}

resource "aws_wafv2_web_acl_association" "lb_waf_association" {
  resource_arn = aws_lb.load_balancer.arn
  web_acl_arn  = data.aws_wafv2_web_acl.service_waf.arn
}

resource "aws_lb_listener" "https_listener" {
  load_balancer_arn = aws_lb.load_balancer.arn

  port            = 443
  protocol        = "HTTPS"
  ssl_policy      = "ELBSecurityPolicy-FS-1-2-2019-08"
  certificate_arn = data.aws_acm_certificate.acm_certificate.arn

  default_action {
    type = "fixed-response"

    fixed_response {
      content_type = "text/plain"
      message_body = "200 OK"
      status_code  = "200"
    }
  }

  tags = local.tags
}

resource "aws_lb_listener_rule" "fivetran_webhooks_listener_rule" {
  listener_arn = aws_lb_listener.https_listener.arn
  priority     = 100

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

  condition {
    path_pattern {
      values = [
        "/shopify*",
        "/facebook-ads*",
        "/ad-reporting*"
      ]
    }
  }

  tags = local.tags
}

resource "aws_lb_target_group" "fivetran_webhooks_target_group" {
  name        = "${local.load_balancer_name}-tg"
  target_type = "lambda"

  tags = local.tags
}

resource "aws_lambda_permission" "load_balancer_fivetran_webhooks_lambda_permissions" {
  action        = "lambda:InvokeFunction"
  principal     = "elasticloadbalancing.amazonaws.com"
  source_arn    = aws_lb_target_group.fivetran_webhooks_target_group.arn
  function_name = module.lambda_audience_fivetran_webhooks.lambda_arn
}

resource "aws_lb_target_group_attachment" "fivetran_webhooks_lambda_target_group_attachment" {
  target_group_arn = aws_lb_target_group.fivetran_webhooks_target_group.arn
  target_id        = module.lambda_audience_fivetran_webhooks.lambda_arn

  depends_on = [
    aws_lambda_permission.load_balancer_fivetran_webhooks_lambda_permissions
  ]
}

resource "aws_route53_record" "load_balancer_route53_record" {
  zone_id = data.aws_route53_zone.route53_zone.id
  name    = local.load_balancer_route53_record_name
  type    = "A"

  alias {
    name                   = aws_lb.load_balancer.dns_name
    zone_id                = aws_lb.load_balancer.zone_id
    evaluate_target_health = false
  }
}

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

  zone_id = data.aws_route53_zone.route53_zone_networking.id
  name    = local.load_balancer_route53_record_name
  type    = "A"

  alias {
    name                   = aws_lb.load_balancer.dns_name
    zone_id                = aws_lb.load_balancer.zone_id
    evaluate_target_health = false
  }
}
