Parameters:
  App:
    Type: String
    Description: Your application's name.
  Env:
    Type: String
    Description: The name of the environment being deployed.
  # Customize your Aurora Serverless cluster by setting the default value of the following parameters.
  chatDBName:
    Type: String
    Description: The name of the initial database to be created in the Aurora Serverless v2 cluster.
    Default: chat
    # Cannot have special characters
    # Naming constraints: https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_Limits.html#RDS_Limits.Constraints
  VPCID:
    Type: String
    Description: The ID of the VPC in which to create the Aurora Serverless v2 cluster.
    Default: ""
  PrivateSubnets:
    Type: String
    Description: The IDs of the private subnets in which to create the Aurora Serverless v2 cluster.
    Default: ""

Conditions:
  IsSNDevEnv: !Equals [ !Ref Env, "sndev" ]

Mappings:
  chatEnvScalingConfigurationMap:
    All:
      "DBMinCapacity": 0.5 # AllowedValues: from 0.5 through 128
      "DBMaxCapacity": 8   # AllowedValues: from 0.5 through 128

Resources:
  chatDBSubnetGroup:
    Type: 'AWS::RDS::DBSubnetGroup'
    Properties:
      DBSubnetGroupDescription: Group of private subnets for Aurora Serverless v2 cluster.
      SubnetIds:
        !Split [',', !Ref PrivateSubnets]

  chatWorkloadSecurityGroup:
    Metadata:
      'aws:copilot:description': 'A security group for one or more workloads to access the Aurora Serverless v2 cluster chat'
    Type: 'AWS::EC2::SecurityGroup'
    Properties:
      GroupDescription: 'The Security Group to access Aurora Serverless v2 cluster chat.'
      VpcId: !Ref VPCID
      Tags:
        - Key: Name
          Value: !Sub 'copilot-${App}-${Env}-Aurora'

  chatDBClusterSecurityGroup:
    Metadata:
      'aws:copilot:description': 'A security group for your Aurora Serverless v2 cluster chat'
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: The Security Group for the Aurora Serverless v2 cluster.
      VpcId: !Ref VPCID
      SecurityGroupIngress:
        - IpProtocol: tcp
          FromPort: 5432
          ToPort: 5432
          SourceSecurityGroupId: { 'Fn::ImportValue': !Sub '${App}-${Env}-EnvironmentSecurityGroup' }
          Description: 'Access to environment security group'
      Tags:
        - Key: Name
          Value: !Sub 'copilot-${App}-${Env}-Aurora'

  chatDBClusterSecurityGroupIngressFromWorkload:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      Description: Ingress from one or more workloads in the environment.
      GroupId: !Ref chatDBClusterSecurityGroup
      IpProtocol: tcp
      ToPort: 5432
      FromPort: 5432
      SourceSecurityGroupId: !Ref chatWorkloadSecurityGroup

  chatAuroraSecret:
    Metadata:
      'aws:copilot:description': 'A Secrets Manager secret to store your DB credentials'
    Type: AWS::SecretsManager::Secret
    Properties:
      Description: !Sub Aurora main user secret for ${AWS::StackName}
      GenerateSecretString:
        SecretStringTemplate: '{"username": "postgres"}'
        GenerateStringKey: "password"
        ExcludePunctuation: true
        IncludeSpace: false
        PasswordLength: 16
  chatDBClusterParameterGroup:
    Metadata:
      'aws:copilot:description': 'A DB parameter group for engine configuration values'
    Type: 'AWS::RDS::DBClusterParameterGroup'
    Properties:
      Description: !Ref 'AWS::StackName'
      Family: 'aurora-postgresql16'
      Parameters:
        client_encoding: 'UTF8'

  chatDBCluster:
    Metadata:
      'aws:copilot:description': 'The chat Aurora Serverless v2 database cluster'
    Type: 'AWS::RDS::DBCluster'
    Properties:
      MasterUsername:
        !Join [ "",  [ '{{resolve:secretsmanager:', !Ref chatAuroraSecret, ":SecretString:username}}" ]]
      MasterUserPassword:
        !Join [ "",  [ '{{resolve:secretsmanager:', !Ref chatAuroraSecret, ":SecretString:password}}" ]]
      DatabaseName: !Ref chatDBName
      Engine: 'aurora-postgresql'
      EngineVersion: '16.1'
      DBClusterParameterGroupName: !Ref chatDBClusterParameterGroup
      DBSubnetGroupName: !Ref chatDBSubnetGroup
      Port: 5432
      VpcSecurityGroupIds:
        - !Ref chatDBClusterSecurityGroup
      ServerlessV2ScalingConfiguration:
        # Replace "All" below with "!Ref Env" to set different autoscaling limits per environment.
        MinCapacity: !FindInMap [chatEnvScalingConfigurationMap, All, DBMinCapacity]
        MaxCapacity: !FindInMap [chatEnvScalingConfigurationMap, All, DBMaxCapacity]

  chatDBWriterInstance:
    Metadata:
      'aws:copilot:description': 'The chat Aurora Serverless v2 writer instance'
    Type: 'AWS::RDS::DBInstance'
    Properties:
      DBClusterIdentifier: !Ref chatDBCluster
      DBInstanceClass: db.serverless
      Engine: 'aurora-postgresql'
      PromotionTier: 1
      AvailabilityZone: !Select
        - 0
        - !GetAZs
          Ref: AWS::Region

  chatSecretAuroraClusterAttachment:
    Type: AWS::SecretsManager::SecretTargetAttachment
    Properties:
      SecretId: !Ref chatAuroraSecret
      TargetId: !Ref chatDBCluster
      TargetType: AWS::RDS::DBCluster

Outputs:
  chatSecret:
    Description: "The JSON secret that holds the database username and password. Fields are 'host', 'port', 'dbname', 'username', 'password', 'dbClusterIdentifier' and 'engine'"
    Value: !Ref chatAuroraSecret
    Export:
      Name: !Sub ${App}-${Env}-chatAuroraSecret
  chatSecurityGroup:
    Description: "The security group to attach to the workload."
    Value: !Ref chatWorkloadSecurityGroup
    Export:
      Name: !Sub ${App}-${Env}-chatSecurityGroup