package cmd

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	openapi "github.com/tidbcloud/tidb-management-service/api/spec/tidb_cloud_open_api/common/v1beta1"
	mgmt "github.com/tidbcloud/tidb-management-service/api/spec/tidb_mgmt_service/v1"
)

func TestCustomStatusCreateRequest(t *testing.T) {
	request, err := (customStatusCreateOptions{
		clusterID:      42,
		statusType:     "pitr",
		statusName:     "pitr-job-7",
		overrideStatus: "maintenance",
		timeoutSecs:    300,
		blockActions:   []string{"pause_cluster", "DELETE_CLUSTER"},
	}).request()
	require.NoError(t, err)

	status := request.GetCustomStatus()
	assert.Equal(t, uint64(42), status.GetClusterId())
	assert.Equal(t, "pitr-job-7", status.GetStatusName())
	assert.Equal(t, mgmt.CustomStatusType_CUSTOM_STATUS_TYPE_PITR, status.GetStatusType())
	assert.Equal(t, int64(300), status.GetTimeoutSecs())
	require.NotNil(t, status.OverrideStatus)
	assert.Equal(t, openapi.ClusterState_MAINTENANCE, status.GetOverrideStatus())
	assert.Equal(t, []mgmt.ClusterAction{
		mgmt.ClusterAction_CLUSTER_ACTION_PAUSE_CLUSTER,
		mgmt.ClusterAction_CLUSTER_ACTION_DELETE_CLUSTER,
	}, status.GetMutex().GetClusterAction())
}

func TestCustomStatusCreateRequestRejectsInvalidOptions(t *testing.T) {
	tests := map[string]customStatusCreateOptions{
		"missing cluster ID":   {statusType: "pitr", statusName: "pitr-job-7"},
		"missing status name":  {clusterID: 42, statusType: "pitr"},
		"invalid status type":  {clusterID: 42, statusType: "invalid", statusName: "pitr-job-7"},
		"invalid override":     {clusterID: 42, statusType: "pitr", statusName: "pitr-job-7", overrideStatus: "invalid"},
		"invalid block action": {clusterID: 42, statusType: "pitr", statusName: "pitr-job-7", blockActions: []string{"invalid"}},
		"negative timeout":     {clusterID: 42, statusType: "pitr", statusName: "pitr-job-7", timeoutSecs: -1},
	}
	for name, options := range tests {
		t.Run(name, func(t *testing.T) {
			_, err := options.request()
			require.Error(t, err)
		})
	}
}

func TestCustomStatusCommandRegistersOperations(t *testing.T) {
	command := newCustomStatusCommand()
	createCommand, _, err := command.Find([]string{"create"})
	require.NoError(t, err)
	assert.NotNil(t, createCommand.Flags().Lookup("block-action"))
	assert.Nil(t, createCommand.Flags().Lookup("block-pause"))
	_, _, err = command.Find([]string{"delete"})
	require.NoError(t, err)
	_, _, err = command.Find([]string{"query"})
	require.NoError(t, err)
}
