package eks

import (
	"context"
	"fmt"

	xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1"
	o11yv2 "github.com/tidbcloud/observability/agent-control-server/api/v2"
	eksv1beta1 "github.com/upbound/provider-aws/apis/eks/v1beta1"
	"k8s.io/apimachinery/pkg/types"

	"github.com/tidbcloud/infra-provider/regional-server/pkg/controllers"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/controllers/appbox/task"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/controllers/appbox/task/common"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/namer"
)

type eksProvider struct{}

func (eksProvider) FillProviderSpec(ctx context.Context, t *task.BaseTask, spec *o11yv2.KubernetesAgentSpec) error {
	key := types.NamespacedName{
		Name: controllers.UniqueIdentifier(t.APPBox.ObjectMeta, namer.WithPrefix(t.Config.ResourceNamePrefix)),
	}
	c := &eksv1beta1.Cluster{}
	if err := t.Local.Get(ctx, key, c); err != nil {
		return err
	}
	if len(c.Status.AtProvider.VPCConfig) == 0 || c.Status.AtProvider.VPCConfig[0].ClusterSecurityGroupID == nil {
		return fmt.Errorf("eks cluster %s has no security group", c.Name)
	}
	sg := *c.Status.AtProvider.VPCConfig[0].ClusterSecurityGroupID

	spec.EKS = &o11yv2.EKSConfig{
		AccountID:               t.VPC.Spec.AccountRef.AccountID,
		AssumeRoleArn:           t.RoleARN(),
		VpcID:                   t.VPC.Status.VPC.VPCID,
		NodeSubnetIDs:           getNodeSubnetIDs(t),
		SecurityGroupID:         sg,
		ProviderConfigReference: &xpv1.Reference{Name: t.VPC.Spec.AccountRef.ProviderConfigName},
	}
	return nil
}

func getNodeSubnetIDs(t *task.BaseTask) []string {
	ids := make([]string, 0, len(t.VPC.Status.NodeSubnets))
	for _, s := range t.VPC.Status.NodeSubnets {
		ids = append(ids, s.SubnetID)
	}
	return ids
}

// NewO11yProvider returns the EKS provider implementation for common O11y task.
func NewO11yProvider() common.Provider { return eksProvider{} }
