data "aws_subnet" "public" {
  for_each = toset(module.vpc_info.default_public_subnet_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.environment}-fansifter-lb-logs"
}

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

data "aws_route53_zone" "route53_zone" {
  name         = local.route53_zone
  private_zone = false
}

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

  name         = "theorchard.io."
  private_zone = false
}

data "cloudflare_ip_ranges" "cloudflare" {}

data "cloudflare_zone" "cloudflare_zone" {
  name = var.public_domain_name
}

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(
    [for s in data.aws_subnet.public : s.cidr_block],
    data.cloudflare_ip_ranges.cloudflare.ipv4_cidr_blocks,
  )
  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         = module.vpc_info.default_public_subnet_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-TLS13-1-2-2021-06"
  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" "sendgrid_webhooks_listener_rule" {
  listener_arn = aws_lb_listener.https_listener.arn
  priority     = 100

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

  condition {
    path_pattern {
      values = [
        "/events-theorchard",
        "/events-sme",
      ]
    }
  }

  tags = local.tags
}

resource "aws_lb_target_group" "sendgrid_webhooks_target_group" {
  name        = "${var.environment}-${var.application_family}-sendgrid-wbhks-tg"
  target_type = "lambda"

  tags = local.tags
}

resource "aws_lambda_permission" "load_balancer_sendgrid_webhooks_lambda_permissions" {
  action        = "lambda:InvokeFunction"
  principal     = "elasticloadbalancing.amazonaws.com"
  source_arn    = aws_lb_target_group.sendgrid_webhooks_target_group.arn
  function_name = module.lambda_audience_sendgrid_webhooks.lambda_arn
}

resource "aws_lb_target_group_attachment" "sendgrid_webhooks_lambda_target_group_attachment" {
  target_group_arn = aws_lb_target_group.sendgrid_webhooks_target_group.arn
  target_id        = module.lambda_audience_sendgrid_webhooks.lambda_arn

  depends_on = [
    aws_lambda_permission.load_balancer_sendgrid_webhooks_lambda_permissions
  ]
}

resource "aws_route53_record" "load_balancer_route53_record" {
  zone_id = data.aws_route53_zone.route53_zone.id
  name    = local.load_balancer_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" "theorchard_io_load_balancer_route53_record" {
  provider = aws.networking

  zone_id = data.aws_route53_zone.theorchard_io_route53_zone.id
  name    = local.load_balancer_name
  type    = "A"

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

resource "cloudflare_record" "public_cname_record" {
  zone_id = data.cloudflare_zone.cloudflare_zone.id
  name    = local.load_balancer_name
  value   = "${local.load_balancer_name}.${var.domain_name}"
  type    = "CNAME"
  proxied = true
}
