package account

import (
	"context"

	"github.com/tidbcloud/infra-provider/regional-server/pkg/common/constants"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/common/models"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/resourcemanager/account"
)

var (
	_ SharedBucketServiceInterface = &SharedBucketService{}
)

type SharedBucketServiceInterface interface {
	AssignSharedBucket(ctx context.Context, account models.DataPlaneAccountInfo, clusterID string, tenantID string, projectID string) (models.SharedBucketInfo, error)
	UnassignSharedBucket(ctx context.Context, clusterID string) error
}

type SharedBucketService struct {
	sharedBucketRW account.SharedBucketReaderWriter
}

func NewSharedBucketService(sharedBucketRW account.SharedBucketReaderWriter) *SharedBucketService {
	return &SharedBucketService{
		sharedBucketRW: sharedBucketRW,
	}
}

// AssignSharedBucket Assign an SharedBucket to a vpc
func (svc SharedBucketService) AssignSharedBucket(ctx context.Context, account models.DataPlaneAccountInfo, clusterID string, tenantID string, projectID string) (models.SharedBucketInfo, error) {
	bindingSharedBucketKey, err := svc.findBindingSharedBucketKey(ctx, []models.SharedBucketBindingTarget{
		{
			TargetType: constants.SharedBucketBindingCluster,
			TargetKey:  clusterID,
		},
		{
			TargetType: constants.SharedBucketBindingProject,
			TargetKey:  projectID,
		},
		{
			TargetType: constants.SharedBucketBindingTenantID,
			TargetKey:  tenantID,
		},
	})
	if err != nil {
		return models.SharedBucketInfo{}, err
	}
	if len(bindingSharedBucketKey) > 0 {
		return account.SharedBucketBundle.GetByKey(ctx, bindingSharedBucketKey)
	}

	defaultSharedBucket, err := account.SharedBucketBundle.GetDefault(ctx)
	if err != nil {
		return models.SharedBucketInfo{}, err
	}

	err = svc.sharedBucketRW.Bind(ctx, defaultSharedBucket, models.SharedBucketBindingTarget{
		TargetType: constants.SharedBucketBindingCluster,
		TargetKey:  clusterID,
	})
	if err != nil {
		return models.SharedBucketInfo{}, err
	}
	return defaultSharedBucket, nil
}

func (svc SharedBucketService) UnassignSharedBucket(ctx context.Context, clusterID string) error {
	return svc.sharedBucketRW.Unbind(ctx, models.SharedBucketBindingTarget{
		TargetType: constants.SharedBucketBindingCluster,
		TargetKey:  clusterID,
	})
}

func (svc SharedBucketService) findBindingSharedBucketKey(ctx context.Context, targets []models.SharedBucketBindingTarget) (string, error) {
	for _, target := range targets {
		bindingSharedBucketKey, err := svc.sharedBucketRW.GetBinding(ctx, target)
		if err != nil {
			return "", err
		}
		if len(bindingSharedBucketKey) > 0 {
			return bindingSharedBucketKey, nil
		}
	}
	return "", nil
}
