package commonazure

import (
	"context"
	"fmt"
	"strings"

	azurenetworkv1beta2 "github.com/upbound/provider-azure/apis/network/v1beta2"
	"sigs.k8s.io/controller-runtime/pkg/client"

	azurecloud "github.com/tidbcloud/observability/agent-control-server/pkg/cloud/azure"
	"github.com/tidbcloud/observability/agent-control-server/pkg/consts"
	"github.com/tidbcloud/observability/agent-control-server/pkg/deploy"
	"github.com/tidbcloud/observability/agent-control-server/pkg/reconciler"
	"github.com/tidbcloud/observability/agent-control-server/pkg/util"
)

type PrivateLinkIPTask[T client.Object] struct {
	*reconciler.BaseTask[T]
	clusterName string
}

func NewPrivateLinkIPTask[T client.Object](ctx *reconciler.Context[T], clusterName string) *PrivateLinkIPTask[T] {
	return &PrivateLinkIPTask[T]{
		BaseTask:    &reconciler.BaseTask[T]{Context: ctx},
		clusterName: clusterName,
	}
}

func (t *PrivateLinkIPTask[T]) Name() string {
	return "PrivateLinkIP"
}

func (t *PrivateLinkIPTask[T]) Create(ctx context.Context) deploy.Result {
	clusterName := strings.TrimSpace(t.clusterName)
	if clusterName == "" {
		return deploy.Panic(fmt.Errorf("kubernetes cluster name is empty"))
	}

	var endpoints azurenetworkv1beta2.PrivateEndpointList
	if err := t.Local.List(ctx, &endpoints, client.MatchingLabels{consts.LabelKeyRelatedCluster: clusterName}); err != nil {
		return deploy.Panic(fmt.Errorf("failed to list private endpoints for cluster %s: %w", clusterName, err))
	}
	if len(endpoints.Items) == 0 {
		return deploy.Panic(fmt.Errorf("no private endpoint found for cluster %s, wait created", clusterName))
	}

	ip := azurecloud.ExtractPrivateIP(&endpoints.Items[0])
	if ip == "" {
		return deploy.Panic(fmt.Errorf("private endpoint %s has empty private IP", endpoints.Items[0].Name))
	}

	currentIP := strings.TrimSpace(util.GetAnnotation(t.Agent, consts.AnnotationKeyO11yServiceDNSName))
	if currentIP == ip {
		return deploy.Done()
	}

	util.SetAnnotation(t.Agent, consts.AnnotationKeyO11yServiceDNSName, ip)
	t.L.Info("updated o11y service dns from private endpoint IP", "endpointName", endpoints.Items[0].Name, "privateIP", ip)
	return deploy.Done()
}
