module "default_tags" {
  source             = "git@github.com:theorchard/terraform-default-tags.git//?ref=2.0.0"
  environment        = var.environment
  application_family = var.application_family
  team_name          = var.team_name
}

provider "aws" {
  region = "us-east-1"

  default_tags {
    tags = module.default_tags.tags
  }
}

terraform {
  backend "s3" {
    bucket  = "qa-accounting-terraform-state"
    key     = "uat/us_east_1_vpc/terraform.tfstate"
    region  = "us-east-1"
    encrypt = "true"
  }
}

module "vpc_info" {
  source = "git@github.com:theorchard/terraform-vpc-info.git?ref=3.0.2"

  environment = "qa"
}

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

# Add public subnets
resource "aws_subnet" "public_default" {
  for_each = { for subnet in var.vpc_public_subnets : subnet["cidr_block"] => subnet }

  vpc_id            = module.vpc_info.vpc_id
  cidr_block        = each.key
  availability_zone = each.value["availability_zone"]

  tags = {
    Name        = each.value["name"]
    Environment = var.environment
  }
}

data "aws_route_table" "public" {
  vpc_id = module.vpc_info.vpc_id
  tags = {
    Name = "qa_public_subnet_route"
  }
}

# Associate route table with public subnets
resource "aws_route_table_association" "public_default" {
  for_each = { for subnet in var.vpc_public_subnets : subnet["cidr_block"] => subnet }

  subnet_id      = aws_subnet.public_default[each.key].id
  route_table_id = data.aws_route_table.public.id
}

# Add public network acl
resource "aws_network_acl" "public_default_nacl" {
  for_each = { for subnet in var.vpc_public_subnets : subnet["cidr_block"] => subnet }

  vpc_id     = module.vpc_info.vpc_id
  subnet_ids = [aws_subnet.public_default[each.key].id]

  egress {
    protocol   = "-1"
    rule_no    = 2
    action     = "allow"
    cidr_block = "0.0.0.0/0"
    from_port  = 0
    to_port    = 0
  }

  ingress {
    protocol   = "-1"
    rule_no    = 1
    action     = "allow"
    cidr_block = "0.0.0.0/0"
    from_port  = 0
    to_port    = 0
  }

  tags = {
    Name        = "${each.value["name"]}_network_acl"
    Environment = var.environment
  }
}

# Add private subnets
resource "aws_subnet" "private_default" {
  for_each = { for subnet in var.vpc_private_subnets : subnet["cidr_block"] => subnet }

  vpc_id            = module.vpc_info.vpc_id
  cidr_block        = each.key
  availability_zone = each.value["availability_zone"]

  tags = {
    Name        = each.value["name"]
    Environment = var.environment
    tier        = "private"
  }
}

data "aws_route_table" "private" {
  for_each = { for subnet in var.vpc_private_subnets : subnet["availability_zone"] => subnet }

  vpc_id = module.vpc_info.vpc_id
  tags = {
    Name = "qa_private_route_table_${each.key}"
  }
}

# Associate route table with private subnets
resource "aws_route_table_association" "private" {
  for_each = { for subnet in var.vpc_private_subnets : subnet["cidr_block"] => subnet }

  subnet_id      = aws_subnet.private_default[each.key].id
  route_table_id = data.aws_route_table.private[each.value["availability_zone"]].id
}

# add private network acl
resource "aws_network_acl" "private_default_nacl" {
  for_each = { for subnet in var.vpc_private_subnets : subnet["cidr_block"] => subnet if subnet.create_nacl }

  vpc_id     = module.vpc_info.vpc_id
  subnet_ids = [aws_subnet.private_default[each.key].id]

  egress {
    protocol   = "-1"
    rule_no    = 2
    action     = "allow"
    cidr_block = "0.0.0.0/0"
    from_port  = 0
    to_port    = 0
  }

  ingress {
    protocol   = "-1"
    rule_no    = 1
    action     = "allow"
    cidr_block = "0.0.0.0/0"
    from_port  = 0
    to_port    = 0
  }

  tags = {
    Name        = "${each.value["name"]}_network_acl"
    Environment = var.environment
  }
}

resource "aws_ec2_managed_prefix_list" "public" {
  address_family = "IPv4"
  max_entries    = length(var.vpc_public_subnets)
  name           = "${var.environment}-${var.account_group}-public-subnet-prefix-list"

  dynamic "entry" {
    for_each = var.vpc_public_subnets
    content {
      cidr        = entry.value["cidr_block"]
      description = "${var.environment} ${var.account_group} public subnet ${entry.value["cidr_block"]} in ${entry.value["availability_zone"]}"
    }
  }

  tags = {
    account_group = var.account_group
    environment   = var.environment
    service_name  = "managed-prefix-list"
    subnet_group  = "all"
    subnet_type   = "public"
    tier          = "public"
    terraformed   = "true"
    vpc_id        = module.vpc_info.vpc_id
  }
}

resource "aws_ram_resource_share" "public_subnet" {
  name = "${var.environment}-${var.account_group}-public-subnet-managed-prefix-list-share"

  tags = {
    account_group = var.account_group
    environment   = var.environment
    service_name  = "managed-prefix-list"
    terraformed   = true
  }
}

resource "aws_ram_resource_association" "public_subnet_association" {
  resource_arn       = aws_ec2_managed_prefix_list.public.arn
  resource_share_arn = aws_ram_resource_share.public_subnet.arn
}

resource "aws_ram_principal_association" "public_subnet_principal_association" {
  for_each = var.org_ou_arn

  principal          = each.value
  resource_share_arn = aws_ram_resource_share.public_subnet.arn
}

resource "aws_ec2_managed_prefix_list" "private" {
  address_family = "IPv4"
  max_entries    = length(var.vpc_private_subnets)
  name           = "${var.environment}-${var.account_group}-private-subnet-prefix-list"

  dynamic "entry" {
    for_each = var.vpc_private_subnets
    content {
      cidr        = entry.value["cidr_block"]
      description = "${var.environment} ${var.account_group} private subnet ${entry.value["cidr_block"]} in ${entry.value["availability_zone"]}"
    }
  }

  tags = {
    account_group = var.account_group
    environment   = var.environment
    service_name  = "managed-prefix-list"
    subnet_group  = "all"
    subnet_type   = "private"
    tier          = "private"
    terraformed   = true
    vpc_id        = module.vpc_info.vpc_id
  }
}

resource "aws_ram_resource_share" "private_subnet" {
  name = "${var.environment}-${var.account_group}-private-subnet-managed-prefix-list-share"

  tags = {
    account_group = var.account_group
    environment   = var.environment
    service_name  = "managed-prefix-list"
    terraformed   = true
  }
}

resource "aws_ram_resource_association" "private_subnet_association" {
  resource_arn       = aws_ec2_managed_prefix_list.private.arn
  resource_share_arn = aws_ram_resource_share.private_subnet.arn
}

resource "aws_ram_principal_association" "private_subnet_principal_association" {
  for_each = var.org_ou_arn

  principal          = each.value
  resource_share_arn = aws_ram_resource_share.private_subnet.arn
}
