# Security group for VPC Link v2
resource "aws_security_group" "email_campaigns_vpc_link_sg" {
  name        = "${var.environment}-email-campaigns-vpc-link"
  description = "${var.environment}-email-campaigns-vpc-link"
  vpc_id      = var.vpc_id

  tags = merge(
    local.tags,
    {
      Name = "${var.environment}-email-campaigns-vpc-link"
    }
  )
}

resource "aws_vpc_security_group_egress_rule" "email_campaigns_vpc_link_to_alb" {
  security_group_id            = aws_security_group.email_campaigns_vpc_link_sg.id
  referenced_security_group_id = aws_security_group.proxy_load_balancer_security_group.id
  from_port                    = 443
  ip_protocol                  = "tcp"
  to_port                      = 443
}

resource "aws_vpc_security_group_egress_rule" "email_campaigns_vpc_link_dns" {
  security_group_id = aws_security_group.email_campaigns_vpc_link_sg.id
  cidr_ipv4         = "0.0.0.0/0"
  from_port         = 53
  ip_protocol       = "udp"
  to_port           = 53
}

# Security group for proxy ALB
resource "aws_security_group" "proxy_load_balancer_security_group" {
  name        = "${var.environment}-email-campaigns-vpc-endpoint-proxy"
  description = "${var.environment}-email-campaigns-vpc-endpoint-proxy"
  vpc_id      = var.vpc_id

  tags = merge(
    local.tags,
    {
      Name = "${var.environment}-email-campaigns-vpc-endpoint-proxy"
    }
  )
}

resource "aws_vpc_security_group_ingress_rule" "email_campaigns_alb_from_vpc_link" {
  security_group_id            = aws_security_group.proxy_load_balancer_security_group.id
  referenced_security_group_id = aws_security_group.email_campaigns_vpc_link_sg.id
  from_port                    = 443
  ip_protocol                  = "tcp"
  to_port                      = 443
}

resource "aws_vpc_security_group_egress_rule" "email_campaigns_alb_to_vpce" {
  security_group_id            = aws_security_group.proxy_load_balancer_security_group.id
  referenced_security_group_id = aws_security_group.email_campaigns_vpce_sg.id
  from_port                    = 443
  ip_protocol                  = "tcp"
  to_port                      = 443
}

# Security group for VPC Endpoint (PrivateLink)
resource "aws_security_group" "email_campaigns_vpce_sg" {
  name        = "${var.environment}-email-campaigns-vpce"
  description = "${var.environment}-email-campaigns-vpce"
  vpc_id      = var.vpc_id

  tags = merge(
    local.tags,
    {
      Name = "${var.environment}-email-campaigns-vpce"
    }
  )
}

resource "aws_vpc_security_group_ingress_rule" "email_campaigns_vpce_from_alb" {
  security_group_id            = aws_security_group.email_campaigns_vpce_sg.id
  referenced_security_group_id = aws_security_group.proxy_load_balancer_security_group.id
  from_port                    = 443
  ip_protocol                  = "tcp"
  to_port                      = 443
}

# VPC Link v2 for REST API Gateway
# Traffic flow: API Gateway -> VPC Link v2 -> ALB -> VPC Endpoint (PrivateLink) -> fansifter NLB -> ALB -> Fargate
resource "aws_apigatewayv2_vpc_link" "email_campaigns_vpc_link" {
  name               = "${local.prefix}-ows-email-campaigns-vpc-link"
  security_group_ids = [aws_security_group.email_campaigns_vpc_link_sg.id]
  subnet_ids         = module.vpc_info.default_private_subnet_ids

  tags = merge(
    local.tags,
    {
      Name = "${local.prefix}-ows-email-campaigns-vpc-link"
    }
  )
}

resource "aws_lb" "proxy_load_balancer" {
  name                       = "${var.environment}-email-campaigns-vpc-proxy"
  internal                   = true
  load_balancer_type         = "application"
  idle_timeout               = 60
  security_groups            = [aws_security_group.proxy_load_balancer_security_group.id]
  subnets                    = module.vpc_info.default_private_subnet_ids
  enable_deletion_protection = true

  access_logs {
    bucket  = "shared-orcd-lb-logs"
    prefix  = "${data.aws_caller_identity.current.account_id}/${var.environment}-email-campaigns-vpc-proxy"
    enabled = true
  }

  tags = merge(
    local.tags,
    {
      Name = "${local.prefix}-email-campaigns-vpc-proxy"
    }
  )
}

resource "aws_lb_listener" "proxy_load_balancer_https_listener" {
  load_balancer_arn = aws_lb.proxy_load_balancer.arn
  port              = 443
  protocol          = "HTTPS"
  ssl_policy        = "ELBSecurityPolicy-TLS13-1-2-2021-06"
  certificate_arn   = data.aws_acm_certificate.tls_cert.arn

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

  tags = merge(
    local.tags,
    {
      Name = "${local.prefix}-email-campaigns-vpc-proxy-https-listener"
    }
  )
}

resource "aws_lb_target_group" "proxy_load_balancer_target_group" {
  name        = "${var.environment}-email-campaigns-vpc-proxy"
  port        = 443
  protocol    = "HTTPS"
  vpc_id      = var.vpc_id
  target_type = "ip"

  health_check {
    enabled             = true
    healthy_threshold   = 3
    interval            = 10
    matcher             = "200-299"
    path                = "/hello/"
    port                = 443
    protocol            = "HTTPS"
    timeout             = 5
    unhealthy_threshold = 3
  }
}

data "aws_network_interface" "vpc_endpoint_enis" {
  for_each = aws_vpc_endpoint.email_campaigns.network_interface_ids
  id       = each.value
}

resource "aws_lb_target_group_attachment" "proxy_load_balancer_to_alb" {
  for_each         = data.aws_network_interface.vpc_endpoint_enis
  target_group_arn = aws_lb_target_group.proxy_load_balancer_target_group.arn
  target_id        = each.value.private_ip
  port             = 443
}

# Filter subnets to AZs supported by the fansifter VPC Endpoint Service
data "aws_vpc_endpoint_service" "email_campaigns" {
  service_name = var.email_campaigns_vpce_service_name
}

data "aws_subnets" "email_campaigns_vpce" {
  filter {
    name   = "vpc-id"
    values = [var.vpc_id]
  }
  filter {
    name   = "subnet-id"
    values = module.vpc_info.default_private_subnet_ids
  }
  filter {
    name   = "availability-zone"
    values = data.aws_vpc_endpoint_service.email_campaigns.availability_zones
  }
}

# PrivateLink VPC Endpoint to reach email-campaigns in fansifter account
resource "aws_vpc_endpoint" "email_campaigns" {
  vpc_id              = var.vpc_id
  service_name        = var.email_campaigns_vpce_service_name
  vpc_endpoint_type   = "Interface"
  subnet_ids          = data.aws_subnets.email_campaigns_vpce.ids
  security_group_ids  = [aws_security_group.email_campaigns_vpce_sg.id]
  private_dns_enabled = false

  tags = merge(
    local.tags,
    {
      Name = "${var.environment}-email-campaigns-vpce"
    }
  )
}

# /external/{source} resource
resource "aws_api_gateway_resource" "email_campaigns_source_resource" {
  rest_api_id = aws_api_gateway_rest_api.fan_response_rest_api.id
  parent_id   = aws_api_gateway_resource.external_root_resource.id
  path_part   = "{source}"
}

# /external/{source}/{campaignId} resource
resource "aws_api_gateway_resource" "email_campaigns_campaign_id_resource" {
  rest_api_id = aws_api_gateway_rest_api.fan_response_rest_api.id
  parent_id   = aws_api_gateway_resource.email_campaigns_source_resource.id
  path_part   = "{campaignId}"
}

# /external/{source}/{campaignId}/automated-emails resource
resource "aws_api_gateway_resource" "email_campaigns_automated_emails_resource" {
  rest_api_id = aws_api_gateway_rest_api.fan_response_rest_api.id
  parent_id   = aws_api_gateway_resource.email_campaigns_campaign_id_resource.id
  path_part   = "automated-emails"
}

# GET /external/{source}/{campaignId}/automated-emails method
resource "aws_api_gateway_method" "email_campaigns_automated_emails_get" {
  rest_api_id   = aws_api_gateway_rest_api.fan_response_rest_api.id
  resource_id   = aws_api_gateway_resource.email_campaigns_automated_emails_resource.id
  http_method   = "GET"
  authorization = "CUSTOM"
  authorizer_id = aws_api_gateway_authorizer.smf_fan_response_authorizer.id

  request_validator_id = aws_api_gateway_request_validator.fan_response_rest_api_validator.id

  request_parameters = {
    "method.request.path.source"     = true
    "method.request.path.campaignId" = true
  }
}

resource "aws_api_gateway_integration" "email_campaigns_automated_emails_integration" {
  rest_api_id             = aws_api_gateway_rest_api.fan_response_rest_api.id
  resource_id             = aws_api_gateway_resource.email_campaigns_automated_emails_resource.id
  http_method             = aws_api_gateway_method.email_campaigns_automated_emails_get.http_method
  integration_http_method = "GET"
  type                    = "HTTP_PROXY"

  uri = "https://${var.environment}-ows-email-campaigns.theorchard.io/source-campaigns/{source}/{campaignId}/automated-emails"

  connection_type    = "VPC_LINK"
  connection_id      = aws_apigatewayv2_vpc_link.email_campaigns_vpc_link.id
  integration_target = aws_lb.proxy_load_balancer.arn

  request_parameters = {
    "integration.request.header.Accept"           = "'application/json'"
    "integration.request.header.X-Forwarded-From" = "'api-gateway'"
    "integration.request.path.source"             = "method.request.path.source"
    "integration.request.path.campaignId"         = "method.request.path.campaignId"
  }

  depends_on = [
    aws_apigatewayv2_vpc_link.email_campaigns_vpc_link,
    aws_vpc_endpoint.email_campaigns,
  ]
}

# Method response for 200 OK
resource "aws_api_gateway_method_response" "email_campaigns_response_200" {
  rest_api_id = aws_api_gateway_rest_api.fan_response_rest_api.id
  resource_id = aws_api_gateway_resource.email_campaigns_automated_emails_resource.id
  http_method = aws_api_gateway_method.email_campaigns_automated_emails_get.http_method
  status_code = "200"

  response_models = {
    "application/json" = "Empty"
  }

  response_parameters = {
    "method.response.header.Access-Control-Allow-Origin" = true
  }
}

# Integration response for 200 OK
resource "aws_api_gateway_integration_response" "email_campaigns_response_200" {
  rest_api_id = aws_api_gateway_rest_api.fan_response_rest_api.id
  resource_id = aws_api_gateway_resource.email_campaigns_automated_emails_resource.id
  http_method = aws_api_gateway_method.email_campaigns_automated_emails_get.http_method
  status_code = aws_api_gateway_method_response.email_campaigns_response_200.status_code

  response_parameters = {
    "method.response.header.Access-Control-Allow-Origin" = "'*'"
  }

  depends_on = [
    aws_api_gateway_integration.email_campaigns_automated_emails_integration
  ]
}

# Method response for 4xx errors
resource "aws_api_gateway_method_response" "email_campaigns_response_4xx" {
  rest_api_id = aws_api_gateway_rest_api.fan_response_rest_api.id
  resource_id = aws_api_gateway_resource.email_campaigns_automated_emails_resource.id
  http_method = aws_api_gateway_method.email_campaigns_automated_emails_get.http_method
  status_code = "400"

  response_models = {
    "application/json" = "Empty"
  }

  response_parameters = {
    "method.response.header.Access-Control-Allow-Origin" = true
  }
}

# Integration response for 4xx errors
resource "aws_api_gateway_integration_response" "email_campaigns_response_4xx" {
  rest_api_id       = aws_api_gateway_rest_api.fan_response_rest_api.id
  resource_id       = aws_api_gateway_resource.email_campaigns_automated_emails_resource.id
  http_method       = aws_api_gateway_method.email_campaigns_automated_emails_get.http_method
  status_code       = "400"
  selection_pattern = "4\\d{2}"

  response_parameters = {
    "method.response.header.Access-Control-Allow-Origin" = "'*'"
  }

  depends_on = [
    aws_api_gateway_integration.email_campaigns_automated_emails_integration
  ]
}

# Method response for 5xx errors
resource "aws_api_gateway_method_response" "email_campaigns_response_5xx" {
  rest_api_id = aws_api_gateway_rest_api.fan_response_rest_api.id
  resource_id = aws_api_gateway_resource.email_campaigns_automated_emails_resource.id
  http_method = aws_api_gateway_method.email_campaigns_automated_emails_get.http_method
  status_code = "500"

  response_models = {
    "application/json" = "Empty"
  }

  response_parameters = {
    "method.response.header.Access-Control-Allow-Origin" = true
  }
}

# Integration response for 5xx errors
resource "aws_api_gateway_integration_response" "email_campaigns_response_5xx" {
  rest_api_id       = aws_api_gateway_rest_api.fan_response_rest_api.id
  resource_id       = aws_api_gateway_resource.email_campaigns_automated_emails_resource.id
  http_method       = aws_api_gateway_method.email_campaigns_automated_emails_get.http_method
  status_code       = "500"
  selection_pattern = "5\\d{2}"

  response_parameters = {
    "method.response.header.Access-Control-Allow-Origin" = "'*'"
  }

  depends_on = [
    aws_api_gateway_integration.email_campaigns_automated_emails_integration
  ]
}
