package entity

import (
	"time"

	apiv1 "github.com/tidbcloud/cluster-service-ng/api/cluster-service-ng/v1beta"
	"github.com/tidbcloud/cluster-service-ng/pkg/nodegroup"
	"github.com/tidbcloud/cluster-service-ng/pkg/storage/mysql/schema"
)

// Re-export state constants for use in domain layer
const (
	NodeInstanceGroupStateNormal           = nodegroup.NodeInstanceGroupStateNormal
	NodeInstanceGroupStateShortageDetected = nodegroup.NodeInstanceGroupStateShortageDetected
	NodeInstanceGroupStateFallbackCreating = nodegroup.NodeInstanceGroupStateFallbackCreating
	NodeInstanceGroupStateFallbackReady    = nodegroup.NodeInstanceGroupStateFallbackReady
	NodeInstanceGroupStateRecovering       = nodegroup.NodeInstanceGroupStateRecovering
	NodeInstanceGroupStateDrainingFallback = nodegroup.NodeInstanceGroupStateDrainingFallback
	NodeInstanceGroupStateDeletingFallback = nodegroup.NodeInstanceGroupStateDeletingFallback
	NodeInstanceGroupStateDeprecated       = nodegroup.NodeInstanceGroupStateDeprecated
)

// NodeInstanceGroup represents the node instance group configuration at region level.
type NodeInstanceGroup = apiv1.NodeInstanceGroup

// NodeInstanceGroupStatusActive indicates an active node instance group.
const NodeInstanceGroupStatusActive = apiv1.NodeInstanceGroup_ACTIVE

// NodeInstanceGroupStatusPending indicates a pending node instance group.
const NodeInstanceGroupStatusPending = apiv1.NodeInstanceGroup_PENDING

// NodeInstanceGroupStatusDeprecated indicates a deprecated node instance group.
const NodeInstanceGroupStatusDeprecated = apiv1.NodeInstanceGroup_DEPRECATED

// NodeInstanceGroupStatusRetiring indicates a node instance group being retired.
const NodeInstanceGroupStatusRetiring = apiv1.NodeInstanceGroup_RETIRING

// NodeInstanceGroupStatusRetired indicates a fully retired node instance group.
const NodeInstanceGroupStatusRetired = apiv1.NodeInstanceGroup_RETIRED

// NodeInstanceGroupInstanceTypeStatusNormal indicates instance type is available.
const NodeInstanceGroupInstanceTypeStatusNormal = apiv1.InstanceTypeStatus_NORMAL

// NodeInstanceGroupInstanceTypeStatusDisabled indicates instance type is disabled.
const NodeInstanceGroupInstanceTypeStatusDisabled = apiv1.InstanceTypeStatus_DISABLED

// DataplaneNodeInstanceGroup represents per-dataplane overrides for node instance groups.
type DataplaneNodeInstanceGroup = apiv1.DataplaneNodeInstanceGroup

// DataplaneNodeInstanceGroupStatusActive indicates the node instance group is active on a dataplane.
const DataplaneNodeInstanceGroupStatusActive = apiv1.DataplaneNodeInstanceGroup_ACTIVE

// DataplaneNodeInstanceGroupStatusDeprecated indicates the node instance group is deprecated on a dataplane.
const DataplaneNodeInstanceGroupStatusDeprecated = apiv1.DataplaneNodeInstanceGroup_DEPRECATED

// DataplaneNodeInstanceGroupStatusRetiring indicates the node instance group is being retired on a dataplane.
const DataplaneNodeInstanceGroupStatusRetiring = apiv1.DataplaneNodeInstanceGroup_RETIRING

// DataplaneNodeInstanceGroupStatusRetired indicates the node instance group is fully retired on a dataplane.
const DataplaneNodeInstanceGroupStatusRetired = apiv1.DataplaneNodeInstanceGroup_RETIRED

// NodeInstanceGroupFallbackInstance describes a fallback instance type.
type NodeInstanceGroupFallbackInstance = apiv1.NodeInstanceGroup_FallbackInstance

// DataplaneNodeInstanceGroupState represents the state of a node instance group in the shortage handling state machine.
type DataplaneNodeInstanceGroupState struct {
	schema.DataplaneNodeInstanceGroupState
}

// IsInShortageHandling returns true if the state indicates active shortage handling.
func (s *DataplaneNodeInstanceGroupState) IsInShortageHandling() bool {
	switch s.State {
	case NodeInstanceGroupStateShortageDetected,
		NodeInstanceGroupStateFallbackCreating,
		NodeInstanceGroupStateFallbackReady,
		NodeInstanceGroupStateRecovering,
		NodeInstanceGroupStateDrainingFallback,
		NodeInstanceGroupStateDeletingFallback:
		return true
	default:
		return false
	}
}

// IsInCooldown returns true if the state is in cooldown period.
func (s *DataplaneNodeInstanceGroupState) IsInCooldown() bool {
	if s.CooldownUntil == nil {
		return false
	}
	return time.Now().Before(*s.CooldownUntil)
}

// DataplaneNodeInstanceGroupLock represents a distributed lock for per-(dataplane, nodeSpec) operations.
type DataplaneNodeInstanceGroupLock struct {
	schema.DataplaneNodeInstanceGroupLock
}

// IsExpired returns true if the lock has expired.
func (l *DataplaneNodeInstanceGroupLock) IsExpired() bool {
	return time.Now().After(l.ExpiresAt)
}
