package commonalicloud

import (
	"context"
	"fmt"
	"strings"

	aliplv1alpha1 "github.com/crossplane-contrib/provider-upjet-alibabacloud/apis/privatelink/v1alpha1"
	"sigs.k8s.io/controller-runtime/pkg/client"

	"github.com/tidbcloud/observability/agent-control-server/pkg/cloud/alicloud"
	"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 PrivateLinkNameTask[T client.Object] struct {
	*reconciler.BaseTask[T]
	clusterName string
}

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

func (t *PrivateLinkNameTask[T]) Name() string {
	return "PrivateLinkName"
}

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

	if t.Config.IsServerlessMode() {
		return t.checkWithNativeAPI(clusterName)
	}
	return t.checkWithUpbound(ctx, clusterName)
}

func (t *PrivateLinkNameTask[T]) checkWithNativeAPI(clusterName string) deploy.Result {
	region := t.Config.O11yConfig.Region
	if region == "" {
		return deploy.Panic(fmt.Errorf("region is not configured"))
	}

	cli, err := t.AliCloud.PrivateLink(nil, alicloud.WithRegion(region))
	if err != nil {
		return deploy.Error(fmt.Errorf("failed to create privatelink client: %w", err))
	}

	endpointID, endpointDomain, err := alicloud.FindVPCEndpointByClusterTag(cli, region, clusterName)
	if err != nil {
		return deploy.Error(fmt.Errorf("failed to find vpc endpoint by cluster tag: %w", err))
	}
	if endpointID == "" {
		return deploy.Panic(fmt.Errorf("no vpc endpoint found for cluster %s", clusterName))
	}
	if endpointDomain == "" {
		return deploy.Panic(fmt.Errorf("vpc endpoint %s has empty endpoint domain", endpointID))
	}

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

	util.SetAnnotation(t.Agent, consts.AnnotationKeyO11yServiceDNSName, endpointDomain)
	t.L.Info("updated o11y service dns from shared endpoint", "endpointID", endpointID, "endpointDomain", endpointDomain)
	return deploy.Done()
}

func (t *PrivateLinkNameTask[T]) checkWithUpbound(ctx context.Context, clusterName string) deploy.Result {
	var endpoints aliplv1alpha1.VpcEndpointList
	if err := t.Local.List(ctx, &endpoints, client.MatchingLabels{consts.LabelKeyRelatedCluster: clusterName}); err != nil {
		return deploy.Panic(fmt.Errorf("failed to list vpc endpoints for cluster %s: %w", clusterName, err))
	}
	if len(endpoints.Items) == 0 {
		return deploy.Panic(fmt.Errorf("no vpc endpoint found for cluster %s, wait created", clusterName))
	}

	ep := endpoints.Items[0]

	endpointDomain := ""
	if ep.Status.AtProvider.EndpointDomain != nil {
		endpointDomain = strings.TrimSpace(*ep.Status.AtProvider.EndpointDomain)
	}
	if endpointDomain == "" {
		return deploy.Panic(fmt.Errorf("vpc endpoint %s has empty endpoint domain", ep.Name))
	}

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

	util.SetAnnotation(t.Agent, consts.AnnotationKeyO11yServiceDNSName, endpointDomain)
	t.L.Info("updated o11y service dns from shared endpoint", "endpointName", ep.Name, "endpointDomain", endpointDomain)
	return deploy.Done()
}
