package repository

import (
	"context"

	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/entity"
)

type ClusterFilter struct {
	Labels            map[string]string
	ClusterIds        []uint64
	ProjectIds        []uint64
	ExcludeProjectIds []uint64
	OrganizationIds   []uint64
	DeployType        entity.DeployType
	CloudProviders    []string
	Regions           []string
	RegionPairs       []RegionPair
	View              entity.ClusterView
	States            []entity.ClusterState
	ExcludeStates     []entity.ClusterState
	QueryDeleted      bool
	RefreshCache      bool
	ServicePlans      []string
	EngineTypes       []string
	Name              string
	TagCanonicalNames []string

	PermissionFilter *PermissionFilter

	ShadowPoolIds []uint64
	ShadowStates  []entity.ShadowState
	CreatedAtAsc  bool
}

type RegionPair struct {
	CloudProvider string
	Region        string
}

type PermissionFilter struct {
	All        bool // if true, has all permissions
	ProjectIds []uint64
	ClusterIds []uint64
}

// ShadowPoolClusterCount holds the result of a grouped cluster count query.
type ShadowPoolClusterCount struct {
	PoolID      uint64
	ShadowState entity.ShadowState
	IsDeleted   bool
	Count       int64
}

type ClusterRepository interface {
	CountDisplayNameUnderProject(ctx context.Context, projectId uint64, displayName string) (int64, error)
	CountDisplayNameUnderOrg(ctx context.Context, orgId uint64, displayName string) (int64, error)
	InsertNewCluster(ctx context.Context, cluster *entity.Cluster) (pk uint64, err error)
	GetCluster(ctx context.Context, clusterId uint64, includeDeleted bool) (*entity.Cluster, error)
	DeleteCluster(ctx context.Context, clusterId uint64) error
	UpdateDisplayName(ctx context.Context, clusterId uint64, displayName string) error
	SetClusterRegion(ctx context.Context, clusterId uint64, provider, region string) error
	UpdateLabels(ctx context.Context, clusterId uint64, labels map[string]string) error
	TouchCluster(ctx context.Context, clusterId uint64) error
	// QueryClusterByFilterAndPage query clusters by filter and page. PageSize is ignored if pageSize is 0.
	QueryClusterByFilterAndPage(
		ctx context.Context,
		filter *ClusterFilter,
		offset, pageSize int,
	) ([]*entity.Cluster, error)
	CountClusterByFilter(ctx context.Context, filter *ClusterFilter) (int64, error)
	// CountShadowPoolClustersGrouped returns cluster counts grouped by (pool_id, shadow_state, is_deleted)
	// for the given shadow pool IDs. A single query replaces per-state loops.
	CountShadowPoolClustersGrouped(ctx context.Context, poolIDs []uint64) ([]ShadowPoolClusterCount, error)
	UpdateServicePlan(ctx context.Context, clusterId uint64, servicePlan string) error
	// UpdateProjectId moves a cluster to a different project within the same org.
	UpdateProjectId(ctx context.Context, clusterId uint64, projectId uint64) error
	UpdateShadowState(ctx context.Context,
		clusterId uint64,
		shadowState entity.ShadowState,
		originalState entity.ShadowState) error

	// SupplementOriginalProjectIdAndServicePlan only used for data supplement
	// FIXME: @peijin remove this function after supplement finished
	SupplementOriginalProjectIdAndServicePlan(ctx context.Context, startId uint64, pageSize int) (uint64, error)

	QueryPreparedShadowClustersForUpdate(ctx context.Context, shadowPoolId uint64, count int) ([]*entity.Cluster, error)

	UpdateRuVersion(ctx context.Context, clusterId uint64, ruVersion int32) error
}
