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 * as servicediscovery from 'aws-cdk-lib/aws-servicediscovery';
import { celerySecrets } from '../secrets/studio-api-celery-secrets';
export interface CeleryFlowerServiceProps {
  accountStage: string;
  cluster: ecs.Cluster;
  vpc: ec2.IVpc;
  subnets: ec2.ISubnet[];
  blueTargetGroup: ApplicationTargetGroup;
  loadBalancerSecurityGroup: ec2.SecurityGroup;
}

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

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

    const taskRole = new iam.Role(this, 'TaskRole', {
      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, 'CeleryFlowerExecutionRole', {
      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, 'StudioApiFlowerTaskDefinition', {
      cpu: 4096,
      memoryLimitMiB: 16384,
      taskRole: taskRole,
      executionRole: executionRole,
      runtimePlatform: {
        operatingSystemFamily: ecs.OperatingSystemFamily.LINUX,
        cpuArchitecture: ecs.CpuArchitecture.ARM64,
      },
      family: 'BackendInfraStackCeleryFlowerFargateServiceStudioApiFlowerTaskDefinition3A84993A',
    });

    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 container to the task definition
    const container = taskDefinition.addContainer('StudioApiFlowerContainer1', {
      image: ecs.ContainerImage.fromEcrRepository(repository, 'latest'),
      logging: new ecs.AwsLogDriver({
        streamPrefix: 'StudioApiFlowerContainer',
      }),
      healthCheck: {
        command: ['CMD-SHELL', `curl -f http://localhost:5555/healthcheck || exit 1`],
        interval: cdk.Duration.seconds(60),
        timeout: cdk.Duration.seconds(20),
        retries: 3,
        startPeriod: cdk.Duration.seconds(120),
      },
      secrets: { ...secretsStudio, ...secretsCelery },
      command: ['uv', 'run', '--no-dev', 'celery', '--app', 'studio_api', 'flower', '--basic-auth=admin:margu'],
      cpu: 4096,
      memoryLimitMiB: 16384,
      essential: true,
    });

    // Add port mappings to the container
    container.addPortMappings({
      containerPort: 5555,
    });

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

    // Allow traffic from the load balancer to the Fargate service on port 8005
    fargateServiceSecurityGroup.addIngressRule(props.loadBalancerSecurityGroup, ec2.Port.tcp(5555), 'Allow traffic from Load Balancer');

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

    // Attach the Fargate service to the blue target group initially
    this.service.attachToApplicationTargetGroup(props.blueTargetGroup);

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