module "main_vpc" {
  source = "../../../modules/vpc/vpc_v2"

  name_prefix       = local.name_prefix
  cidr_second_octet = var.vpc["cidr_second_octet"]

  flow_logs = {
    gsirt = {
      log_destination      = "${data.aws_s3_bucket.security_logs.arn}/vpcflow/"
      log_destination_type = "s3"
      traffic_type         = "REJECT"
    }
  }

  common_tags = merge(
    local.common_tags,
    {
      project                  = "Infrastructure",
      service                  = "Networking",
      plat_env_project_service = "${local.aggregated_tag}_INFRA_NTW"
    }
  )
}

module "main_public_subnets" {
  source = "../../../modules/vpc/subnet"

  name_prefix        = local.name_prefix
  subnets            = var.public_subnets
  vpc_id             = module.main_vpc.vpc_id
  is_public          = true
  cidr_second_octet  = var.vpc["cidr_second_octet"]
  availability_zones = local.availability_zones

  common_tags = merge(
    local.common_tags,
    {
      project                  = "Infrastructure",
      service                  = "Networking",
      plat_env_project_service = "${local.aggregated_tag}_INFRA_NTW"
    }
  )
}

module "main_public_routing" {
  source = "../../../modules/vpc/routes"

  is_public   = true
  name_prefix = local.name_prefix
  vpc_id      = module.main_vpc.vpc_id
  vpc_cidr    = module.main_vpc.vpc_cidr
  igw_id      = module.main_vpc.vpc_igw
  subnets     = module.main_public_subnets.subnet_ids

  common_tags = merge(
    local.common_tags,
    {
      project                  = "Infrastructure",
      service                  = "Networking",
      plat_env_project_service = "${local.aggregated_tag}_INFRA_NTW"
    }
  )
}

module "main_private_subnets" {
  source = "../../../modules/vpc/subnet"

  name_prefix        = local.name_prefix
  subnets            = var.private_subnets
  vpc_id             = module.main_vpc.vpc_id
  is_public          = false
  cidr_second_octet  = var.vpc["cidr_second_octet"]
  availability_zones = local.availability_zones

  common_tags = merge(
    local.common_tags,
    {
      project                  = "Infrastructure",
      service                  = "Networking",
      plat_env_project_service = "${local.aggregated_tag}_INFRA_NTW"
    }
  )
}

module "main_nat_gateways" {
  source = "../../../modules/vpc/nat"

  name_prefix       = local.name_prefix
  public_subnet_ids = module.main_public_subnets.subnet_ids

  common_tags = merge(
    local.common_tags,
    {
      project                  = "Infrastructure",
      service                  = "Networking",
      plat_env_project_service = "${local.aggregated_tag}_INFRA_NTW"
    }
  )
}

# One route table per availability zone with NAT gateway. Copypasted since module doesn't support count right now.
module "main_private_routing_1" {
  source = "../../../modules/vpc/routes"

  is_public      = false
  name_prefix    = local.name_prefix
  vpc_id         = module.main_vpc.vpc_id
  vpc_cidr       = module.main_vpc.vpc_cidr
  nat_gateway_id = module.main_nat_gateways.nats[0].id
  subnets        = [module.main_private_subnets.subnet_ids[0]]

  common_tags = merge(
    local.common_tags,
    {
      project                  = "Infrastructure",
      service                  = "Networking",
      plat_env_project_service = "${local.aggregated_tag}_INFRA_NTW"
    }
  )
}

module "main_private_routing_2" {
  source = "../../../modules/vpc/routes"

  is_public      = false
  name_prefix    = local.name_prefix
  vpc_id         = module.main_vpc.vpc_id
  vpc_cidr       = module.main_vpc.vpc_cidr
  nat_gateway_id = module.main_nat_gateways.nats[1].id
  subnets        = [module.main_private_subnets.subnet_ids[1]]

  common_tags = merge(
    local.common_tags,
    {
      project                  = "Infrastructure",
      service                  = "Networking",
      plat_env_project_service = "${local.aggregated_tag}_INFRA_NTW"
    }
  )
}

module "main_private_routing_3" {
  source = "../../../modules/vpc/routes"

  is_public      = false
  name_prefix    = local.name_prefix
  vpc_id         = module.main_vpc.vpc_id
  vpc_cidr       = module.main_vpc.vpc_cidr
  nat_gateway_id = module.main_nat_gateways.nats[2].id
  subnets        = [module.main_private_subnets.subnet_ids[2]]

  common_tags = merge(
    local.common_tags,
    {
      project                  = "Infrastructure",
      service                  = "Networking",
      plat_env_project_service = "${local.aggregated_tag}_INFRA_NTW"
    }
  )
}

module "apollo-prod_delphi-prod" {
  source = "../../../modules/vpc/peering/one-to-one-external"

  vpc_requester_cidr  = "10.17.0.0/16"
  vpc_accepter_cidr   = "10.13.0.0/16"
  connection_name     = "APL_PROD_TO_DLP_PROD"
  accepter_account_id = module.aws_accounts_list.accounts["gdb-delphi-prod"]

  providers = {
    aws.requester = aws
    aws.accepter  = aws.gdb-delphi-prod
  }
}

module "gsirt_endpoint" {
  source = "../../../modules/vpc/endpoint_gateway"

  service           = module.gsirt_regional_endpoints.regional_endpoints_service_name[var.aws_region_id]
  vpc_endpoint_type = "Interface"
  subnet_ids        = module.main_private_subnets.subnet_ids
  vpc_id            = module.main_vpc.vpc_id
  cidr_second_octet = var.vpc["cidr_second_octet"]

  common_tags = merge(
    local.common_tags,
    {
      Name                     = format("%v-gsirt-endpoint", local.name_prefix)
      project                  = "Infrastructure",
      service                  = "Networking",
      plat_env_project_service = "${local.aggregated_tag}_INFRA_NTW"
    }
  )
}

resource "aws_security_group_rule" "apollo_new_uat_alb" {
  from_port         = 443
  to_port           = 443
  type              = "ingress"
  security_group_id = module.main_sg_map.alb_id
  protocol          = "tcp"
  cidr_blocks       = ["10.18.0.0/16"]
  description       = "Access from new Apollo UAT"
}

resource "aws_security_group_rule" "apollo_uat_ecs" {
  from_port                = 8000
  protocol                 = "tcp"
  security_group_id        = module.main_sg_map.ecs_id
  to_port                  = 8000
  type                     = "ingress"
  source_security_group_id = "${local.account_id}/sg-033fe735836bb5e0d" // uat-apollo-sg-ecs
}

resource "aws_security_group_rule" "apollo_legacy_prod_ecs" {
  from_port                = 8000
  protocol                 = "tcp"
  security_group_id        = module.main_sg_map.ecs_id
  to_port                  = 8000
  type                     = "ingress"
  source_security_group_id = "${module.aws_accounts_list.accounts["gdb-delphi-prod"]}/sg-0f46f91b76d76149c"
}

resource "aws_security_group_rule" "apollo_legacy_prod_alb" {
  from_port                = 443
  protocol                 = "tcp"
  security_group_id        = module.main_sg_map.alb_id
  to_port                  = 443
  type                     = "ingress"
  source_security_group_id = "${module.aws_accounts_list.accounts["gdb-delphi-prod"]}/sg-0f46f91b76d76149c"
}

resource "aws_security_group_rule" "apollo_legacy_ecs_redis" {
  from_port                = 6379
  protocol                 = "tcp"
  security_group_id        = module.main_sg_map.redis_id
  to_port                  = 6379
  type                     = "ingress"
  source_security_group_id = "${module.aws_accounts_list.accounts["gdb-delphi-prod"]}/sg-0f46f91b76d76149c"
}

locals {
  ingress-couchbase = {
    a = { from_port = 4369, to_port = 4369, description = "Allow inbound unencrypted node-to-node connections (erlang port mapper)." },
    b = { from_port = 9100, to_port = 9105, description = "Allow inbound unencrypted node-to-node connections (indexer)." },
    c = { from_port = 9110, to_port = 9118, description = "Allow inbound unencrypted node-to-node connections (Analytics)." },
    d = { from_port = 9120, to_port = 9122, description = "Allow inbound unencrypted node-to-node connections (Analytics)." },
    e = { from_port = 9130, to_port = 9130, description = "Allow inbound unencrypted node-to-node connections (gprc)." },
    f = { from_port = 9999, to_port = 9999, description = "Allow inbound unencrypted node-to-node connections (indexer)." },
    g = { from_port = 11209, to_port = 11210, description = "Allow inbound unencrypted node-to-node connections (memcached)." },
    h = { from_port = 21100, to_port = 21299, description = "Allow inbound encrypted node-to-node connections (memcached)." },
    i = { from_port = 8091, to_port = 8096, description = "Allow inbound unencrypted client connections to Couchbase." },
    j = { from_port = 18091, to_port = 18096, description = "Allow inbound encrypted client connections to Couchbase." },
    k = { from_port = 11210, to_port = 11211, description = "Allow inbound unencrypted client connections to Couchbase (memcached)." },
    l = { from_port = 11207, to_port = 11207, description = "Allow inbound encrypted client connections to Couchbase (memcached)." },
  }
}

resource "aws_security_group_rule" "apollo_legacy_win_couchbase" {
  for_each                 = local.ingress-couchbase
  from_port                = lookup(each.value, "from_port", 0)
  protocol                 = "tcp"
  security_group_id        = module.main_sg_map.couchbase_id
  source_security_group_id = "${module.aws_accounts_list.accounts["gdb-delphi-prod"]}/sg-05d635334ac1f088a"
  to_port                  = lookup(each.value, "to_port", 0)
  type                     = "ingress"
  description              = lookup(each.value, "description", "")
}

data "aws_ec2_transit_gateway" "transit_gateway" {
  filter {
    name   = "options.amazon-side-asn"
    values = ["64513"]
  }
}

data "aws_ec2_managed_prefix_list" "vpn_ny_users" {
  filter {
    name   = "prefix-list-name"
    values = ["vpn-ny-users"]
  }
}

data "aws_ec2_managed_prefix_list" "vpn_ny" {
  filter {
    name   = "prefix-list-name"
    values = ["vpn-ny"]
  }
}

data "aws_ec2_managed_prefix_list" "vpn_sme" {
  filter {
    name   = "prefix-list-name"
    values = ["vpn-sme-internal-primary"]
  }
}

resource "aws_ec2_transit_gateway_vpc_attachment" "transit_gateway_attachment" {
  vpc_id             = module.main_vpc.vpc_id
  transit_gateway_id = data.aws_ec2_transit_gateway.transit_gateway.id
  subnet_ids = concat(
    module.main_private_subnets.subnet_ids,
  )
}

resource "aws_route" "ny" {
  for_each = toset([
    module.main_private_routing_1.route_table_id,
    module.main_private_routing_2.route_table_id,
    module.main_private_routing_3.route_table_id,
    module.main_public_routing.route_table_id
  ])

  route_table_id             = each.value
  destination_prefix_list_id = data.aws_ec2_managed_prefix_list.vpn_ny.id
  transit_gateway_id         = data.aws_ec2_transit_gateway.transit_gateway.id
}

resource "aws_route" "sme" {
  for_each = toset([
    module.main_private_routing_1.route_table_id,
    module.main_private_routing_2.route_table_id,
    module.main_private_routing_3.route_table_id,
    module.main_public_routing.route_table_id
  ])

  route_table_id             = each.value
  destination_prefix_list_id = data.aws_ec2_managed_prefix_list.vpn_sme.id
  transit_gateway_id         = data.aws_ec2_transit_gateway.transit_gateway.id
}
