package entity

import (
	"hash/fnv"
	"slices"
	"strings"
	"time"

	"github.com/google/uuid"

	openapicommonv1beta1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_cloud_open_api/common/v1beta1"
	tidbmgmtservicev1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_mgmt_service/v1"
)

type ClusterCustomStatus struct {
	StatusId      uint64
	StatusName    string
	StatusType    tidbmgmtservicev1.CustomStatusType
	ClusterId     uint64
	CustomMutex   *tidbmgmtservicev1.ClusterCustomStatus_CustomMutex
	TimeoutSecs   *int64
	OverrideState *openapicommonv1beta1.ClusterState
	CreatedAt     time.Time
	DeleteAt      *time.Time
}

func GenStatusId() uint64 {
	const (
		statusIdStartAt = 100000000000
		statusIdMod     = 10000000000
	)

	h := fnv.New64()
	uuidStr := strings.Replace(uuid.New().String(), "-", "", 4)
	_, _ = h.Write([]byte(uuidStr))

	return h.Sum64()%statusIdMod + statusIdStartAt
}

// check if the custom status is expired
func (c *ClusterCustomStatus) IsExpired() bool {
	if c.TimeoutSecs == nil || *c.TimeoutSecs == 0 {
		return false
	}

	expiredAt := c.CreatedAt.Add(time.Duration(*c.TimeoutSecs) * time.Second)

	return time.Now().UTC().After(expiredAt)
}

func (c *ClusterCustomStatus) IsStatusMutexed(statusType tidbmgmtservicev1.CustomStatusType) bool {
	// expired status is not mutexed
	if c.IsExpired() {
		return false
	}

	if c.CustomMutex == nil {
		return false
	}
	return slices.Contains(c.CustomMutex.StatusType, statusType)
}

func (c *ClusterCustomStatus) IsActionMutexed(clusterAction tidbmgmtservicev1.ClusterAction) bool {
	// expired status is not mutexed
	if c.IsExpired() {
		return false
	}

	if c.CustomMutex == nil {
		return false
	}
	return slices.Contains(c.CustomMutex.ClusterAction, clusterAction)
}
