import * as cdk from 'aws-cdk-lib';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as ecs from 'aws-cdk-lib/aws-ecs';
import * as ecr from 'aws-cdk-lib/aws-ecr';
import * as codedeploy from 'aws-cdk-lib/aws-codedeploy';
import { Construct } from 'constructs';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as iam from 'aws-cdk-lib/aws-iam';
import * as events from 'aws-cdk-lib/aws-events';
import * as targets from 'aws-cdk-lib/aws-events-targets';
import { ApplicationTargetGroup, ApplicationListener } from 'aws-cdk-lib/aws-elasticloadbalancingv2';
import { studioSecrets } from '../secrets/studio-secrets';
import { celerySecrets } from '../secrets/studio-api-celery-secrets';

export interface CeleryServiceProps {
  accountStage: string;
  cluster: ecs.Cluster;
  vpc: ec2.IVpc;
  subnets: ec2.ISubnet[];
}

export class CeleryBeatService extends Construct {
  public service: ecs.FargateService;

  constructor(scope: Construct, id: string, props: CeleryServiceProps) {
    super(scope, id);

    const taskRole = new iam.Role(this, 'CeleryBeatTaskRole', {
      assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'),
      managedPolicies: [
        iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AmazonECSTaskExecutionRolePolicy'),
        iam.ManagedPolicy.fromAwsManagedPolicyName('AmazonSSMManagedInstanceCore'),
      ],
    });

    // Create a dedicated execution role with custom policy
    const executionRole = new iam.Role(this, 'CeleryBeatExecutionRole', {
      assumedBy: new iam.ServicePrincipal('ecs-tasks.amazonaws.com'),
    });

    // Add the complete execution role policy based on your existing policy
    executionRole.addToPolicy(new iam.PolicyStatement({
      effect: iam.Effect.ALLOW,
      actions: [
        'ecr:BatchCheckLayerAvailability',
        'ecr:BatchGetImage',
        'ecr:GetDownloadUrlForLayer',
        'ecr:GetAuthorizationToken',
      ],
      resources: ['*'], 
    }));

    // Add CloudWatch Logs permissions
    executionRole.addToPolicy(new iam.PolicyStatement({
      effect: iam.Effect.ALLOW,
      actions: [
        'logs:CreateLogStream',
        'logs:PutLogEvents',
      ],
      resources: [`arn:aws:logs:${cdk.Aws.REGION}:${cdk.Aws.ACCOUNT_ID}:log-group:*`],
    }));

    // Add Secrets Manager permissions  
    executionRole.addToPolicy(new iam.PolicyStatement({
      effect: iam.Effect.ALLOW,
      actions: [
        'secretsmanager:DescribeSecret',
        'secretsmanager:GetSecretValue',
      ],
      resources: [
        `arn:aws:secretsmanager:${cdk.Aws.REGION}:${cdk.Aws.ACCOUNT_ID}:secret:*`,
      ],
    }));

    // Define a Fargate task definition
    const taskDefinition = new ecs.FargateTaskDefinition(this, 'CeleryBeatTaskDefinition', {
      memoryLimitMiB: 1024,
      cpu: 512,
      taskRole: taskRole,
      executionRole: executionRole,
      runtimePlatform: {
        operatingSystemFamily: ecs.OperatingSystemFamily.LINUX,
        cpuArchitecture: ecs.CpuArchitecture.ARM64,
      },
      family: 'BackendInfraStackCeleryBeatFargateServiceCeleryBeatTaskDefinitionD3A8CAEC',
    });

    const repository = ecr.Repository.fromRepositoryAttributes(this, 'studioApiRepository', {
      repositoryArn: `arn:aws:ecr:${cdk.Aws.REGION}:${cdk.Aws.ACCOUNT_ID}:repository/studio-api`,
      repositoryName: 'studio-api',
    });
    const secretsStudio = studioSecrets(this, props.accountStage, false);
    const secretsCelery = celerySecrets(this, props.accountStage);

    // Add a celery beat container to the task definition
    const celeryBeatContainer = taskDefinition.addContainer('StudioApiCeleryBeatContainer1', {
      image: ecs.ContainerImage.fromEcrRepository(repository, 'latest'),
      logging: new ecs.AwsLogDriver({
        streamPrefix: 'CeleryBeatContainer',
      }),
      secrets: { ...secretsStudio, ...secretsCelery },
      cpu: 512,
      memoryLimitMiB: 1024,
      command: ['uv', 'run', '--no-dev', 'celery', '--app', 'studio_api', 'beat', '-l', 'info'],
      essential: true,
    });

    // Create a security group for the Fargate service
    const fargateServiceSecurityGroup = new ec2.SecurityGroup(this, 'FargateServiceSG', {
      vpc: props.vpc,
      allowAllOutbound: true,
    });

    // Define the Fargate service
    this.service = new ecs.FargateService(this, 'CeleryBeatFargateService', {
      cluster: props.cluster,
      taskDefinition: taskDefinition,
      serviceName: 'CeleryBeatService',
      deploymentController: {
        type: ecs.DeploymentControllerType.ECS,
      },
      securityGroups: [fargateServiceSecurityGroup],
      vpcSubnets: {
        subnets: props.subnets,
      },
      enableExecuteCommand: true,
      desiredCount: 1,
    });

    // Enable auto-scaling for the Fargate service
    const scalableTarget = this.service.autoScaleTaskCount({
      minCapacity: 1,
      maxCapacity: 1,
    });
  }
}
