package entity

import (
	"testing"

	"github.com/stretchr/testify/require"
	clusterngv1beta "github.com/tidbcloud/cluster-service-ng/api/cluster-service-ng/v1beta"

	globalcommonv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/common/v1"
	globalngv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/nextgen/v1"
	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
	"github.com/tidbcloud/tidb-management-service/utilities/clusterevent"
)

func TestNewResourcePoolLifecycleEvent(t *testing.T) {
	tests := []struct {
		name      string
		eventType clusterevent.EventType
		status    string
	}{
		{name: "pausing", eventType: clusterevent.EventTypePausing, status: "CLUSTER_STATUS_PAUSING"},
		{name: "paused", eventType: clusterevent.EventTypePaused, status: "CLUSTER_STATUS_PAUSED"},
		{name: "resuming", eventType: clusterevent.EventTypeResuming, status: "CLUSTER_STATUS_RESUMING"},
		{name: "resumed", eventType: clusterevent.EventTypeResumed, status: "CLUSTER_STATUS_NORMAL"},
	}
	resourcePool := &ResourcePool{ResourcePool: &globalngv1.ResourcePool{
		Id:          100,
		OwnerId:     42,
		ServicePlan: globalcommonv1.ServicePlan_BYOC,
	}}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			event, berr := NewResourcePoolLifecycleEvent(t.Context(), resourcePool, tt.eventType)

			require.NoError(t, berr)
			require.Equal(t, tt.eventType, event.EventType)
			require.Equal(t, tt.status, event.Status)
			require.Equal(t, uint64(100), event.ClusterID)
			require.Equal(t, uint64(42), event.TenantID)
			require.Equal(t, clusterevent.ClusterTypeTidbxResourcePool, event.ClusterType)
		})
	}
}

func TestNewResourcePoolLifecycleEventRejectsNilResourcePool(t *testing.T) {
	event, berr := NewResourcePoolLifecycleEvent(t.Context(), nil, clusterevent.EventTypePausing)

	require.Nil(t, event)
	require.Error(t, berr)
	require.Equal(t, bizerr.ErrCodeParams, berr.ErrCode())
}

func TestBuildResourcePoolTopology_PremiumReservedIncludesSpecAndCount(t *testing.T) {
	sharedPool := &clusterngv1beta.SharedPool{
		ComponentGroups: []*clusterngv1beta.Component{
			{
				ComponentType: clusterngv1beta.ComponentType_TIKV,
				NodeQuota: &clusterngv1beta.NodeQuota{
					NodeSpec:  &clusterngv1beta.NodeSpec{Cpu: 8, MemoryGi: 32},
					NodeCount: 3,
				},
				Storages: []*clusterngv1beta.Component_Storage{
					{Name: clusterngv1beta.Component_Storage_DATA, Type: "gp3"},
					{Name: clusterngv1beta.Component_Storage_RAFTLOG, Type: "gp3"},
				},
			},
		},
	}

	topology := buildResourcePoolTopology(sharedPool, globalcommonv1.ServicePlan_Premium_Reserved)
	require.Equal(t, "{TiKV x3 (8C32G, DATA: gp3, RAFTLOG: gp3)}", topology)
}

func TestBuildResourcePoolTopology_NonPremiumReservedKeepsLegacyFormat(t *testing.T) {
	sharedPool := &clusterngv1beta.SharedPool{
		ComponentGroups: []*clusterngv1beta.Component{
			{
				ComponentType: clusterngv1beta.ComponentType_TIKV,
				NodeQuota: &clusterngv1beta.NodeQuota{
					NodeSpec:  &clusterngv1beta.NodeSpec{Cpu: 8, MemoryGi: 32},
					NodeCount: 3,
				},
				Storages: []*clusterngv1beta.Component_Storage{
					{Name: clusterngv1beta.Component_Storage_DATA, Type: "gp3"},
					{Name: clusterngv1beta.Component_Storage_RAFTLOG, Type: "gp3"},
				},
			},
		},
	}

	topology := buildResourcePoolTopology(sharedPool, globalcommonv1.ServicePlan_Premium)
	require.Equal(t, "{TiKV (DATA: gp3, RAFTLOG: gp3)}", topology)
}
