package impl

import (
	"testing"

	"github.com/stretchr/testify/require"
	"github.com/tidbcloud/dataflow-service-ng/app/event_bus/publisher/center"
	"github.com/tidbcloud/dataflow-service-ng/app/repo/entity"
	"github.com/tidbcloud/eventbus-datastruct/event"
)

func TestConvertPrivateEndpointToDisplayEventCreate(t *testing.T) {
	endpoint := &entity.BizSinkEndpoint{
		Updatable:      entity.Updatable{Base: entity.Base{ID: 9}},
		Name:           "ep-1",
		TenantID:       11,
		EventClusterID: 99,
		EventProjectID: 88,
		EventAuthorID:  77,
		EventAuthor:    "user@example.com",
		SharedPoolID:   "sp-1",
		ServiceName:    "com.amazonaws.vpce.svc",
		Status:         entity.BizPLEndpointStatusCreating,
		EndpointType:   entity.BizSinkEndpointTypeVPCEndpointService,
	}

	ev := convertPrivateEndpointToDisplayEvent(endpoint, entity.CreatePrivateEndpointForExternalServices)
	require.NotNil(t, ev)
	require.Equal(t, string(entity.CreatePrivateEndpointForExternalServices), ev.DisplayEventType)
	require.Equal(t, event.EventStatusStarted, ev.DisplayStatus)
	require.Equal(t, uint64(99), ev.ClusterID)
	require.Equal(t, uint64(88), ev.ProjectID)
	require.Equal(t, uint64(77), ev.AuthorID)
	require.Equal(t, "user@example.com", ev.Author)
	require.Equal(t, "9", ev.ContextID)

	detail, ok := ev.Detail.(*center.PrivateEndpointMsg)
	require.True(t, ok)
	require.Equal(t, uint64(9), detail.EndpointId)
	require.Equal(t, "sp-1", detail.SharedPoolID)
}

func TestConvertPrivateEndpointTerminalStatuses(t *testing.T) {
	tests := map[string]struct {
		eventType     entity.DataflowEventType
		status        entity.BizSinkEndpointStatus
		displayStatus event.EventStatus
	}{
		"create available": {
			eventType:     entity.CreatePrivateEndpointForExternalServices,
			status:        entity.BizPLEndpointStatusAvailable,
			displayStatus: event.EventStatusSucceeded,
		},
		"create failed": {
			eventType:     entity.CreatePrivateEndpointForExternalServices,
			status:        entity.BizPLEndpointStatusFailed,
			displayStatus: event.EventStatusFailed,
		},
		"create rejected": {
			eventType:     entity.CreatePrivateEndpointForExternalServices,
			status:        entity.BizPLEndpointStatusRejected,
			displayStatus: event.EventStatusFailed,
		},
		"delete deleting": {
			eventType:     entity.DeletePrivateEndpointForExternalServices,
			status:        entity.BizPLEndpointStatusDeleting,
			displayStatus: event.EventStatusStarted,
		},
		"delete deleted": {
			eventType:     entity.DeletePrivateEndpointForExternalServices,
			status:        entity.BizPLEndpointStatusDeleted,
			displayStatus: event.EventStatusSucceeded,
		},
	}
	for name, tc := range tests {
		t.Run(name, func(t *testing.T) {
			ev := convertPrivateEndpointToDisplayEvent(
				&entity.BizSinkEndpoint{
					Updatable: entity.Updatable{Base: entity.Base{ID: 1}},
					Name:      "ep",
					Status:    tc.status,
				},
				tc.eventType,
			)
			require.NotNil(t, ev)
			require.Equal(t, tc.displayStatus, ev.DisplayStatus)
			require.Equal(t, string(tc.eventType), ev.DisplayEventType)
		})
	}
}

func TestShouldEmitCreatePrivateEndpointStatus(t *testing.T) {
	require.True(t, shouldEmitCreatePrivateEndpointStatus(entity.BizPLEndpointStatusAvailable))
	require.True(t, shouldEmitCreatePrivateEndpointStatus(entity.BizPLEndpointStatusFailed))
	require.False(t, shouldEmitCreatePrivateEndpointStatus(entity.BizPLEndpointStatusCreating))
	require.False(t, shouldEmitCreatePrivateEndpointStatus(entity.BizPLEndpointStatusPendingAcceptance))
}
