import * as cdk from 'aws-cdk-lib';
import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2';
import { IVpc } from 'aws-cdk-lib/aws-ec2';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import { Construct } from 'constructs';
import { certificate } from '../certificate/studio-api-certificate'; // Import the certificate
import * as certManager from 'aws-cdk-lib/aws-certificatemanager';

export const setupWebSocketLoadBalancer = (scope: Construct, vpc: IVpc, subnets: ec2.ISubnet[], certificate: certManager.ICertificate) => {
  // Create a security group for the load balancer
  const webSocketLoadBalancerSecurityGroup = new ec2.SecurityGroup(scope, 'WebSocketLoadBalancerSG', {
    vpc: vpc,
    allowAllOutbound: true,
    description: 'BackendInfraStack/websocketLoadBalancer/WebSocketLoadBalancerSG',
  });

  const allowedIpRanges = [
    '103.21.244.0/22',
    '103.22.200.0/22',
    '103.31.4.0/22',
    '104.16.0.0/13',
    '104.24.0.0/14',
    '108.162.192.0/18',
    '131.0.72.0/22',
    '141.101.64.0/18',
    '162.158.0.0/15',
    '172.64.0.0/13',
    '173.245.48.0/20',
    '188.114.96.0/20',
    '190.93.240.0/20',
    '197.234.240.0/22',
    '198.41.128.0/17',
  ];

  // Add ingress rules for each allowed IP range
  allowedIpRanges.forEach((ipRange) => {
    webSocketLoadBalancerSecurityGroup.addIngressRule(ec2.Peer.ipv4(ipRange), ec2.Port.tcp(80), 'Allow HTTP traffic');
    webSocketLoadBalancerSecurityGroup.addIngressRule(ec2.Peer.ipv4(ipRange), ec2.Port.tcp(443), 'Allow HTTPS traffic');
  });

  const loadBalancer = new elbv2.ApplicationLoadBalancer(scope, 'WebSocketLoadBalancer', {
    vpc,
    vpcSubnets: {
      subnets: subnets,
    },
    internetFacing: true,
    securityGroup: webSocketLoadBalancerSecurityGroup,
    idleTimeout: cdk.Duration.seconds(300),
  });

  const blueTargetGroup = new elbv2.ApplicationTargetGroup(scope, 'WebSocketBlueTargetGroup', {
    vpc,
    port: 9090,
    protocol: elbv2.ApplicationProtocol.HTTP,
    targetType: elbv2.TargetType.IP,
    healthCheck: {
      path: '/health',
      interval: cdk.Duration.seconds(30),
      timeout: cdk.Duration.seconds(5),
      healthyThresholdCount: 2,
      unhealthyThresholdCount: 2,
    },
  });

  const greenTargetGroup = new elbv2.ApplicationTargetGroup(scope, 'WebSocketGreenTargetGroup', {
    vpc,
    port: 9090,
    protocol: elbv2.ApplicationProtocol.HTTP,
    targetType: elbv2.TargetType.IP,
    healthCheck: {
      path: '/health',
      interval: cdk.Duration.seconds(30),
      timeout: cdk.Duration.seconds(5),
      healthyThresholdCount: 2,
      unhealthyThresholdCount: 2,
    },
  });

  // Add listener for HTTP (port 80) and redirect to HTTPS
  const httpListener = loadBalancer.addListener('WebSocketHttpListener', {
    port: 80,
    defaultAction: elbv2.ListenerAction.redirect({
      protocol: 'HTTPS',
      port: '443',
      permanent: true,
    }),
    open: false,
  });

  const httpsListener = loadBalancer.addListener('WebSocketHttpsListener', {
    port: 443,
    protocol: elbv2.ApplicationProtocol.HTTPS,
    certificates: [certificate],
    defaultTargetGroups: [blueTargetGroup],
    open: false,
  });

  // return { loadBalancer, blueTargetGroup, greenTargetGroup, httpsListener, loadBalancerSecurityGroup };
  return { loadBalancer, blueTargetGroup, greenTargetGroup, httpsListener, webSocketLoadBalancerSecurityGroup };
};
