package key

import (
	"context"
	"fmt"

	"github.com/tidbcloud/infra-provider/regional-server/api/v1alpha1"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/config"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/consts"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/controllers/key/task"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/controllers/key/task/alicloud"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/controllers/key/task/aws"
	"k8s.io/utils/ptr"
	"sigs.k8s.io/controller-runtime/pkg/client"
)

type KeyQueryer interface {
	GetTrustedDataplaneStatus(ctx context.Context, namespace, keyName, trustedDataplaneId string) (*task.KeyTrustedDataplaneStatus, error)
}

type keyQueryer struct {
	cli    client.Client
	config config.RootConfig
}

func NewKeyQueryer(cli client.Client, config config.RootConfig) KeyQueryer {
	return &keyQueryer{cli: cli, config: config}
}

func (q *keyQueryer) getVendorQueryer(key *v1alpha1.Key) task.KeyVendorQueryer {
	provider := key.Labels["tags.tidbcloud.com/cloud-provider"]
	switch provider {
	case consts.ProviderTypeEKS:
		return aws.NewAWSKeyQueryer(q.cli, q.config)
	case consts.ProviderTypeACK:
		return alicloud.NewAliCloudKeyQueryer(q.cli, q.config)
	default:
		panic(fmt.Sprintf("unsupported provider for key queryer: %s", provider))
	}
}

func (q *keyQueryer) GetTrustedDataplaneStatus(ctx context.Context, namespace, keyName, trustedDataplaneId string) (*task.KeyTrustedDataplaneStatus, error) {
	key := &v1alpha1.Key{}
	if err := q.cli.Get(ctx, client.ObjectKey{
		Namespace: namespace,
		Name:      keyName,
	}, key); err != nil {
		return nil, fmt.Errorf("get key error: %w", err)
	}

	// Check if the trusted dataplane is in the spec
	dpIdFound := false
	for _, dpId := range key.Spec.TrustedDataplanes {
		if trustedDataplaneId == dpId {
			dpIdFound = true
			break
		}
	}
	if !dpIdFound {
		return ptr.To(task.KeyTrustedDataplaneStatusNotExists), nil
	}

	// If dataplane is in spec, check the actual cloud provider status
	vendorQueryer := q.getVendorQueryer(key)
	roleStatus, err := vendorQueryer.GetTrustedDataplaneStatus(ctx, key, trustedDataplaneId)
	if err != nil {
		return nil, fmt.Errorf("get key trusted dataplane status error: %w", err)
	}
	return roleStatus, nil
}
