package regionalservice

import (
	"fmt"

	"github.com/tidbcloud/observability/pkg/common/constants"
)

type StatusAccess int

const IDEMPOTENT StatusAccess = 0
const CONFLICT StatusAccess = 1
const EXECUTABLE StatusAccess = 2

func checkStatus(currentStatus constants.ResourceStatus, action constants.ApiEndpoint) StatusAccess {
	if statusMap, actionOK := actionStatusMap[action]; !actionOK {
		panic(fmt.Sprintf("pair [action %s,status %s] is not defined in actionStatusMap", action, currentStatus))
	} else {
		if accessResult, statusOK := statusMap[currentStatus]; !statusOK {
			panic(fmt.Sprintf("pair [action %s,status %s] is not defined in actionStatusMap", action, currentStatus))
		} else {
			return accessResult
		}
	}
}

var actionStatusMap = map[constants.ApiEndpoint]map[constants.ResourceStatus]StatusAccess{
	constants.EndpointClusterCreate: {
		constants.CREATING:        CONFLICT,
		constants.ACTIVE:          CONFLICT,
		constants.UPDATING:        CONFLICT,
		constants.DELETING:        CONFLICT,
		constants.TO_BE_DELETED:   CONFLICT,
		constants.CREATION_FAILED: CONFLICT,
		constants.TO_BE_PAUSED:    CONFLICT,
		constants.PAUSING:         CONFLICT,
		constants.PAUSED:          CONFLICT,
		constants.RESUMING:        CONFLICT,
	},
	constants.EndpointClusterDelete: {
		constants.CREATING:        EXECUTABLE,
		constants.ACTIVE:          EXECUTABLE,
		constants.UPDATING:        CONFLICT,
		constants.DELETING:        IDEMPOTENT,
		constants.TO_BE_DELETED:   IDEMPOTENT,
		constants.CREATION_FAILED: EXECUTABLE,
		constants.TO_BE_PAUSED:    EXECUTABLE,
		constants.PAUSING:         CONFLICT,
		constants.PAUSED:          EXECUTABLE,
		constants.RESUMING:        EXECUTABLE,
	},
	constants.EndpointClusterPause: {
		constants.CREATING:        CONFLICT,
		constants.ACTIVE:          EXECUTABLE,
		constants.UPDATING:        CONFLICT,
		constants.DELETING:        CONFLICT,
		constants.TO_BE_DELETED:   CONFLICT,
		constants.CREATION_FAILED: CONFLICT,
		constants.TO_BE_PAUSED:    IDEMPOTENT,
		constants.PAUSING:         IDEMPOTENT,
		constants.PAUSED:          IDEMPOTENT,
		constants.RESUMING:        CONFLICT,
	},
	constants.EndpointClusterResume: {
		constants.CREATING:        CONFLICT,
		constants.ACTIVE:          IDEMPOTENT,
		constants.UPDATING:        CONFLICT,
		constants.DELETING:        CONFLICT,
		constants.TO_BE_DELETED:   CONFLICT,
		constants.CREATION_FAILED: CONFLICT,
		constants.TO_BE_PAUSED:    EXECUTABLE,
		constants.PAUSING:         EXECUTABLE,
		constants.PAUSED:          EXECUTABLE,
		constants.RESUMING:        IDEMPOTENT,
	},
	constants.EndpointClusterMonitorSpec: {
		constants.CREATING:        CONFLICT,
		constants.ACTIVE:          EXECUTABLE,
		constants.UPDATING:        EXECUTABLE,
		constants.DELETING:        CONFLICT,
		constants.TO_BE_DELETED:   CONFLICT,
		constants.CREATION_FAILED: CONFLICT,
		constants.TO_BE_PAUSED:    EXECUTABLE,
		constants.PAUSING:         CONFLICT,
		constants.PAUSED:          EXECUTABLE,
		constants.RESUMING:        CONFLICT,
	},
	constants.EndpointClusterAgentObserved: {
		constants.CREATING:        CONFLICT,
		constants.ACTIVE:          EXECUTABLE,
		constants.UPDATING:        EXECUTABLE,
		constants.DELETING:        CONFLICT,
		constants.TO_BE_DELETED:   CONFLICT,
		constants.CREATION_FAILED: CONFLICT,
		constants.TO_BE_PAUSED:    EXECUTABLE,
		constants.PAUSING:         CONFLICT,
		constants.PAUSED:          EXECUTABLE,
		constants.RESUMING:        CONFLICT,
	},
	constants.EndpointClusterUpdate: {
		constants.CREATING:        CONFLICT,
		constants.ACTIVE:          EXECUTABLE,
		constants.UPDATING:        EXECUTABLE,
		constants.DELETING:        CONFLICT,
		constants.TO_BE_DELETED:   CONFLICT,
		constants.CREATION_FAILED: CONFLICT,
		constants.TO_BE_PAUSED:    EXECUTABLE,
		constants.PAUSING:         CONFLICT,
		constants.PAUSED:          EXECUTABLE,
		constants.RESUMING:        CONFLICT,
	},
}
