using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    // Read the default VPC and public subnets, which we will use.
    var vpc = Aws.Ec2.GetVpc.Invoke(new()
    {
        Default = true,
    });

    var subnets = Aws.Ec2.GetSubnetIds.Invoke(new()
    {
        VpcId = vpc.Apply(getVpcResult => getVpcResult.Id),
    });

    // Create a security group that permits HTTP ingress and unrestricted egress.
    var webSecurityGroup = new Aws.Ec2.SecurityGroup("webSecurityGroup", new()
    {
        VpcId = vpc.Apply(getVpcResult => getVpcResult.Id),
        Egress = new[]
        {
            new Aws.Ec2.Inputs.SecurityGroupEgressArgs
            {
                Protocol = "-1",
                FromPort = 0,
                ToPort = 0,
                CidrBlocks = new[]
                {
                    "0.0.0.0/0",
                },
            },
        },
        Ingress = new[]
        {
            new Aws.Ec2.Inputs.SecurityGroupIngressArgs
            {
                Protocol = "tcp",
                FromPort = 80,
                ToPort = 80,
                CidrBlocks = new[]
                {
                    "0.0.0.0/0",
                },
            },
        },
    });

    // Create an ECS cluster to run a container-based service.
    var cluster = new Aws.Ecs.Cluster("cluster");

    // Create an IAM role that can be used by our service's task.
    var taskExecRole = new Aws.Iam.Role("taskExecRole", new()
    {
        AssumeRolePolicy = JsonSerializer.Serialize(new Dictionary<string, object?>
        {
            ["Version"] = "2008-10-17",
            ["Statement"] = new[]
            {
                new Dictionary<string, object?>
                {
                    ["Sid"] = "",
                    ["Effect"] = "Allow",
                    ["Principal"] = new Dictionary<string, object?>
                    {
                        ["Service"] = "ecs-tasks.amazonaws.com",
                    },
                    ["Action"] = "sts:AssumeRole",
                },
            },
        }),
    });

    var taskExecRolePolicyAttachment = new Aws.Iam.RolePolicyAttachment("taskExecRolePolicyAttachment", new()
    {
        Role = taskExecRole.Name,
        PolicyArn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy",
    });

    // Create a load balancer to listen for HTTP traffic on port 80.
    var webLoadBalancer = new Aws.ElasticLoadBalancingV2.LoadBalancer("webLoadBalancer", new()
    {
        Subnets = subnets.Apply(getSubnetIdsResult => getSubnetIdsResult.Ids),
        SecurityGroups = new[]
        {
            webSecurityGroup.Id,
        },
    });

    var webTargetGroup = new Aws.ElasticLoadBalancingV2.TargetGroup("webTargetGroup", new()
    {
        Port = 80,
        Protocol = "HTTP",
        TargetType = "ip",
        VpcId = vpc.Apply(getVpcResult => getVpcResult.Id),
    });

    var webListener = new Aws.ElasticLoadBalancingV2.Listener("webListener", new()
    {
        LoadBalancerArn = webLoadBalancer.Arn,
        Port = 80,
        DefaultActions = new[]
        {
            new Aws.ElasticLoadBalancingV2.Inputs.ListenerDefaultActionArgs
            {
                Type = "forward",
                TargetGroupArn = webTargetGroup.Arn,
            },
        },
    });

    // Spin up a load balanced service running NGINX
    var appTask = new Aws.Ecs.TaskDefinition("appTask", new()
    {
        Family = "fargate-task-definition",
        Cpu = "256",
        Memory = "512",
        NetworkMode = "awsvpc",
        RequiresCompatibilities = new[]
        {
            "FARGATE",
        },
        ExecutionRoleArn = taskExecRole.Arn,
        ContainerDefinitions = JsonSerializer.Serialize(new[]
        {
            new Dictionary<string, object?>
            {
                ["name"] = "my-app",
                ["image"] = "nginx",
                ["portMappings"] = new[]
                {
                    new Dictionary<string, object?>
                    {
                        ["containerPort"] = 80,
                        ["hostPort"] = 80,
                        ["protocol"] = "tcp",
                    },
                },
            },
        }),
    });

    var appService = new Aws.Ecs.Service("appService", new()
    {
        Cluster = cluster.Arn,
        DesiredCount = 5,
        LaunchType = "FARGATE",
        TaskDefinition = appTask.Arn,
        NetworkConfiguration = new Aws.Ecs.Inputs.ServiceNetworkConfigurationArgs
        {
            AssignPublicIp = true,
            Subnets = subnets.Apply(getSubnetIdsResult => getSubnetIdsResult.Ids),
            SecurityGroups = new[]
            {
                webSecurityGroup.Id,
            },
        },
        LoadBalancers = new[]
        {
            new Aws.Ecs.Inputs.ServiceLoadBalancerArgs
            {
                TargetGroupArn = webTargetGroup.Arn,
                ContainerName = "my-app",
                ContainerPort = 80,
            },
        },
    }, new CustomResourceOptions
    {
        DependsOn =
        {
            webListener,
        },
    });

    return new Dictionary<string, object?>
    {
        ["url"] = webLoadBalancer.DnsName,
    };
});