resource "aws_vpc" "this" {
  cidr_block           = var.vpc_cidr
  enable_dns_hostnames = true
  enable_dns_support   = true

  tags = merge(local.deployment_tags, {
    Name = "${var.name_prefix}-vpc"
  })
}

resource "aws_internet_gateway" "this" {
  vpc_id = aws_vpc.this.id

  tags = merge(local.deployment_tags, {
    Name = "${var.name_prefix}-igw"
  })
}

resource "aws_subnet" "public" {
  for_each = local.subnets

  vpc_id                  = aws_vpc.this.id
  cidr_block              = each.value.cidr
  availability_zone       = each.value.availability_zone
  map_public_ip_on_launch = true

  tags = merge(local.deployment_tags, {
    Name = "${var.name_prefix}-public-${each.value.availability_zone}"
    Tier = "public"
  })
}

resource "aws_route_table" "public" {
  vpc_id = aws_vpc.this.id

  route {
    cidr_block = "0.0.0.0/0"
    gateway_id = aws_internet_gateway.this.id
  }

  tags = merge(local.deployment_tags, {
    Name = "${var.name_prefix}-public"
  })
}

resource "aws_route_table_association" "public" {
  for_each = aws_subnet.public

  subnet_id      = each.value.id
  route_table_id = aws_route_table.public.id
}

resource "aws_security_group" "instance" {
  name_prefix = "${var.name_prefix}-instance-"
  description = "Public service ports and PrivateLink NLB targets; SSH is intentionally disabled"
  vpc_id      = aws_vpc.this.id

  tags = merge(local.deployment_tags, {
    Name = "${var.name_prefix}-instance"
  })

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_vpc_security_group_egress_rule" "instance_all" {
  security_group_id = aws_security_group.instance.id
  description       = "Package, registry, SSM, and AWS API access"
  ip_protocol       = "-1"
  cidr_ipv4         = "0.0.0.0/0"
  tags              = local.deployment_tags
}

resource "aws_vpc_security_group_ingress_rule" "public_services" {
  for_each = local.public_ports

  security_group_id = aws_security_group.instance.id
  description       = "Public ${each.key} test endpoint"
  ip_protocol       = "tcp"
  from_port         = each.value
  to_port           = each.value
  cidr_ipv4         = "0.0.0.0/0"
  tags              = local.deployment_tags
}

resource "aws_security_group" "kafka_nlb" {
  count = local.privatelink_enabled ? 1 : 0

  name_prefix = "${var.name_prefix}-kafka-nlb-"
  # AWS does not allow changing a security group description in place. Keep
  # the original value so consolidation does not replace the retained NLB SG.
  description = "Kafka PrivateLink NLB"
  vpc_id      = aws_vpc.this.id

  tags = merge(local.deployment_tags, {
    Name = "${var.name_prefix}-kafka-nlb"
  })

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_vpc_security_group_egress_rule" "kafka_nlb_all" {
  count = local.privatelink_enabled ? 1 : 0

  security_group_id = aws_security_group.kafka_nlb[0].id
  description       = "Forward MySQL and Kafka PrivateLink traffic to the instance"
  ip_protocol       = "-1"
  cidr_ipv4         = "0.0.0.0/0"
  tags              = local.deployment_tags
}

resource "aws_vpc_security_group_ingress_rule" "mysql_from_nlb" {
  count = local.privatelink_enabled ? 1 : 0

  security_group_id            = aws_security_group.instance.id
  description                  = "MySQL traffic from the shared PrivateLink NLB"
  ip_protocol                  = "tcp"
  from_port                    = local.ports.mysql
  to_port                      = local.ports.mysql
  referenced_security_group_id = aws_security_group.kafka_nlb[0].id
  tags                         = local.deployment_tags
}

resource "aws_vpc_security_group_ingress_rule" "kafka_pl_public_from_nlb" {
  count = local.privatelink_enabled ? 1 : 0

  security_group_id            = aws_security_group.instance.id
  description                  = "Anonymous Kafka traffic from the shared PrivateLink NLB"
  ip_protocol                  = "tcp"
  from_port                    = local.ports.kafka_pl_public
  to_port                      = local.ports.kafka_pl_public
  referenced_security_group_id = aws_security_group.kafka_nlb[0].id
  tags                         = local.deployment_tags
}

resource "aws_vpc_security_group_ingress_rule" "kafka_pl_sasl_from_nlb" {
  count = local.privatelink_enabled ? 1 : 0

  security_group_id            = aws_security_group.instance.id
  description                  = "SASL Kafka traffic from the shared PrivateLink NLB"
  ip_protocol                  = "tcp"
  from_port                    = local.ports.kafka_pl_sasl
  to_port                      = local.ports.kafka_pl_sasl
  referenced_security_group_id = aws_security_group.kafka_nlb[0].id
  tags                         = local.deployment_tags
}
