###############################################################################
# VPC
###############################################################################

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

  tags = {
    Name        = "${var.project}-${var.environment}-vpc"
    Project     = var.project
    Environment = var.environment
  }
}

###############################################################################
# Internet Gateway
###############################################################################

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

  tags = {
    Name    = "${var.project}-${var.environment}-igw"
    Project = var.project
  }
}

###############################################################################
# Subnets
###############################################################################

# Public subnets (for ALB). Production predates this module and uses
# 10.0.1.0/24 + 10.0.2.0/24; preserve those adoption-safe identities.
resource "aws_subnet" "public" {
  count                   = length(var.azs)
  vpc_id                  = aws_vpc.this.id
  cidr_block              = cidrsubnet(var.vpc_cidr, 8, 1 + count.index)
  availability_zone       = var.azs[count.index]
  map_public_ip_on_launch = false

  tags = {
    Name    = "${var.project}-${var.environment}-public-${substr(var.azs[count.index], -1, 1)}"
    Project = var.project
  }
}

# Private app subnets (for EC2) — cidrsubnet(/16, 8, 10) = 10.0.10.0/24, cidrsubnet(/16, 8, 11) = 10.0.11.0/24
resource "aws_subnet" "private_app" {
  count             = length(var.azs)
  vpc_id            = aws_vpc.this.id
  cidr_block        = cidrsubnet(var.vpc_cidr, 8, 10 + count.index)
  availability_zone = var.azs[count.index]

  tags = {
    Name    = "${var.project}-${var.environment}-app-${substr(var.azs[count.index], -1, 1)}"
    Project = var.project
  }
}

# Private cache subnets (for ElastiCache) — cidrsubnet(/16, 8, 20) = 10.0.20.0/24, cidrsubnet(/16, 8, 21) = 10.0.21.0/24
resource "aws_subnet" "private_cache" {
  count             = length(var.azs)
  vpc_id            = aws_vpc.this.id
  cidr_block        = cidrsubnet(var.vpc_cidr, 8, 20 + count.index)
  availability_zone = var.azs[count.index]

  tags = {
    Name    = "${var.project}-${var.environment}-cache-${substr(var.azs[count.index], -1, 1)}"
    Project = var.project
  }
}

###############################################################################
# NAT Gateway (single, in first public subnet for cost savings)
###############################################################################

resource "aws_eip" "nat" {
  domain = "vpc"
}

resource "aws_nat_gateway" "this" {
  allocation_id = aws_eip.nat.id
  subnet_id     = aws_subnet.public[0].id

  tags = {
    Name    = "${var.project}-${var.environment}-nat"
    Project = var.project
  }

  depends_on = [aws_internet_gateway.this]
}

###############################################################################
# Route Tables
###############################################################################

# Public route table — routes to Internet Gateway
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 = {
    Name    = "${var.project}-${var.environment}-public-rt"
    Project = var.project
  }
}

# Private route table — routes to NAT Gateway
resource "aws_route_table" "private" {
  vpc_id = aws_vpc.this.id

  route {
    cidr_block     = "0.0.0.0/0"
    nat_gateway_id = aws_nat_gateway.this.id
  }

  tags = {
    Name    = "${var.project}-${var.environment}-private-rt"
    Project = var.project
  }
}

###############################################################################
# Route Table Associations
###############################################################################

resource "aws_route_table_association" "public" {
  count          = length(var.azs)
  subnet_id      = aws_subnet.public[count.index].id
  route_table_id = aws_route_table.public.id
}

resource "aws_route_table_association" "private_app" {
  count          = length(var.azs)
  subnet_id      = aws_subnet.private_app[count.index].id
  route_table_id = aws_route_table.private.id
}

resource "aws_route_table_association" "private_cache" {
  count          = length(var.azs)
  subnet_id      = aws_subnet.private_cache[count.index].id
  route_table_id = aws_route_table.private.id
}
