import * as cdk from 'aws-cdk-lib';
import * as sqs from 'aws-cdk-lib/aws-sqs';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as lambdaEventSources from 'aws-cdk-lib/aws-lambda-event-sources';
import * as iam from 'aws-cdk-lib/aws-iam';
import { Construct } from 'constructs';
import * as secretManager from 'aws-cdk-lib/aws-secretsmanager';
export interface BackgroundJobStackProps extends cdk.StackProps {
  accountStage: string;
}
export class BackgroundJobStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props: BackgroundJobStackProps) {
    super(scope, id, props);

    // Create an SQS queue
    const queue = new sqs.Queue(this, 'DeleteClipsFromS3Queue', {
      visibilityTimeout: cdk.Duration.seconds(30),
      retentionPeriod: cdk.Duration.days(4),
      queueName: 'delete-clips-from-s3-queue',
    });

    const secret = secretManager.Secret.fromSecretNameV2(this, 'S3BucketCreds', `s3-bucket-creds`);

    // Create a Lambda function
    const DeleteClipsFromS3Lambda = new lambda.Function(this, 'DeleteClipsFromS3Lambda', {
      runtime: lambda.Runtime.PYTHON_3_10,
      handler: 'main.handler',
      code: lambda.Code.fromAsset('lambda/delete-clips-s3'), // Assumes your Lambda code is in the 'lambda' directory
      functionName: 'delete-clips-from-s3-lambda',
      environment: {
        QUEUE_URL: queue.queueUrl,
      },
      timeout: cdk.Duration.minutes(15),
    });

    // Grant the Lambda function permissions to read messages from the SQS queue
    queue.grantConsumeMessages(DeleteClipsFromS3Lambda);
    // Grant the Lambda function permissions to read the secret
    secret.grantRead(DeleteClipsFromS3Lambda);

    // Create an event source mapping to trigger the Lambda function when messages are available in the SQS queue
    const eventSource = new lambdaEventSources.SqsEventSource(queue, {
      batchSize: 10, // Process up to 10 messages at once
      maxBatchingWindow: cdk.Duration.seconds(5), // Wait up to 5 seconds for more messages
      reportBatchItemFailures: true, // Report failures for individual items in the batch
    });
    DeleteClipsFromS3Lambda.addEventSource(eventSource);

    // Override Logical ID for Event Source Mapping in staging environment
    if (props.accountStage === 'staging' || props.accountStage === 'prod') {
      cdk.Aspects.of(DeleteClipsFromS3Lambda).add({
        visit: (node: any) => {
          if (node.constructor.name === 'CfnEventSourceMapping') {
            node.overrideLogicalId('DeleteClipsFromS3LambdaSqsEventSourceBackgroundJobStackDeleteClipsFromS3Queue71CDDD3D0F2D7900');
          }
        }
      });
    }    

    // prod role
    if ('734185074900' === this.account) {
      // Create an IAM policy statement for S3 access
      const s3Policy = new iam.PolicyStatement({
        actions: ['s3:ListBucket', 's3:GetObject', 's3:PutObject', 's3:DeleteObject', 'sts:GetCallerIdentity'],
        resources: [
          'arn:aws:s3:::suno-data-uploads', // Replace with your actual bucket name
          'arn:aws:s3:::suno-data-uploads/*',
        ],
      });
      // Attach the policy to the Lambda function's role
      DeleteClipsFromS3Lambda.addToRolePolicy(s3Policy);
      // Role that allows staging lambda to access prod
      const crossAccountRole = new iam.Role(this, 'StagingAccountS3Role', {
        assumedBy: new iam.AccountPrincipal('590183763515'), // Replace with the staging account ID
        roleName: 'StagingAccountS3Role',
        inlinePolicies: {
          AllowS3Access: new iam.PolicyDocument({
            statements: [
              new iam.PolicyStatement({
                actions: ['s3:PutObject', 's3:GetObject', 's3:DeleteObject', 's3:ListBucket'],
                resources: ['arn:aws:s3:::suno-data-uploads', 'arn:aws:s3:::suno-data-uploads/*', 'arn:aws:s3:::suno-media-sour', 'arn:aws:s3:::suno-media-sour/*'],
              }),
            ],
          }),
        },
      });
    }

    // staging roles
    if ('590183763515' === this.account) {
      // Create an IAM policy statement to allow the Lambda function to assume the StagingLambdaAccessRole
      const assumeRolePolicy = new iam.PolicyStatement({
        actions: ['sts:AssumeRole', 'sts:GetCallerIdentity'],
        resources: ['arn:aws:iam::734185074900:role/StagingLambdaAccessRole'], // Replace with your actual role ARN
      });
      // Attach the assume role policy to the Lambda function's role
      DeleteClipsFromS3Lambda.addToRolePolicy(assumeRolePolicy);
    }
  }
}
