"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.PostgresRDSConstruct = void 0;
const secretsmanager = require("aws-cdk-lib/aws-secretsmanager");
const aws_rds_1 = require("aws-cdk-lib/aws-rds");
const aws_cdk_lib_1 = require("aws-cdk-lib");
const aws_ec2_1 = require("aws-cdk-lib/aws-ec2");
const constructs_1 = require("constructs");
;
class PostgresRDSConstruct extends constructs_1.Construct {
    constructor(scope, id, props) {
        var _a, _b, _c;
        super(scope, id);
        const stackName = aws_cdk_lib_1.Stack.of(this).stackName;
        /*
        * maxACU, minACU, and SGIngressRules are optional parameters
        */
        props = {
            ...props,
            maxACU: (_a = props.maxACU) !== null && _a !== void 0 ? _a : 8, // default to 8 ACU
            minACU: (_b = props.minACU) !== null && _b !== void 0 ? _b : 0, // default to 0 ACU is now possible
            SGIngressRules: (_c = props.SGIngressRules) !== null && _c !== void 0 ? _c : [],
        };
        const vpc = aws_ec2_1.Vpc.fromVpcAttributes(this, 'Vpc', {
            vpcId: props.useVpcId,
            availabilityZones: props.availabilityZones,
            privateSubnetIds: props.privateSubnetIds,
        });
        // Create a secret for the RDS credentials
        const rdsSecret = new secretsmanager.Secret(this, 'RdsSecret', {
            secretName: props.rdsPostgresSecret,
            description: 'RDS Postgres User for current DEC foundation',
            generateSecretString: {
                secretStringTemplate: JSON.stringify({ username: 'postgres' }),
                generateStringKey: 'password',
                excludeCharacters: '"@/\\',
            },
        });
        const parameterGroupDescription = `Parameter Group for ${props.dbClusterIdentifier}`;
        const auroraParameters = {};
        auroraParameters['timezone'] = 'US/Eastern';
        auroraParameters['idle_session_timeout'] = '60000'; // 1 minute idle timeout for any given session
        const libParameterGroup = new aws_rds_1.ParameterGroup(this, 'LibParameterGroup', {
            engine: aws_rds_1.DatabaseClusterEngine.auroraPostgres({
                version: props.pgVersion,
            }),
            description: parameterGroupDescription,
            parameters: auroraParameters,
        });
        const baseSGname = `${props.dbClusterIdentifier}-Base`;
        const accessSGname = `${props.dbClusterIdentifier}-Access`;
        const baseId = `${props.dbClusterIdentifier}-base`;
        const accessId = `${props.dbClusterIdentifier}-access`;
        const baseSG = new aws_ec2_1.SecurityGroup(this, baseId, {
            vpc: vpc,
            securityGroupName: baseSGname,
            description: 'Base Security Group',
        });
        const accessSG = new aws_ec2_1.SecurityGroup(this, accessId, {
            vpc: vpc,
            securityGroupName: accessSGname,
            description: 'Access Security Group',
        });
        accessSG.connections.allowFrom(baseSG, aws_ec2_1.Port.tcp(5432), 'Postgres to Base SG');
        baseSG.connections.allowFrom(accessSG, aws_ec2_1.Port.tcp(5432), 'Postgres to Access SG');
        const externalSGname = `${props.dbClusterIdentifier}-External`;
        const externalId = `${props.dbClusterIdentifier}-external`;
        const externalSG = new aws_ec2_1.SecurityGroup(this, externalId, {
            vpc: vpc,
            securityGroupName: externalSGname,
            description: 'Outside access Security Group',
            allowAllOutbound: true,
        });
        if (props.SGIngressRules) {
            props.SGIngressRules.forEach((rule) => {
                externalSG.addIngressRule(aws_ec2_1.Peer.ipv4(rule.ipv4), aws_ec2_1.Port.tcp(rule.port), rule.description);
            });
        }
        const dbCluster = new aws_rds_1.DatabaseCluster(this, 'peered-DBCluster', {
            clusterIdentifier: props.dbClusterIdentifier,
            instanceIdentifierBase: props.dbClusterIdentifier,
            credentials: aws_rds_1.Credentials.fromSecret(rdsSecret),
            engine: aws_rds_1.DatabaseClusterEngine.auroraPostgres({ version: props.dbFullVersion }),
            securityGroups: [baseSG, accessSG, externalSG],
            serverlessV2MinCapacity: props.minACU,
            serverlessV2MaxCapacity: props.maxACU,
            storageEncrypted: true,
            parameterGroup: libParameterGroup,
            vpc: vpc,
            enableDataApi: true,
            storageType: aws_rds_1.DBClusterStorageType.AURORA_IOPT1,
            deletionProtection: true,
            writer: aws_rds_1.ClusterInstance.serverlessV2('writer'),
            vpcSubnets: vpc.selectSubnets({
                subnetType: aws_ec2_1.SubnetType.PRIVATE_WITH_EGRESS,
            }),
            port: 5432,
        });
        this.accessSGID = accessSG.securityGroupId;
        new aws_cdk_lib_1.CfnOutput(this, 'DatabaseEndpoint', {
            description: 'The connection endpoint for the database server',
            value: dbCluster.clusterEndpoint.hostname,
            exportName: `${id}:DatabaseEndpoint`,
        });
        new aws_cdk_lib_1.CfnOutput(this, 'AccessSecurityGroup', {
            description: 'The Access Security Group for the instance',
            value: accessSG.securityGroupId,
            exportName: `${id}:AccessSecurityGroup`,
        });
        new aws_cdk_lib_1.CfnOutput(this, 'ExternalSecurityGroup', {
            description: 'The External Security Group for the instance',
            value: externalSG.securityGroupId,
            exportName: `${id}:ExternalSecurityGroup`,
        });
    }
}
exports.PostgresRDSConstruct = PostgresRDSConstruct;
module.exports = { PostgresRDSConstruct };
