package server

import (
	"fmt"

	corev1 "k8s.io/api/core/v1"

	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	apiv1 "github.com/tidbcloud/infra-provider/api/tidbcloud/cluster-server/v1"
	"github.com/tidbcloud/infra-provider/pkg/consts"
)

func buildExplicitKubernetes(provider string, request *apiv1.Kubernetes) (cloudv1.Kubernetes, error) {
	cloud, err := buildExplicitDataplaneCloud(provider, request)
	if err != nil {
		return cloudv1.Kubernetes{}, err
	}
	kubernetes := cloudv1.Kubernetes{
		Name:     request.GetName(),
		Endpoint: request.GetEndpoint(),
		Account:  request.GetAccountId(),
		Network:  request.GetVpc(),
		Provider: provider,
		Version:  request.GetVersion(),
		Cloud:    cloud,
	}
	if request.GetCa() != "" {
		kubernetes.CAData = []byte(request.GetCa())
	}
	if request.GetKubeConfigSecretRef() != nil {
		kubernetes.KubeConfigSecretRef = &corev1.SecretReference{
			Namespace: request.GetKubeConfigSecretRef().Namespace,
			Name:      request.GetKubeConfigSecretRef().Name,
		}
	}
	return kubernetes, nil
}

func buildExplicitDataplaneCloud(provider string, request *apiv1.Kubernetes) (cloudv1.Cloud, error) {
	if request == nil || !(request.GetAws() != nil || request.GetAlicloud() != nil) {
		return cloudv1.Cloud{}, nil
	}

	switch provider {
	case consts.ProviderTypeEKS:
		if request.GetAws() == nil {
			return cloudv1.Cloud{}, fmt.Errorf("%w: %w", errReplayInvalidDataplaneKubernetes, unsupportedReplayCloudProvider(provider))
		}
		return cloudv1.Cloud{
			AWS: awsCloudFromRequest(request.GetAws()),
		}, nil
	case consts.ProviderTypeACK:
		if request.GetAlicloud() == nil {
			return cloudv1.Cloud{}, fmt.Errorf("%w: %w", errReplayInvalidDataplaneKubernetes, unsupportedReplayCloudProvider(provider))
		}
		return cloudv1.Cloud{
			Ack: &cloudv1.CloudAck{
				Subnets: request.GetAlicloud().GetVswitchs(),
			},
		}, nil
	default:
		return cloudv1.Cloud{}, fmt.Errorf("%w: %w", errReplayInvalidDataplaneKubernetes, unsupportedReplayCloudProvider(provider))
	}
}

func validateExplicitKubernetesRequest(request *apiv1.Kubernetes) error {
	if request != nil && request.GetKubeConfigSecretRef() != nil && request.GetKubeconfig() != "" {
		return fmt.Errorf("%w: kubeConfigSecretRef and kubeconfig are mutually exclusive", errReplayInvalidDataplaneKubernetes)
	}
	return nil
}

func awsCloudFromRequest(aws *apiv1.Kubernetes_Aws) *cloudv1.CloudAWS {
	cloudAWS := &cloudv1.CloudAWS{
		EKSSecurityGroup: aws.GetSecurityGroup(),
		AdminNodeRole:    aws.GetAdminNodeRole(),
	}
	for _, group := range []struct {
		name    cloudv1.AWSSubnetGroupName
		subnets []*apiv1.Kubernetes_AwsSubnet
	}{
		{name: cloudv1.AWSSubnetGroupNodes, subnets: aws.GetNodeSubnets()},
		{name: cloudv1.AWSSubnetGroupPublicNLB, subnets: aws.GetPublicLoadbalancerSubnets()},
		{name: cloudv1.AWSSubnetGroupPrivateNLB, subnets: aws.GetPrivateLoadbalancerSubnets()},
		{name: cloudv1.AWSSubnetGroupSecondaryCIDR, subnets: aws.GetSecondaryNodeSubnets()},
	} {
		if len(group.subnets) == 0 {
			continue
		}
		cloudAWS.SubnetGroups = append(cloudAWS.SubnetGroups, cloudv1.AWSSubnetGroup{
			Name:    group.name,
			Subnets: getAwsSubnetFromReq(group.subnets),
		})
	}
	return cloudAWS
}
