# VPC part
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,
    {
      service                  = "Networking",
      plat_env_project_service = "${local.aggregated_tag}_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,
    {
      service                  = "Networking",
      plat_env_project_service = "${local.aggregated_tag}_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,
    {
      service                  = "Networking",
      plat_env_project_service = "${local.aggregated_tag}_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,
    {
      service                  = "Networking",
      plat_env_project_service = "${local.aggregated_tag}_NTW"
    }
  )
}

module "main_nat_gateways" {
  source      = "../../modules/vpc/nat"
  name_prefix = local.name_prefix
  # Not using NAT gateway redundancy in dev
  public_subnet_ids = [module.main_public_subnets.subnet_ids[1]]
  common_tags = merge(
    local.common_tags,
    {
      service                  = "Networking",
      plat_env_project_service = "${local.aggregated_tag}_NTW"
    }
  )
}

# In some environments it's better to create multiple nat gateways, one per availability zone.
module "main_private_routing" {
  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
  common_tags = merge(
    local.common_tags,
    {
      service                  = "Networking",
      plat_env_project_service = "${local.aggregated_tag}_NTW"
    }
  )
}

# DB subnets without internet access
module "main_private_db_subnets" {
  source             = "../../modules/vpc/subnet"
  name_prefix        = local.name_prefix
  subnets            = var.private_db_subnets
  vpc_id             = module.main_vpc.vpc_id
  is_public          = false
  cidr_second_octet  = var.vpc["cidr_second_octet"]
  availability_zones = local.availability_zones
  custom_identifier  = "-db"
  common_tags = merge(
    local.common_tags,
    {
      service                  = "Networking",
      plat_env_project_service = "${local.aggregated_tag}_NTW"
    }
  )
}

module "main_private_db_routing" {
  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
  subnets               = module.main_private_db_subnets.subnet_ids
  disable_default_route = true
  common_tags = merge(
    local.common_tags,
    {
      service                  = "Networking",
      plat_env_project_service = "${local.aggregated_tag}_NTW"
    }
  )
}

module "nat_gateways" {
  source = "../../modules/vpc/whitelist_nat_by_platform"
  allowed_envs = [
    "apollo dev",
    "apollo new dev",
    "apollo new qa",
    "apollo new stage",
    "apollo new uat",
    "apollo prod",
    "apollo new prod",
    "artistapp dev",
    "artistapp stage",
    "artistapp prod",
    "core dev",
    "core qa",
    "core uat",
    "core prod",
    "delphi dev",
    "delphi qa",
    "delphi stage",
    "delphi prod",
    "infra dev",
    "infra dev jenkins",
    "infra prod",
    "whitelist dev",
    "whitelist uat",
    "whitelist prod",
  ]
}

module "main_sg_map" {
  source                  = "../modules/sg_map"
  name_prefix             = local.name_prefix
  vpc_id                  = module.main_vpc.vpc_id
  vpn_masq_cidrs          = ["10.50.12.148/32"]
  projectgroup_whitelist  = var.projectgroup_whitelist
  external_https_access   = concat(var.artistapp_team, var.external_https_access)
  internal_https_access   = var.internal_https_access
  external_access_mode    = "mixed"
  github_ip_addr          = var.github_ip_addr
  nat_gateways            = module.nat_gateways.rules_list
  sentry_access           = var.sentry_access_from_public_ip
  managed_prefix_list_ids = [data.aws_ec2_managed_prefix_list.vpn_ny_users.id]

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

module "s3_endpoint" {
  source       = "../../modules/vpc/endpoint_gateway"
  service      = "s3"
  vpc_id       = module.main_vpc.vpc_id
  route_tables = local.all_routetables
  common_tags = merge(
    local.common_tags,
    {
      service                  = "Networking",
      plat_env_project_service = "${local.aggregated_tag}_NTW"
    }
  )
}

module "dynamodb_endpoint" {
  source       = "../../modules/vpc/endpoint_gateway"
  service      = "dynamodb"
  vpc_id       = module.main_vpc.vpc_id
  route_tables = local.all_routetables
  common_tags = merge(
    local.common_tags,
    {
      service                  = "Networking",
      plat_env_project_service = "${local.aggregated_tag}_NTW"
    }
  )
}

module "gsirt_regional_endpoints" {
  source = "../../modules/gsirt_regional_endpoints"
}

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"
    }
  )
}

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.route_table_id,
    module.main_public_routing.route_table_id,
    module.main_private_db_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.route_table_id,
    module.main_public_routing.route_table_id,
    module.main_private_db_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
}
