package e2ev2

import (
	"context"
	"fmt"

	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/utils/pointer"
	"sigs.k8s.io/controller-runtime/pkg/client"

	ec2v1beta1 "github.com/crossplane/provider-aws/apis/ec2/v1beta1"

	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	"github.com/tidbcloud/infra-api/test/e2ev2/framework"
	"github.com/tidbcloud/infra-api/test/e2ev2/provider"
)

const Name string = "gardener-provider"

var _ provider.Provider = new(GardenerProvider)

type GardenerProvider struct {
}

func (p *GardenerProvider) Name() string {
	return Name
}

func (p *GardenerProvider) NewNetwork(ctx context.Context) *cloudv1.Network {
	return &cloudv1.Network{
		ObjectMeta: metav1.ObjectMeta{
			GenerateName: fmt.Sprintf("e2e-%s-", p.Name()),
		},
		Spec: cloudv1.NetworkSpec{
			Provider: cloudv1.ProviderAWS,
			Region:   framework.DefaultAWSRegion,
			CIDR:     framework.DefaultAWSVPCCidr,
		},
	}
}

func (p *GardenerProvider) ConnectNetwork(ctx context.Context, infraCli client.Client, network *cloudv1.Network) (client.Client, error) {
	return nil, nil
}

func (p *GardenerProvider) AfterNetworkCreated(ctx context.Context, infraCli client.Client, tenantCli client.Client, network *cloudv1.Network) error {
	return nil
}

func (p *GardenerProvider) AfterNetworkDeleted(ctx context.Context, infraCli client.Client, tenantCli client.Client, network *cloudv1.Network) error {
	return nil
}

func (p *GardenerProvider) NewCluster(ctx context.Context, network *cloudv1.Network) *cloudv1.Cluster {
	return &cloudv1.Cluster{
		ObjectMeta: metav1.ObjectMeta{
			GenerateName: fmt.Sprintf("e2e-%s-", p.Name()),
			Namespace:    network.Namespace,
			Labels: map[string]string{
				cloudv1.ProviderTypeLabel: cloudv1.ProviderAWS,
			},
		},
		Spec: cloudv1.ClusterSpec{
			Cluster: cloudv1.ClusterTopology{
				TiDB: cloudv1.TiDB{
					Replicas:     1,
					InstanceType: framework.InstanceTypeT3Medium,
				},
				TiKV: cloudv1.TiKV{
					Replicas:     1,
					StorageSize:  resource.MustParse("10Gi"),
					InstanceType: framework.InstanceTypeT3Medium,
				},
				PD: cloudv1.PD{
					InstanceType: framework.InstanceTypeT3Medium,
					Replicas:     1,
					StorageSize:  resource.MustParse("10Gi"),
				},
				TiFlash: cloudv1.TiFlash{
					InstanceType: framework.InstanceTypeT3aMedium,
					Replicas:     0,
					StorageSize:  resource.MustParse("0Gi"),
				},
			},
			NetworkName: network.Name,
			SqlEndpoints: cloudv1.SqlEndpoints{
				Public: cloudv1.Service{
					Enabled: pointer.Bool(true),
					LoadBalancerSourceRanges: []string{
						"0.0.0.0/0",
					},
				},
			},
		},
	}
}

func (p *GardenerProvider) AfterClusterCreated(ctx context.Context, infraCli client.Client, tenantCli client.Client, cluster *cloudv1.Cluster) error {
	return nil
}

func (p *GardenerProvider) AfterClusterDeleted(ctx context.Context, infraCli client.Client, tenantCli client.Client, cluster *cloudv1.Cluster) error {
	return nil
}

func (p *GardenerProvider) SupportTiFlash() bool {
	return true
}

func (p *GardenerProvider) SupportNetworkPeering() bool {
	return true
}

func (p *GardenerProvider) NewPeerVPC(ctx context.Context) *ec2v1beta1.VPC {
	return framework.NewVPC(fmt.Sprintf("e2e-%s-", p.Name()), framework.CrossPlaneAWSProviderConfigName, framework.DefaultAWSPeeringVPCCidr)
}

func (p *GardenerProvider) NewImport(ctx context.Context, cluster *cloudv1.Cluster) *cloudv1.Import {
	return &cloudv1.Import{
		ObjectMeta: metav1.ObjectMeta{
			GenerateName: fmt.Sprintf("e2e-%s-import-", p.Name()),
			Namespace:    cluster.Namespace,
		},
		Spec: cloudv1.ImportSpec{
			ClusterName: cluster.Name,
			Source: cloudv1.Source{
				Format: cloudv1.DataFormatSQL,
				Storage: cloudv1.Storage{
					S3: &cloudv1.S3{
						URL: "s3://tidbcloud-samples/data-ingestion/?region=us-west-2",
					},
				},
				UserName: "cloud_admin",
				Password: "",
			},
			AccessConfig: cloudv1.AccessConfig{
				RoleArn: "arn:aws:iam::385595570414:role/import-sample-access",
			},
		},
	}
}
