AWSTemplateFormatVersion: '2010-09-09'
Description: "Auto subnet VPC with dual NAT and route tables"

Parameters:
  VpcCidr:
    Type: String
    Default: 10.0.0.0/20
    Description: "VPC CIDR block (example: 10.0.0.0/20)"

  NamePrefix:
    Type: String
    Default: ha-compact
    Description: "Resource name prefix"

Resources:
  MainVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VpcCidr
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: !Sub "${NamePrefix}-vpc"

  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Sub "${NamePrefix}-igw"

  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref MainVPC
      InternetGatewayId: !Ref InternetGateway

  PublicSubnetA:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MainVPC
      CidrBlock: !Select [0, !Cidr [!Ref VpcCidr, 16, 8]]
      AvailabilityZone: !Select [0, !GetAZs ""]
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub "${NamePrefix}-pub-a"

  PublicSubnetB:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MainVPC
      CidrBlock: !Select [1, !Cidr [!Ref VpcCidr, 16, 8]]
      AvailabilityZone: !Select [1, !GetAZs ""]
      MapPublicIpOnLaunch: true
      Tags:
        - Key: Name
          Value: !Sub "${NamePrefix}-pub-b"

  AppPrivateSubnetA:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MainVPC
      CidrBlock: !Select [1, !Cidr [!Ref VpcCidr, 4, 10]]
      AvailabilityZone: !Select [0, !GetAZs ""]
      Tags:
        - Key: Name
          Value: !Sub "${NamePrefix}-app-a"

  AppPrivateSubnetB:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MainVPC
      CidrBlock: !Select [2, !Cidr [!Ref VpcCidr, 4, 10]]
      AvailabilityZone: !Select [1, !GetAZs ""]
      Tags:
        - Key: Name
          Value: !Sub "${NamePrefix}-app-b"

  DBPrivateSubnetA:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MainVPC
      CidrBlock: !Select [12, !Cidr [!Ref VpcCidr, 16, 8]]
      AvailabilityZone: !Select [0, !GetAZs ""]
      Tags:
        - Key: Name
          Value: !Sub "${NamePrefix}-db-a"

  DBPrivateSubnetB:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref MainVPC
      CidrBlock: !Select [13, !Cidr [!Ref VpcCidr, 16, 8]]
      AvailabilityZone: !Select [1, !GetAZs ""]
      Tags:
        - Key: Name
          Value: !Sub "${NamePrefix}-db-b"

  NatEipA:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc

  NatGatewayA:
    Type: AWS::EC2::NatGateway
    DependsOn: AttachGateway
    Properties:
      AllocationId: !GetAtt NatEipA.AllocationId
      SubnetId: !Ref PublicSubnetA
      Tags:
        - Key: Name
          Value: !Sub "${NamePrefix}-nat-gw-a"

  NatEipB:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc

  NatGatewayB:
    Type: AWS::EC2::NatGateway
    DependsOn: AttachGateway
    Properties:
      AllocationId: !GetAtt NatEipB.AllocationId
      SubnetId: !Ref PublicSubnetB
      Tags:
        - Key: Name
          Value: !Sub "${NamePrefix}-nat-gw-b"

  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref MainVPC
      Tags:
        - Key: Name
          Value: !Sub "${NamePrefix}-rtb-public"

  PublicRoute:
    Type: AWS::EC2::Route
    DependsOn: AttachGateway
    Properties:
      RouteTableId: !Ref PublicRouteTable
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway

  AppRouteTableA:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref MainVPC
      Tags:
        - Key: Name
          Value: !Sub "${NamePrefix}-rtb-app-a"

  AppRouteA:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref AppRouteTableA
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref NatGatewayA

  AppRouteTableB:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref MainVPC
      Tags:
        - Key: Name
          Value: !Sub "${NamePrefix}-rtb-app-b"

  AppRouteB:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref AppRouteTableB
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref NatGatewayB

  DBRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref MainVPC
      Tags:
        - Key: Name
          Value: !Sub "${NamePrefix}-rtb-db-isolated"

  PublicSubnetAAssoc:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnetA
      RouteTableId: !Ref PublicRouteTable

  PublicSubnetBAssoc:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnetB
      RouteTableId: !Ref PublicRouteTable

  AppSubnetAAssoc:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref AppPrivateSubnetA
      RouteTableId: !Ref AppRouteTableA

  AppSubnetBAssoc:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref AppPrivateSubnetB
      RouteTableId: !Ref AppRouteTableB

  DBSubnetAAssoc:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref DBPrivateSubnetA
      RouteTableId: !Ref DBRouteTable

  DBSubnetBAssoc:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref DBPrivateSubnetB
      RouteTableId: !Ref DBRouteTable

Outputs:
  VpcId:
    Value: !Ref MainVPC

  PublicSubnetAId:
    Value: !Ref PublicSubnetA

  PublicSubnetBId:
    Value: !Ref PublicSubnetB

  AppPrivateSubnetAId:
    Value: !Ref AppPrivateSubnetA

  AppPrivateSubnetBId:
    Value: !Ref AppPrivateSubnetB

  DBPrivateSubnetAId:
    Value: !Ref DBPrivateSubnetA

  DBPrivateSubnetBId:
    Value: !Ref DBPrivateSubnetB

  NatGatewayAId:
    Value: !Ref NatGatewayA

  NatGatewayBId:
    Value: !Ref NatGatewayB
