package resourcepoolpolicy

import globalngv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/nextgen/v1"

type Operation uint8

const (
	OperationUnknown Operation = iota
	OperationCreateInstance
	OperationRestoreInstance
	OperationManualBackup
	OperationImportExport
	OperationScale
	OperationUpdateInstance
	OperationDeleteInstance
	OperationUpdateNetwork
	OperationUpdatePoolLimits
	OperationRenamePool
	OperationEditCloudResourceTags
	OperationDeletePool
	OperationScheduledBackup
	// OperationPausePreparationBackup is reserved for backups owned by the
	// currently active Pause preparation operation.
	OperationPausePreparationBackup
	operationCount
)

type Decision uint8

const (
	DecisionBlocked Decision = iota
	DecisionAllowed
	DecisionTriggerOrReuseResume
)

func Decide(operation Operation, state globalngv1.ResourcePool_LifecycleState) Decision {
	if operation <= OperationUnknown || operation >= operationCount {
		return DecisionBlocked
	}
	if operation == OperationPausePreparationBackup {
		if state == globalngv1.ResourcePool_PAUSE_PRECHECKING {
			return DecisionAllowed
		}
		return DecisionBlocked
	}

	// Pause/Resume policy does not change the pre-existing behavior of the
	// lifecycle states outside its four-state matrix.
	switch state {
	case globalngv1.ResourcePool_LIFECYCLE_STATE_UNSPECIFIED:
		// Legacy resource pools have no persisted lifecycle state until the
		// metadata backfill completes. Preserve their pre-lifecycle behavior
		// without treating other unknown enum values as valid.
		return DecisionAllowed
	case globalngv1.ResourcePool_CREATING,
		globalngv1.ResourcePool_MODIFYING,
		globalngv1.ResourcePool_ACTIVE,
		globalngv1.ResourcePool_FAILED:
		return DecisionAllowed
	case globalngv1.ResourcePool_PAUSING:
		return decidePausing(operation)
	case globalngv1.ResourcePool_PAUSE_PRECHECKING:
		return decidePausePrechecking(operation)
	case globalngv1.ResourcePool_PAUSED:
		return decidePaused(operation)
	case globalngv1.ResourcePool_RESUMING:
		return decideResuming(operation)
	default:
		return DecisionBlocked
	}
}

func decidePausePrechecking(operation Operation) Decision {
	if operation == OperationPausePreparationBackup {
		return DecisionAllowed
	}
	return DecisionBlocked
}

func decidePausing(operation Operation) Decision {
	switch operation {
	case OperationDeletePool:
		return DecisionAllowed
	default:
		return DecisionBlocked
	}
}

func decidePaused(operation Operation) Decision {
	switch operation {
	case OperationCreateInstance, OperationRestoreInstance:
		return DecisionTriggerOrReuseResume
	case OperationDeleteInstance,
		OperationUpdatePoolLimits,
		OperationRenamePool,
		OperationEditCloudResourceTags,
		OperationDeletePool:
		return DecisionAllowed
	default:
		return DecisionBlocked
	}
}

func decideResuming(operation Operation) Decision {
	switch operation {
	case OperationCreateInstance, OperationRestoreInstance:
		return DecisionTriggerOrReuseResume
	case OperationDeletePool:
		return DecisionAllowed
	default:
		return DecisionBlocked
	}
}
