package utils

import (
	"fmt"

	"github.com/aws/aws-sdk-go/aws/arn"
	"github.com/crossplane/crossplane-runtime/pkg/meta"
	"k8s.io/apimachinery/pkg/api/equality"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	eksv1alpha1 "github.com/tidbcloud/eks-provider/api/v1alpha1"
	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
)

type (
	EKSNetworkSpecMut func(spec *eksv1alpha1.EKSNetworkSpec) error
)

// MutateEKSNetworkSpec mutates the EKSNetworkSpec of a network with the given mutate function.
// It will return true if the spec is mutated and the network CR is needed to be updated.
func MutateEKSNetworkSpec(
	network *cloudv1.Network,
	mut EKSNetworkSpecMut,
) (needUpdate bool, err error) {
	spec, err := eksv1alpha1.EKSNetworkSpecForNetwork(network)
	if err != nil {
		return needUpdate, err
	}

	oldSpec := spec.DeepCopy()

	err = mut(spec)
	if err != nil {
		return needUpdate, err
	}

	if !equality.Semantic.DeepEqual(spec, oldSpec) {
		return true, eksv1alpha1.SetEKSNetworkSpec(network, spec)
	}

	return needUpdate, err
}

func SetIAMAccountID(nodeRoleARN string, network *cloudv1.Network) error {
	key, err := arn.Parse(nodeRoleARN)
	if err != nil {
		return fmt.Errorf("failed to parse node role arn: %s, error: %w", nodeRoleARN, err)
	}
	network.Status.IAM.AccountID = key.AccountID
	return nil
}

func SetExternalName(obj metav1.Object, name string) {
	if obj.GetAnnotations() == nil {
		obj.SetAnnotations(map[string]string{})
	}
	if name == "" {
		panic("empty name")
	}
	obj.GetAnnotations()[meta.AnnotationKeyExternalName] = name
}
