AWSTemplateFormatVersion: '2010-09-09'
Description: >
  StoreCon VPC Multi-AZ Architecture - Production-grade VPC with public/private/data subnets
  across two AZs, NAT Gateways, VPC Endpoints, and Security Groups for store computer migration.

Parameters:
  Environment:
    Type: String
    Default: dev
    AllowedValues: [dev, stg, prod]
  ProjectName:
    Type: String
    Default: storcon
  VpcCidr:
    Type: String
    Default: 10.0.0.0/16
    Description: VPC CIDR block # TODO: Adjust for actual network plan
  AZa:
    Type: AWS::EC2::AvailabilityZone::Name
    Default: ap-northeast-1a
  AZc:
    Type: AWS::EC2::AvailabilityZone::Name
    Default: ap-northeast-1c

Resources:
  # ============================================================
  # VPC
  # ============================================================
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: !Ref VpcCidr
      EnableDnsSupport: true
      EnableDnsHostnames: true
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-${Environment}-vpc"
        - Key: Project
          Value: !Ref ProjectName
        - Key: Environment
          Value: !Ref Environment

  # ============================================================
  # Internet Gateway
  # ============================================================
  InternetGateway:
    Type: AWS::EC2::InternetGateway
    Properties:
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-${Environment}-igw"

  IGWAttachment:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway

  # ============================================================
  # Public Subnets
  # ============================================================
  PublicSubnetA:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.1.0/24
      AvailabilityZone: !Ref AZa
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-${Environment}-public-a"

  PublicSubnetC:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.2.0/24
      AvailabilityZone: !Ref AZc
      MapPublicIpOnLaunch: false
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-${Environment}-public-c"

  # ============================================================
  # Private Subnets (Application)
  # ============================================================
  PrivateSubnetA:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.10.0/24
      AvailabilityZone: !Ref AZa
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-${Environment}-private-a"

  PrivateSubnetC:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.11.0/24
      AvailabilityZone: !Ref AZc
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-${Environment}-private-c"

  # ============================================================
  # Data Subnets (Database)
  # ============================================================
  DataSubnetA:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.20.0/24
      AvailabilityZone: !Ref AZa
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-${Environment}-data-a"

  DataSubnetC:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref VPC
      CidrBlock: 10.0.21.0/24
      AvailabilityZone: !Ref AZc
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-${Environment}-data-c"

  # ============================================================
  # NAT Gateways (one per AZ for HA)
  # ============================================================
  EipNatA:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-${Environment}-nat-eip-a"

  NatGatewayA:
    Type: AWS::EC2::NatGateway
    DependsOn: IGWAttachment
    Properties:
      AllocationId: !GetAtt EipNatA.AllocationId
      SubnetId: !Ref PublicSubnetA
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-${Environment}-nat-a"

  EipNatC:
    Type: AWS::EC2::EIP
    Properties:
      Domain: vpc
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-${Environment}-nat-eip-c"

  NatGatewayC:
    Type: AWS::EC2::NatGateway
    DependsOn: IGWAttachment
    Properties:
      AllocationId: !GetAtt EipNatC.AllocationId
      SubnetId: !Ref PublicSubnetC
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-${Environment}-nat-c"

  # ============================================================
  # Route Tables
  # ============================================================
  PublicRouteTable:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-${Environment}-public-rt"

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

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

  PublicSubnetCAssoc:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PublicSubnetC
      RouteTableId: !Ref PublicRouteTable

  PrivateRouteTableA:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-${Environment}-private-rt-a"

  PrivateRouteA:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PrivateRouteTableA
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref NatGatewayA

  PrivateSubnetAAssoc:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnetA
      RouteTableId: !Ref PrivateRouteTableA

  DataSubnetAAssoc:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref DataSubnetA
      RouteTableId: !Ref PrivateRouteTableA

  PrivateRouteTableC:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !Ref VPC
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-${Environment}-private-rt-c"

  PrivateRouteC:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref PrivateRouteTableC
      DestinationCidrBlock: 0.0.0.0/0
      NatGatewayId: !Ref NatGatewayC

  PrivateSubnetCAssoc:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref PrivateSubnetC
      RouteTableId: !Ref PrivateRouteTableC

  DataSubnetCAssoc:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref DataSubnetC
      RouteTableId: !Ref PrivateRouteTableC

  # ============================================================
  # Security Groups
  # ============================================================
  ALBSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security group for ALB - allows HTTPS inbound
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 443
          ToPort: 443
          CidrIp: 0.0.0.0/0
          Description: HTTPS from Internet (via CloudFront)
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-${Environment}-sg-alb"

  AppSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security group for ECS Fargate tasks
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 8080
          ToPort: 8080
          SourceSecurityGroupId: !Ref ALBSecurityGroup
          Description: App port from ALB only
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-${Environment}-sg-app"

  DataSecurityGroup:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: Security group for Aurora and ElastiCache
      VpcId: !Ref VPC
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 3306
          ToPort: 3306
          SourceSecurityGroupId: !Ref AppSecurityGroup
          Description: MySQL/Aurora from App SG
        - IpProtocol: tcp
          FromPort: 6379
          ToPort: 6379
          SourceSecurityGroupId: !Ref AppSecurityGroup
          Description: Redis from App SG
      Tags:
        - Key: Name
          Value: !Sub "${ProjectName}-${Environment}-sg-data"

  # ============================================================
  # VPC Endpoints
  # ============================================================
  S3GatewayEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcId: !Ref VPC
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.s3"
      VpcEndpointType: Gateway
      RouteTableIds:
        - !Ref PrivateRouteTableA
        - !Ref PrivateRouteTableC

  SecretsManagerEndpoint:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      VpcId: !Ref VPC
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.secretsmanager"
      VpcEndpointType: Interface
      SubnetIds:
        - !Ref PrivateSubnetA
        - !Ref PrivateSubnetC
      SecurityGroupIds:
        - !Ref AppSecurityGroup
      PrivateDnsEnabled: true

Outputs:
  VpcId:
    Description: VPC ID
    Value: !Ref VPC
    Export:
      Name: !Sub "${ProjectName}-${Environment}-VpcId"

  PublicSubnetIds:
    Description: Public Subnet IDs (comma-separated)
    Value: !Join [",", [!Ref PublicSubnetA, !Ref PublicSubnetC]]
    Export:
      Name: !Sub "${ProjectName}-${Environment}-PublicSubnetIds"

  PrivateSubnetIds:
    Description: Private Subnet IDs (comma-separated)
    Value: !Join [",", [!Ref PrivateSubnetA, !Ref PrivateSubnetC]]
    Export:
      Name: !Sub "${ProjectName}-${Environment}-PrivateSubnetIds"

  DataSubnetIds:
    Description: Data Subnet IDs (comma-separated)
    Value: !Join [",", [!Ref DataSubnetA, !Ref DataSubnetC]]
    Export:
      Name: !Sub "${ProjectName}-${Environment}-DataSubnetIds"

  ALBSecurityGroupId:
    Description: ALB Security Group ID
    Value: !Ref ALBSecurityGroup
    Export:
      Name: !Sub "${ProjectName}-${Environment}-ALBSgId"

  AppSecurityGroupId:
    Description: App Security Group ID
    Value: !Ref AppSecurityGroup
    Export:
      Name: !Sub "${ProjectName}-${Environment}-AppSgId"

  DataSecurityGroupId:
    Description: Data Security Group ID
    Value: !Ref DataSecurityGroup
    Export:
      Name: !Sub "${ProjectName}-${Environment}-DataSgId"
