package data

import (
	"fmt"
	"math/rand"

	xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1"
	ec2v1alpha1 "github.com/crossplane/provider-aws/apis/ec2/v1alpha1"
	ec2v1beta1 "github.com/crossplane/provider-aws/apis/ec2/v1beta1"
	lambdav1alpha1 "github.com/crossplane/provider-aws/apis/lambda/v1alpha1"
	"github.com/tidbcloud/shared-provider/pkg/types"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/utils/pointer"
)

func NewCustomerVPC() *ec2v1beta1.VPC {
	return &ec2v1beta1.VPC{
		ObjectMeta: metav1.ObjectMeta{
			Name: fmt.Sprintf("e2e-customer-vpc-%d", rand.Int31()),
		},
		Spec: ec2v1beta1.VPCSpec{
			ResourceSpec: xpv1.ResourceSpec{
				ProviderConfigReference: &xpv1.Reference{
					Name: types.CrossplaneProviderConfigReferenceName,
				},
			},
			ForProvider: ec2v1beta1.VPCParameters{
				CIDRBlock:          "192.168.10.0/22",
				EnableDNSSupport:   pointer.Bool(true),
				EnableDNSHostNames: pointer.Bool(true),
			},
		},
	}
}

func NewCustomerSubnet(vpcName, zone string) *ec2v1beta1.Subnet {
	return &ec2v1beta1.Subnet{
		ObjectMeta: metav1.ObjectMeta{
			Name: fmt.Sprintf("e2e-customer-subnet-%d", rand.Int31()),
		},
		Spec: ec2v1beta1.SubnetSpec{
			ResourceSpec: xpv1.ResourceSpec{
				ProviderConfigReference: &xpv1.Reference{
					Name: types.CrossplaneProviderConfigReferenceName,
				},
			},
			ForProvider: ec2v1beta1.SubnetParameters{
				CIDRBlock: "192.168.10.0/24",
				VPCIDRef: &xpv1.Reference{
					Name: vpcName,
				},
				AvailabilityZone: pointer.String("us-east-1a"),
			},
		},
	}
}

func NewVPCEndpointSecurityGroup(vpcName string) *ec2v1beta1.SecurityGroup {
	name := fmt.Sprintf("e2e-vpc-ep-sg-%d", rand.Int31())
	return &ec2v1beta1.SecurityGroup{
		ObjectMeta: metav1.ObjectMeta{
			Name: name,
		},
		Spec: ec2v1beta1.SecurityGroupSpec{
			ResourceSpec: xpv1.ResourceSpec{
				ProviderConfigReference: &xpv1.Reference{
					Name: types.CrossplaneProviderConfigReferenceName,
				},
			},
			ForProvider: ec2v1beta1.SecurityGroupParameters{
				Description: "for shared tier private link e2e, please @liubo02",
				GroupName:   name,
				VPCIDRef: &xpv1.Reference{
					Name: vpcName,
				},
				Ingress: []ec2v1beta1.IPPermission{
					{
						IPProtocol: "-1",
						IPRanges: []ec2v1beta1.IPRange{
							{
								CIDRIP: "0.0.0.0/0",
							},
						},
					},
				},
				Egress: []ec2v1beta1.IPPermission{
					{
						IPProtocol: "-1",
						IPRanges: []ec2v1beta1.IPRange{
							{
								CIDRIP: "0.0.0.0/0",
							},
						},
					},
				},
			},
		},
	}
}

func NewVPCEndpoint(vpcName, subnetName, sgName, svcName string) *ec2v1alpha1.VPCEndpoint {
	return &ec2v1alpha1.VPCEndpoint{
		ObjectMeta: metav1.ObjectMeta{
			Name: fmt.Sprintf("e2e-customer-vpc-ep-%d", rand.Int31()),
		},
		Spec: ec2v1alpha1.VPCEndpointSpec{
			ResourceSpec: xpv1.ResourceSpec{
				ProviderConfigReference: &xpv1.Reference{
					Name: types.CrossplaneProviderConfigReferenceName,
				},
			},
			ForProvider: ec2v1alpha1.VPCEndpointParameters{
				ServiceName:     &svcName,
				VPCEndpointType: pointer.String("Interface"),
				CustomVPCEndpointParameters: ec2v1alpha1.CustomVPCEndpointParameters{
					VPCIDRef: &xpv1.Reference{
						Name: vpcName,
					},
					SubnetIDRefs: []xpv1.Reference{
						{
							Name: subnetName,
						},
					},
					SecurityGroupIDRefs: []xpv1.Reference{
						{
							Name: sgName,
						},
					},
				},
			},
		},
	}
}

func NewCustomerLambda(subnetName, sgName, image string, cmds []string) *lambdav1alpha1.Function {
	cmdsPtr := make([]*string, 0, len(cmds))
	for i := range cmds {
		cmdsPtr = append(cmdsPtr, &cmds[i])
	}
	return &lambdav1alpha1.Function{
		ObjectMeta: metav1.ObjectMeta{
			Name: fmt.Sprintf("e2e-customer-lambda-%d", rand.Int31()),
		},
		Spec: lambdav1alpha1.FunctionSpec{
			ResourceSpec: xpv1.ResourceSpec{
				ProviderConfigReference: &xpv1.Reference{
					Name: types.CrossplaneProviderConfigReferenceName,
				},
			},
			ForProvider: lambdav1alpha1.FunctionParameters{
				PackageType: pointer.String("Image"),
				ImageConfig: &lambdav1alpha1.ImageConfig{
					Command: cmdsPtr,
				},
				Publish: pointer.Bool(true),
				CustomFunctionParameters: lambdav1alpha1.CustomFunctionParameters{
					// TODO(liubo02): create role dynamically
					Role: pointer.String("arn:aws:iam::385595570414:role/lambda-test-role"),
					CustomFunctionCodeParameters: lambdav1alpha1.CustomFunctionCodeParameters{
						ImageURI: &image,
					},
					CustomFunctionVPCConfigParameters: &lambdav1alpha1.CustomFunctionVPCConfigParameters{
						SubnetIDRefs: []xpv1.Reference{
							{
								Name: subnetName,
							},
						},
						SecurityGroupIDRefs: []xpv1.Reference{
							{
								Name: sgName,
							},
						},
					},
				},
			},
		},
	}
}
