package impl

import (
	"context"

	"github.com/tidbcloud/dataflow-service/app/repo/entity"
	"github.com/tidbcloud/pkgv2/bizerr"
	mgmt_commonv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/common/v1"
	mgmt "github.com/tidbcloud/tidb-management-service/api/spec/tidb_mgmt_service/v1"
)

// replayClusterProvider prepares cluster-type-specific replay material.
type replayClusterProvider interface {
	PrepareTaskSourceAuditLogs(tasks entity.ReplayTaskList) bizerr.BizError
	PrepareSourceAuditLog(ctx context.Context) (*entity.AuditLogAddr, bizerr.BizError)
	PrepareTargetEndpoint() (string, bizerr.BizError)
}

type replayClusterProviderType int

const (
	replayClusterProviderTypeUnsupported replayClusterProviderType = iota
	replayClusterProviderTypeDedicated
	replayClusterProviderTypePremium
)

func newReplayClusterProvider(
	o *replayOperatorImpl,
	cluster *mgmt.Cluster,
	replayEnt *entity.Replay,
) (replayClusterProvider, bizerr.BizError) {
	if cluster == nil {
		return nil, nil
	}
	switch replayClusterType(cluster) {
	case replayClusterProviderTypePremium:
		return newPremiumReplayClusterProvider(o.MgmtSvcGrpcClient, cluster, replayEnt), nil
	case replayClusterProviderTypeDedicated:
		var sourceAuditLogAddr *entity.AuditLogAddr
		if replayEnt != nil {
			sourceAuditLogAddr = replayEnt.SourceAuditCredential
		}
		return &dedicatedReplayClusterProvider{
			sourceAuditLogAddr: sourceAuditLogAddr,
		}, nil
	default:
		return nil, bizerr.New(
			bizerr.ErrCodeParams,
			"unsupported replay cluster type for cluster %d: deploy_type=%s service_plan=%s",
			cluster.GetClusterId(),
			cluster.GetDeployType().String(),
			cluster.GetNextGenCluster().GetServicePlan().String(),
		)
	}
}

func replayClusterType(cluster *mgmt.Cluster) replayClusterProviderType {
	if cluster == nil {
		return replayClusterProviderTypeUnsupported
	}
	if cluster.GetDeployType() == mgmt.DeployType_DEPLOY_TYPE_DEDICATED {
		return replayClusterProviderTypeDedicated
	}
	if cluster.GetDeployType() == mgmt.DeployType_DEPLOY_TYPE_NEXTGEN &&
		cluster.GetNextGenCluster().GetServicePlan() == mgmt_commonv1.ServicePlan_Premium {
		return replayClusterProviderTypePremium
	}
	return replayClusterProviderTypeUnsupported
}
