package repo

import (
	"context"
	"time"

	"github.com/tidbcloud/pkgv2/bizerr"
	"github.com/tidbcloud/serverless-service/internal/domain/constant"
	"github.com/tidbcloud/serverless-service/internal/domain/entity"
)

type ClusterFilter struct {
	TenantIds  []uint64
	ProjectIds []uint64
	ClusterIds []uint64
	Regions    []string
	RuModes    []constant.ClusterRUMode
	IsPaid     *bool
}

type DowntimeFilter struct {
	ClusterIDs []uint64
	Regions    []string
	Months     []string
}

type CanaryCluster struct {
	ClusterID uint64 `gorm:"column:id" yaml:"cluster_id" json:"cluster_id"`
	ProjectID uint64 `                 yaml:"project_id" json:"project_id"`
}

type ClusterRepo interface {
	ListClustersInPage(
		ctx context.Context,
		filter *ClusterFilter,
		page, size uint32,
	) ([]*entity.Cluster, bizerr.BizError)
	CountClusters(ctx context.Context, filter *ClusterFilter) (int64, bizerr.BizError)
	GetClusterByID(ctx context.Context, clusterID uint64) (*entity.Cluster, bizerr.BizError)
	UpdateRUMode(ctx context.Context, clusterID uint64, mode constant.ClusterRUMode) bizerr.BizError
	Save(ctx context.Context, cluster *entity.Cluster) bizerr.BizError
	Remove(ctx context.Context, clusterID uint64) bizerr.BizError
}

type ClusterTidbPoolRepo interface {
	ListSpendLimitEvents(
		ctx context.Context,
		clusterID uint64,
		start, end time.Time,
	) ([]*entity.ClusterTidbPool, bizerr.BizError)
	LoadUnsyncedRecords(ctx context.Context) ([]*entity.ClusterTidbPool, bizerr.BizError)
	Save(ctx context.Context, record *entity.ClusterTidbPool) bizerr.BizError
	MarkAsSynced(ctx context.Context, record *entity.ClusterTidbPool) bizerr.BizError
	Remove(ctx context.Context, eventID uint64) bizerr.BizError
	RemoveAllEvents(ctx context.Context, clusterID uint64) bizerr.BizError
	CleanUp(ctx context.Context, before time.Time, limit int) bizerr.BizError
	Query(ctx context.Context, sql string) ([]*entity.ClusterTidbPool, bizerr.BizError)
}

type DowntimeRepo interface {
	ListByFilter(ctx context.Context, filter *DowntimeFilter) ([]*entity.Downtime, bizerr.BizError)
	Save(ctx context.Context, record *entity.Downtime) bizerr.BizError
	MultiSave(ctx context.Context, records []*entity.Downtime) bizerr.BizError
}

type CanaryRepo interface {
	AddClusters(ctx context.Context, canaries []*CanaryCluster) bizerr.BizError
	RemoveClusters(ctx context.Context, canaries []*CanaryCluster) bizerr.BizError
	ListClusters(ctx context.Context) ([]*CanaryCluster, bizerr.BizError)
	GetProject(ctx context.Context, projectID uint64) (*entity.ProjectCanary, bizerr.BizError)
	AddProject(ctx context.Context, projectID uint64) bizerr.BizError
	RemoveProject(ctx context.Context, projectID uint64) bizerr.BizError
	ListProjects(ctx context.Context) ([]*entity.ProjectCanary, bizerr.BizError)
	ListClustersInProject(ctx context.Context, projectID uint64) ([]*CanaryCluster, bizerr.BizError)
}
