package alicloud

import (
	"fmt"

	privatelink "github.com/alibabacloud-go/privatelink-20200415/v5/client"
	"k8s.io/utils/ptr"

	"github.com/tidbcloud/observability/agent-control-server/pkg/consts"
)

const VpcEndpointTypeInterface = "Interface"

// PrivateLinkClient is an interface for privatelink client operations.
type PrivateLinkClient interface {
	ListVpcEndpoints(req *privatelink.ListVpcEndpointsRequest) (*privatelink.ListVpcEndpointsResponse, error)
	TagResources(request *privatelink.TagResourcesRequest) (*privatelink.TagResourcesResponse, error)
}

// FindReusableVPCEndpointID tries to find a reusable vpc endpoint using Alicloud native API.
// The reusable vpc endpoint should have the same service name and vpc id as given.
func FindReusableVPCEndpointID(cli PrivateLinkClient, region, endpointType, endpointServiceName, vpcID string) (string, map[string]string, error) {
	output, err := cli.ListVpcEndpoints(&privatelink.ListVpcEndpointsRequest{
		RegionId:     ptr.To(region),
		ServiceName:  ptr.To(endpointServiceName),
		VpcId:        ptr.To(vpcID),
		EndpointType: ptr.To(endpointType),
	})
	if err != nil {
		return "", nil, fmt.Errorf("failed to list vpc endpoints: %w", err)
	}

	if output.Body == nil || len(output.Body.Endpoints) == 0 {
		return "", nil, nil
	}

	for _, endpoint := range output.Body.Endpoints {
		if isVPCEndpointReusableNative(endpoint, endpointType, endpointServiceName, vpcID) {
			if endpoint.EndpointId != nil {
				tags := make(map[string]string)
				for _, tag := range endpoint.Tags {
					if tag.Key != nil && tag.Value != nil {
						tags[*tag.Key] = *tag.Value
					}
				}
				return *endpoint.EndpointId, tags, nil
			}
		}
	}
	return "", nil, nil
}

const (
	VpcEndpointStatusActive    = "Active"
	VpcEndpointStatusAvailable = "Available"
)

// isVPCEndpointReusableNative checks whether the given vpc endpoint is reusable using native API.
// A reusable vpc endpoint should have the same service name and vpc id as given,
// and should be in an active/available state.
func isVPCEndpointReusableNative(endpoint *privatelink.ListVpcEndpointsResponseBodyEndpoints, endpointType, serviceName, vpcID string) bool {
	if endpoint.ServiceName == nil || *endpoint.ServiceName != serviceName {
		return false
	}
	if endpoint.VpcId == nil || *endpoint.VpcId != vpcID {
		return false
	}
	if endpoint.EndpointType == nil || *endpoint.EndpointType != endpointType {
		return false
	}

	if endpoint.EndpointStatus == nil {
		return false
	}

	// Only allow endpoints in specific usable states
	status := *endpoint.EndpointStatus
	if status != VpcEndpointStatusActive && status != VpcEndpointStatusAvailable {
		return false
	}
	return true
}

// FindVPCEndpointByClusterTag finds a VPC endpoint by cluster name tag.
// Returns the endpoint ID and endpoint domain if found.
func FindVPCEndpointByClusterTag(cli PrivateLinkClient, region, clusterName string) (string, string, error) {
	output, err := cli.ListVpcEndpoints(&privatelink.ListVpcEndpointsRequest{
		RegionId: ptr.To(region),
		Tag: []*privatelink.ListVpcEndpointsRequestTag{{
			Key:   ptr.To(consts.LabelKeyRelatedCluster),
			Value: ptr.To(clusterName),
		}},
		EndpointType: ptr.To(VpcEndpointTypeInterface),
	})
	if err != nil {
		return "", "", fmt.Errorf("failed to list vpc endpoints by tag: %w", err)
	}

	if output.Body == nil || len(output.Body.Endpoints) == 0 {
		return "", "", nil
	}

	for _, ep := range output.Body.Endpoints {
		if ep.EndpointStatus != nil && (*ep.EndpointStatus == VpcEndpointStatusActive || *ep.EndpointStatus == VpcEndpointStatusAvailable) {
			if ep.EndpointId != nil && ep.EndpointDomain != nil {
				return *ep.EndpointId, *ep.EndpointDomain, nil
			}
		}
	}
	return "", "", nil
}
