import * as aws from "@pulumi/aws";
import * as pulumi from "@pulumi/pulumi";
import { createAuroraDb, createDbReplica } from "./aurora-db";

const config = new pulumi.Config();
const org = config.require("org");
const stack = pulumi.getStack();
const availabilityZones = aws.getAvailabilityZones({
  state: "available",
});
const stackRef = new pulumi.StackReference(`${org}/k8s-cluster/${stack}`);
const privateSubnetGroupName = stackRef.getOutput(
  "privateDatabaseSubnetGroupName"
) as unknown as string;
const vpcId = stackRef.getOutput("vpcId");
const awsRegion = aws.getRegion({});

// Create a security group that allows all traffic to the RDS instance.
const securityGroup = new aws.ec2.SecurityGroup("suno-aurora-db-sg", {
  vpcId: vpcId,
  description: "Allow all traffic to RDS",
});
new aws.vpc.SecurityGroupIngressRule("suno-db-sg-ingress", {
  securityGroupId: securityGroup.id,
  ipProtocol: "tcp",
  fromPort: 5432,
  toPort: 5432,
  cidrIpv4: "0.0.0.0/0",
});

new aws.vpc.SecurityGroupEgressRule("suno-db-sg-egress", {
  securityGroupId: securityGroup.id,
  ipProtocol: "-1",
  cidrIpv4: "0.0.0.0/0",
});

const privateDatabaseSubnetGroup = aws.rds.getSubnetGroup({
  name: privateSubnetGroupName,
});

const mainDbAppUserSecret = new aws.secretsmanager.Secret(
  "app-user-main-db-secret",
  {
    name: "app-user-main-db-secret",
    description: "Secret for Main DB app user",
  }
);

// Add the secret values
new aws.secretsmanager.SecretVersion("app-user-main-db-secret-version", {
  secretId: mainDbAppUserSecret.id,
  secretString: JSON.stringify({
    username: config.require("mainDbAppUsername"),
    password: config.require("mainDbAppUserPassword"),
  }),
});

const sunoMainDbName = `suno-main-pgdb-${stack}`;
const sunoMainDbObjs = createAuroraDb({
  clusterName: sunoMainDbName,
  databaseName: "suno_main",
  replicaCount: 2,
  instanceType: "db.r6g.16xlarge",
  publiclyAccessible: false,
  awsRegion,
  availabilityZones,
  subnetGroup: privateDatabaseSubnetGroup,
  securityGroup,
  dbAppUserSecret: mainDbAppUserSecret,
});

const analyticsReplica = createDbReplica({
  replicaName: `${sunoMainDbName}-analytics`,
  postgresqlCluster: sunoMainDbObjs.postgresqlCluster,
  instanceType: "db.r6g.16xlarge",
  publiclyAccessible: false,
  promotionTier: 15, // lowest tier allowed to ensure it is not promoted except as a last resort
});

const allMainDbInstanceEndpoints = sunoMainDbObjs.dbReplicas.map((instance) => {
  return instance.endpoint;
});
allMainDbInstanceEndpoints.push(analyticsReplica.endpoint);

// create a custom read endpoint excluding the analytics replica.
const sunoMainCustomReaderEndpoint = new aws.rds.ClusterEndpoint(
  "custom-reader-endpoint",
  {
    clusterIdentifier: sunoMainDbObjs.postgresqlCluster.id,
    clusterEndpointIdentifier: "custom-reader-endpoint",
    customEndpointType: "READER",
    excludedMembers: [analyticsReplica.id],
  }
);

const sunoChopinDbName = `suno-chopin-pgdb-${stack}`;
const sunoChopinDbObjs = createAuroraDb({
  clusterName: sunoChopinDbName,
  databaseName: "chopin",
  replicaCount: 2,
  instanceType: "db.r6g.2xlarge",
  publiclyAccessible: false,
  awsRegion,
  availabilityZones,
  subnetGroup: privateDatabaseSubnetGroup,
  securityGroup,
});
const allChopinDbInstanceEndpoints = sunoChopinDbObjs.dbReplicas.map(
  (instance) => {
    return instance.endpoint;
  }
);

// Export the cluster and proxy endpoints to access the database
export const sunoMainDbEndpoint = sunoMainDbObjs.postgresqlCluster.endpoint;
export const sunoMainDbCustomReaderEndpoint =
  sunoMainCustomReaderEndpoint.endpoint;
export const sunoMainreadWriteProxyEndpoint = sunoMainDbObjs.proxy.endpoint;
export const sunoMainreadOnlyProxyEndpoint =
  sunoMainDbObjs.readOnlyProxy.endpoint;
export const sunoMainDbSecretArn =
  sunoMainDbObjs.postgresqlCluster.masterUserSecrets[0].secretArn;
export const sunoMainAnalyticsReplicaEndpoint = analyticsReplica.endpoint;
export const sunoMainAllReplicaEndpoints = allMainDbInstanceEndpoints;
export const sunoMainDbClusterIdentifier =
  sunoMainDbObjs.postgresqlCluster.clusterIdentifier;

export const sunoChopinDbEndpoint = sunoChopinDbObjs.postgresqlCluster.endpoint;
export const sunoChopinDbReaderEndpoint =
  sunoChopinDbObjs.postgresqlCluster.readerEndpoint;
export const sunoChopinreadWriteProxyEndpoint = sunoChopinDbObjs.proxy.endpoint;
export const sunoChopinreadOnlyProxyEndpoint =
  sunoChopinDbObjs.readOnlyProxy.endpoint;
export const sunoChopinDbSecretArn =
  sunoChopinDbObjs.postgresqlCluster.masterUserSecrets[0].secretArn;
export const sunoChopinAllReplicaEndpoints = allChopinDbInstanceEndpoints;
export const sunoChopinDbClusterIdentifier =
  sunoChopinDbObjs.postgresqlCluster.clusterIdentifier;
