#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from 'aws-cdk-lib';
import { GrpcEcrStack, GrpcEcrStackProps } from '../lib/ecr-stack/grpc-ecr-stack';
import { BackgroundJobStack, BackgroundJobStackProps } from '../lib/background-job-stack/background-job-stack';
import { BackendInfraStack, BackendInfraStackProps } from '../lib/backend-infra-stack/backend-infra-stack';
import { RedisCacheStack, RedisCacheStackProps } from '../lib/redis-cache-stack/redis-cache-stack';
import { MLServingStack, MLServingStackProps } from '../lib/ml-serving-stack/ml-serving-stack';
import * as AWS from 'aws-sdk';
import { CloudFrontStack, CloudFrontStackProps } from '../lib/cloud-front-stack/cloud-front-stack';
import { EventStreamStack, EventStreamStackProps } from '../lib/event-stream-stack/event-stream-stack';
import { ProdS3Stack, ProdS3StackProps } from '../lib/prod-s3-stack/prod-s3-stack';
import { MaxMindStack, MaxMindStackProps } from '../lib/maxmind-stack/stack';
import { GlueJobStack, GlueJobStackProps } from '../lib/glue-job-stack/glue-job-stack';
import { DBMonitorProps, DBMonitorStack } from '../lib/database-monitor-stack/database-monitor-stack';
import { AddMobileV4GensProps, AddMobileV4GensStack } from '../lib/add-mobile-v4-gens-db-update-stack/add-mobile-v4-gens-db-update-stack';
import { BackendEventStreamStack, BackendEventStreamStackProps } from '../lib/backend-event-stream-stack/backend-event-stream-stack';
import { ModalEventStreamStack, ModalEventStreamStackProps } from '../lib/modal-event-stream-stack/modal-event-stream-stack';
import { MultiRegionVpcStack, MultiRegionVpcStackProps } from '../lib/multi-region-suno-main-vpc-stack/multi-region-suno-main-vpc-stack';
import {
  BackendDeploymentNotificationStack,
  BackendDeploymentNotificationStackProps,
} from '../lib/backend-deployment-notification-stack/backend-deployment-notification-stack';
import { RedisAccessorStack, RedisAccessorStackProps } from '../lib/redis-accessor-stack/redis-accessor-stack';
import { CodePipelineStack, CodePipelineStackProps } from '../lib/code-pipeline-stack/code-pipeline-stack';
import { EcrStack } from '../lib/ecr-stack/ecr-stack';
import { CdkPipelineStack } from '../lib/cdk-pipeline-stack/cdk-pipeline-stack';
import { RecInfraStack, RecInfraStackProps } from '../lib/rec-infra-stack/rec-infra-stack';
import { DataLayerProxyStack, DataLayerProxyStackProps } from '../lib/data-layer-proxy-stack/data-layer-proxy-stack';
import { CeleryPipelineStack, CeleryPipelineStackProps } from '../lib/code-pipeline-stack/celery-pipeline-stack';
import { CeleryFlowerPipelineStack, CeleryFlowerPipelineStackProps } from '../lib/code-pipeline-stack/celery-flower-pipeline-stack';

const app = new cdk.App();
// const REGION = 'us-east-1';
const REGION: string = 'us-east-2';
// const REGION = 'ap-southeast-1';
// const REGION = 'eu-central-1';

async function main() {
  let accountId: string;

  // In the pipeline's CodeBuild environment, credentials are provided by the IAM role.
  // We must use them instead of trying to read a local credentials file that doesn't exist.
  if (process.env.CODEBUILD_BUILD_ID) {
    const sts = new AWS.STS();
    const identity = await sts.getCallerIdentity().promise();
    accountId = identity.Account!;
  } else {
    // For local development, continue using the existing profile-based mechanism.
    // const profile = 'prod'; // Replace with your AWS profile name
    const profile = 'staging'; // Replace with your AWS profile name
    accountId = await getAccountId(profile);
  }

  const env: cdk.Environment = {
    // account: '734185074900', // suno prod
    // account: '590183763515', // suno staging
    // account: '992382411129', // suno dev
    account: accountId,
    region: REGION,
  };

  const accountStage = accountId === '734185074900' ? 'prod' : accountId === '590183763515' ? 'staging' : 'dev';

  if (REGION === 'us-east-1') {
    new ProdS3Stack(app, 'ProdS3Stack', { env, account: env.account, accountStage: accountStage, region: REGION } as ProdS3StackProps);
    return;
  }

  // Only run CodePipelineStack in dev environment
  if (accountStage === 'dev') {
    new CodePipelineStack(app, 'CodePipelineStack', { env, accountStage } as CodePipelineStackProps);
    new CeleryPipelineStack(app, 'CeleryPipelineStack', { env, accountStage } as CeleryPipelineStackProps);
    new CeleryFlowerPipelineStack(app, 'CeleryFlowerPipelineStack', { env, accountStage } as CeleryFlowerPipelineStackProps);
    new CdkPipelineStack(app, 'CdkPipelineStack', { env });
    return; // Exit early, don't run other stacks
  }

  // Run all other stacks only for staging and prod environments
  new BackendInfraStack(app, 'BackendInfraStack', { env, accountStage } as BackendInfraStackProps);
  new BackgroundJobStack(app, 'BackgroundJobStack', { env, accountStage } as BackgroundJobStackProps);
  new RedisCacheStack(app, 'RedisCacheStack', { env, accountStage } as RedisCacheStackProps);
  new MLServingStack(app, 'MLServingStack', { env, accountStage } as MLServingStackProps);
  new GrpcEcrStack(app, 'GrpcEcrStack', { env, accountStage } as GrpcEcrStackProps);
  new CloudFrontStack(app, 'CloudFrontStack', { env, accountStage } as CloudFrontStackProps);
  new MaxMindStack(app, 'MaxMindStack', {
    env,
    account: env.account,
    region: env.region,
    accountStage: accountStage,
  } as MaxMindStackProps);
  new EventStreamStack(app, 'EventStreamStack', {
    env,
    account: env.account,
    region: env.region,
    accountStage: accountStage,
  } as EventStreamStackProps);
  new GlueJobStack(app, 'GlueJobStack', { env, accountStage } as GlueJobStackProps);
  new DBMonitorStack(app, 'DBMonitorStack', { env, accountStage } as DBMonitorProps);
  new AddMobileV4GensStack(app, 'AddMobileV4GensStack', { env, accountStage } as AddMobileV4GensProps);
  new BackendEventStreamStack(app, 'BackendEventStreamStack', {
    env,
    account: env.account,
    region: env.region,
    accountStage: accountStage,
  } as BackendEventStreamStackProps);
  new ModalEventStreamStack(app, 'ModalEventStreamStack', {
    env,
    account: env.account,
    region: env.region,
    accountStage: accountStage,
  } as ModalEventStreamStackProps);
  new MultiRegionVpcStack(app, 'MultiRegionVpcStack', { env, accountStage, region: REGION } as MultiRegionVpcStackProps);
  new BackendDeploymentNotificationStack(app, 'BackendDeploymentNotificationStack', { env, accountStage } as BackendDeploymentNotificationStackProps);
  new RedisAccessorStack(app, 'RedisAccessorStack', { env, accountStage } as RedisAccessorStackProps);
  new RecInfraStack(app, 'RecInfraStack', { env, accountStage } as RecInfraStackProps);
  new DataLayerProxyStack(app, 'DataLayerProxyStack', { env, accountStage } as DataLayerProxyStackProps);
}

async function getAccountId(profile: string): Promise<string> {
  const credentials = new AWS.SharedIniFileCredentials({ profile });
  const sts = new AWS.STS({ credentials });
  const identity = await sts.getCallerIdentity().promise();
  return identity.Account!;
}

main().catch((error) => {
  console.error(error);
  process.exit(1);
});
