import * as cdk from "aws-cdk-lib";
import * as ec2 from "aws-cdk-lib/aws-ec2";
import { Construct } from "constructs";

interface VpcStackProps extends cdk.StackProps {
  /**
   * Environment name (staging, prod)
   */
  environment: string;

  /**
   * Maximum number of AZs to use (default: 2)
   */
  maxAzs?: number;

  /**
   * Number of NAT Gateways (default: 1 for cost optimization)
   * Use 2 for high availability in production
   */
  natGateways?: number;
}

export class VpcStack extends cdk.Stack {
  /**
   * The VPC created by this stack
   */
  public readonly vpc: ec2.Vpc;

  /**
   * Security group for Lambda functions
   */
  public readonly lambdaSecurityGroup: ec2.SecurityGroup;

  /**
   * S3 Gateway endpoint (free)
   */
  public readonly s3Endpoint: ec2.GatewayVpcEndpoint;

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

    const { environment, maxAzs = 2, natGateways = 1 } = props;

    // Create VPC with public and private subnets
    this.vpc = new ec2.Vpc(this, "VillageShareVpc", {
      vpcName: `village-share-vpc-${environment}`,
      ipAddresses: ec2.IpAddresses.cidr("10.0.0.0/16"),
      maxAzs,
      natGateways,
      subnetConfiguration: [
        {
          name: "Public",
          subnetType: ec2.SubnetType.PUBLIC,
          cidrMask: 24,
          mapPublicIpOnLaunch: false,
        },
        {
          name: "Private",
          subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS,
          cidrMask: 24,
        },
        {
          name: "Isolated",
          subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
          cidrMask: 24,
        },
      ],
      // Enable DNS support for VPC endpoints
      enableDnsHostnames: true,
      enableDnsSupport: true,
    });

    // Security group for Lambda functions
    this.lambdaSecurityGroup = new ec2.SecurityGroup(
      this,
      "LambdaSecurityGroup",
      {
        vpc: this.vpc,
        securityGroupName: `lambda-sg-${environment}`,
        description: "Security group for Lambda functions in VPC",
        allowAllOutbound: true, // Lambda needs outbound for AWS services
      }
    );

    // Security group for VPC endpoints
    const vpcEndpointSecurityGroup = new ec2.SecurityGroup(
      this,
      "VpcEndpointSecurityGroup",
      {
        vpc: this.vpc,
        securityGroupName: `vpc-endpoint-sg-${environment}`,
        description: "Security group for VPC Interface Endpoints",
        allowAllOutbound: false,
      }
    );

    // Allow HTTPS traffic from Lambda security group to VPC endpoints
    vpcEndpointSecurityGroup.addIngressRule(
      this.lambdaSecurityGroup,
      ec2.Port.tcp(443),
      "Allow HTTPS from Lambda functions"
    );

    // S3 Gateway Endpoint (FREE - no NAT charges for S3 traffic)
    this.s3Endpoint = this.vpc.addGatewayEndpoint("S3Endpoint", {
      service: ec2.GatewayVpcEndpointAwsService.S3,
      subnets: [{ subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS }],
    });

    // SES Interface Endpoint (for sending emails without NAT)
    this.vpc.addInterfaceEndpoint("SesEndpoint", {
      service: ec2.InterfaceVpcEndpointAwsService.SES,
      subnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
      securityGroups: [vpcEndpointSecurityGroup],
      privateDnsEnabled: true,
    });

    // SQS Interface Endpoint (for DLQ access)
    this.vpc.addInterfaceEndpoint("SqsEndpoint", {
      service: ec2.InterfaceVpcEndpointAwsService.SQS,
      subnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
      securityGroups: [vpcEndpointSecurityGroup],
      privateDnsEnabled: true,
    });

    // CloudWatch Logs Interface Endpoint
    this.vpc.addInterfaceEndpoint("CloudWatchLogsEndpoint", {
      service: ec2.InterfaceVpcEndpointAwsService.CLOUDWATCH_LOGS,
      subnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
      securityGroups: [vpcEndpointSecurityGroup],
      privateDnsEnabled: true,
    });

    // Scheduler Interface Endpoint (for EventBridge Scheduler)
    // Note: EventBridge Scheduler uses the scheduler.{region}.amazonaws.com endpoint
    this.vpc.addInterfaceEndpoint("SchedulerEndpoint", {
      service: new ec2.InterfaceVpcEndpointService(
        `com.amazonaws.${cdk.Stack.of(this).region}.scheduler`
      ),
      subnets: { subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS },
      securityGroups: [vpcEndpointSecurityGroup],
      privateDnsEnabled: true,
    });

    // Add tags to subnets for easy identification
    cdk.Tags.of(this.vpc).add("Environment", environment);
    cdk.Tags.of(this.vpc).add("Project", "village-share");

    // Outputs
    new cdk.CfnOutput(this, "VpcId", {
      value: this.vpc.vpcId,
      description: "VPC ID",
      exportName: `VpcId-${environment}`,
    });

    new cdk.CfnOutput(this, "VpcCidr", {
      value: this.vpc.vpcCidrBlock,
      description: "VPC CIDR block",
      exportName: `VpcCidr-${environment}`,
    });

    new cdk.CfnOutput(this, "PrivateSubnetIds", {
      value: this.vpc
        .selectSubnets({ subnetType: ec2.SubnetType.PRIVATE_WITH_EGRESS })
        .subnetIds.join(","),
      description: "Private subnet IDs",
      exportName: `PrivateSubnetIds-${environment}`,
    });

    new cdk.CfnOutput(this, "LambdaSecurityGroupId", {
      value: this.lambdaSecurityGroup.securityGroupId,
      description: "Security group ID for Lambda functions",
      exportName: `LambdaSecurityGroupId-${environment}`,
    });
  }
}
