terraform {
  required_providers {
    aws = {
      source                = "hashicorp/aws"
      configuration_aliases = [aws.requester, aws.accepter]
    }
  }
}

data "aws_vpc" "requester" {
  provider   = aws.requester
  cidr_block = var.vpc_requester_cidr
}

data "aws_vpc" "accepter" {
  provider   = aws.accepter
  cidr_block = var.vpc_accepter_cidr
}

resource "aws_vpc_peering_connection" "this" {
  provider      = aws.requester
  peer_owner_id = var.accepter_account_id
  peer_vpc_id   = data.aws_vpc.accepter.id
  vpc_id        = data.aws_vpc.requester.id
  auto_accept   = false
  tags = merge(
    var.common_tags,
    {
      Name = var.connection_name,
    }
  )
}

resource "aws_vpc_peering_connection_options" "requester_options" {
  provider                  = aws.requester
  vpc_peering_connection_id = aws_vpc_peering_connection.this.id

  requester {
    allow_remote_vpc_dns_resolution = var.allow_remote_vpc_dns_resolution
  }
}

resource "aws_vpc_peering_connection_options" "accepter_options" {
  provider                  = aws.accepter
  vpc_peering_connection_id = aws_vpc_peering_connection.this.id

  accepter {
    allow_remote_vpc_dns_resolution = var.allow_remote_vpc_dns_resolution
  }
}

resource "aws_vpc_peering_connection_accepter" "this" {
  provider                  = aws.accepter
  vpc_peering_connection_id = aws_vpc_peering_connection.this.id
  auto_accept               = true
  tags = merge(
    var.common_tags,
    {
      Name = var.connection_name,
    }
  )
}

# Routing
data "aws_route_tables" "requester" {
  provider = aws.requester
  vpc_id   = data.aws_vpc.requester.id
}

data "aws_route_tables" "accepter" {
  provider = aws.accepter
  vpc_id   = data.aws_vpc.accepter.id
}

locals {
  requester_route_tables = length(var.requester_route_tables) == 0 ? tolist(data.aws_route_tables.requester.ids) : var.requester_route_tables
  accepter_route_tables  = length(var.accepter_route_tables) == 0 ? tolist(data.aws_route_tables.accepter.ids) : var.accepter_route_tables
  req_to_acc_dest_cidrs  = length(var.req_to_acc_dest_cidrs) == 0 ? [var.vpc_accepter_cidr] : var.req_to_acc_dest_cidrs
  acc_to_req_dest_cidrs  = length(var.acc_to_req_dest_cidrs) == 0 ? [var.vpc_requester_cidr] : var.acc_to_req_dest_cidrs
}

resource "aws_route" "requester_to_accepter" {
  provider                  = aws.requester
  count                     = length(local.requester_route_tables) * length(local.req_to_acc_dest_cidrs)
  route_table_id            = sort(tolist(local.requester_route_tables))[floor(count.index / length(local.req_to_acc_dest_cidrs))]
  destination_cidr_block    = local.req_to_acc_dest_cidrs[count.index % length(local.req_to_acc_dest_cidrs)]
  vpc_peering_connection_id = aws_vpc_peering_connection.this.id
}

resource "aws_route" "accepter_to_requester" {
  provider                  = aws.accepter
  count                     = length(local.accepter_route_tables) * length(local.acc_to_req_dest_cidrs)
  route_table_id            = sort(tolist(local.accepter_route_tables))[floor(count.index / length(local.acc_to_req_dest_cidrs))]
  destination_cidr_block    = local.acc_to_req_dest_cidrs[count.index % length(local.acc_to_req_dest_cidrs)]
  vpc_peering_connection_id = aws_vpc_peering_connection.this.id
}
