package tioperator

import (
	"context"

	"github.com/tidbcloud/cluster-service-ng/domain/entity"
)

type Option string

const (
	OpsUpdateNodeCount      Option = "update-node-count"
	OpsUpdateNodeSpec       Option = "update-node-spec"
	OpsUpdateVersion        Option = "update-version"
	OpsUpdateImage          Option = "update-image"
	OpsUpdateConfig         Option = "update-config"
	OpsUpdateUpdateStrategy Option = "update-update-strategy"
	OpsUpdateLabels         Option = "update-labels"

	// only for tidb
	OpsUpdateTiDBAuditLog      Option = "update-tidb-audit-log"
	OpsUpdateTiDBAuditLogImage Option = "update-tidb-audit-log-image"
	OpsUpdateLabelCidr         Option = "update-label-cidr"

	// only for tiflash
	OpsUpdateTiFlashLeaderConfig Option = "update-tiflash-leader-config"

	OpsUpdateMinCount Option = "update-min-count"
	OpsUpdateMaxCount Option = "update-max-count"

	OpsUpdateNodeVersion       Option = "update-node-version"
	OpsUpdateTiKVRemoteWorkers Option = "update-tikv-remote-workers"

	// data storage only for tikv and tiflash
	OpsUpdateDataSize Option = "update-data-size"
	// OpsUpdateDataStorageClass          Option = "update-data-storage-class"  not allow to update
	OpsUpdateDataVolumeAttributesClass Option = "update-data-volume-attributes-class" // only for cloud disk with iops and throughput

	// raft log  only for tikv
	OpsUpdateRaftLogSize Option = "update-raft-log-size"
	// OpsUpdateRaftLogStorageClass          Option = "update-raft-log-storage-class" not allow to update
	OpsUpdateRaftLogVolumeAttributesClass Option = "update-raft-log-volume-attributes-class" // only for cloud disk with iops and throughput
)

type UpdateOption struct {
	Option Option
	Value  any
}

type TiKVRemoteWorkerTarget struct {
	Worker      string
	Coprocessor string
}

type TiOperator interface {
	// list cluster
	ListClusters(ctx context.Context) ([]*entity.SharedPool, error) // only returns cluster id and component group

	// get cluster
	GetCluster(ctx context.Context, clusterId string) (*entity.SharedPool, error)

	// tidb
	ListTiDBGroups(ctx context.Context, clusterId string) ([]*entity.Component, error)
	GetTiDBGroup(ctx context.Context, clusterId, groupId string) (*entity.Component, error)

	UpdateTiDBGroup(ctx context.Context, clusterId, groupId string, options ...UpdateOption) (*entity.Component, error)
	// GetTiDBAuditLogConfig(ctx context.Context, clusterId, groupId string) (*entity.AuditLogConfig, error)

	// tidb worker
	ListTiDBWorkers(ctx context.Context, clusterId string) ([]*entity.Component, error)
	GetTiDBWorker(ctx context.Context, clusterId, groupId string) (*entity.Component, error)
	UpdateTiDBWorker(ctx context.Context, clusterId, groupId string, options ...UpdateOption) (*entity.Component, error)

	// tikv
	ListTiKVGroups(ctx context.Context, clusterId string) ([]*entity.Component, error)
	GetTiKVGroup(ctx context.Context, clusterId, groupId string) (*entity.Component, error)
	UpdateTiKVGroup(ctx context.Context, clusterId, groupId string, options ...UpdateOption) (*entity.Component, error)
	CreatePlacementPolicy(ctx context.Context, sharedPoolId string, policy *entity.PlacementPolicy, keyspaceId uint32) (*entity.PlacementPolicy, error)
	ListPlacementPolicies(ctx context.Context, sharedPoolId, tikvGroupId string) ([]*entity.PlacementPolicy, error)
	GetPlacementPolicy(ctx context.Context, sharedPoolId, placementPolicyId string) (*entity.PlacementPolicy, error)
	UpdatePlacementPolicy(ctx context.Context, sharedPoolId string, policy *entity.PlacementPolicy, keyspaceId uint32) (*entity.PlacementPolicy, error)
	DeletePlacementPolicy(ctx context.Context, sharedPoolId, placementPolicyId string) error

	// tikv worker
	ListTiKVWorkers(ctx context.Context, clusterId string) ([]*entity.Component, error)
	GetTiKVWorker(ctx context.Context, clusterId, groupId string) (*entity.Component, error)
	UpdateTiKVWorker(ctx context.Context, clusterId, groupId string, options ...UpdateOption) (*entity.Component, error)

	// coprocessor worker
	ListCoprocessorWorkers(ctx context.Context, clusterId string) ([]*entity.Component, error)
	GetCoprocessorWorker(ctx context.Context, clusterId, groupId string) (*entity.Component, error)
	UpdateCoprocessorWorker(ctx context.Context, clusterId, groupId string, options ...UpdateOption) (*entity.Component, error)

	// schema manager
	ListSchemaManagers(ctx context.Context, clusterId string) ([]*entity.Component, error)
	GetSchemaManager(ctx context.Context, clusterId, groupId string) (*entity.Component, error)
	UpdateSchemaManager(ctx context.Context, clusterId, groupId string, options ...UpdateOption) (*entity.Component, error)

	// tiflash CN
	ListTiFlashCNs(ctx context.Context, clusterId string) ([]*entity.Component, error)
	GetTiFlashCN(ctx context.Context, clusterId, groupId string) (*entity.Component, error)
	UpdateTiFlashCN(ctx context.Context, clusterId, groupId string, options ...UpdateOption) (*entity.Component, error)

	// tiflash WN
	ListTiFlashWNs(ctx context.Context, clusterId string) ([]*entity.Component, error)
	GetTiFlashWN(ctx context.Context, clusterId, groupId string) (*entity.Component, error)
	UpdateTiFlashWN(ctx context.Context, clusterId, groupId string, options ...UpdateOption) (*entity.Component, error)

	// PDGroup
	ListPDGroups(ctx context.Context, clusterId string) ([]*entity.Component, error)
	GetPDGroup(ctx context.Context, clusterId, groupId string) (*entity.Component, error)
	UpdatePDGroup(ctx context.Context, clusterId, groupId string, options ...UpdateOption) (*entity.Component, error)

	// TsoGroup
	ListTsoGroups(ctx context.Context, clusterId string) ([]*entity.Component, error)
	GetTsoGroup(ctx context.Context, clusterId, groupId string) (*entity.Component, error)
	UpdateTsoGroup(ctx context.Context, clusterId, groupId string, options ...UpdateOption) (*entity.Component, error)

	// Scheduling
	ListSchedulingGroups(ctx context.Context, clusterId string) ([]*entity.Component, error)
	GetSchedulingGroup(ctx context.Context, clusterId, groupId string) (*entity.Component, error)
	UpdateSchedulingGroup(ctx context.Context, clusterId, groupId string, options ...UpdateOption) (*entity.Component, error)

	// TiProxy
	ListTiProxyGroups(ctx context.Context, clusterId string) ([]*entity.Component, error)
	GetTiProxyGroup(ctx context.Context, clusterId, groupId string) (*entity.Component, error)
	UpdateTiProxyGroup(ctx context.Context, clusterId, groupId string, options ...UpdateOption) (*entity.Component, error)
}
