package action

import (
	"os"
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/mock"
	"github.com/stretchr/testify/require"
	"github.com/tidbcloud/cluster-service-ng/domain/entity"
	"github.com/tidbcloud/cluster-service-ng/domain/workflow"
	dataplanemocks "github.com/tidbcloud/cluster-service-ng/pkg/dataplane/mocks"
	"github.com/tidbcloud/cluster-service-ng/pkg/runtime/actions"
	repomocks "github.com/tidbcloud/cluster-service-ng/pkg/storage/repo/mocks"
	"github.com/tidbcloud/cluster-service-ng/pkg/template/render"
	"sigs.k8s.io/yaml"
)

func TestApplySharedPoolRejectsInvalidPauseResumeCombinationBeforeDataplaneAccess(t *testing.T) {
	tests := []struct {
		name    string
		state   entity.PauseResumeState
		desired bool
	}{
		{name: "normal pool cannot desire suspension", desired: true},
		{name: "paused pool must desire suspension", state: entity.PauseResumeStatePaused},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			repo := repomocks.NewSharedPoolRepo(t)
			manager := dataplanemocks.NewManager(t)
			repo.EXPECT().Load(mock.Anything, "sp-1", false).Return(&entity.SharedPool{
				PauseResumeState: tt.state, SuspendComputeDesired: tt.desired,
			}, nil).Once()

			action := NewApplySharedPoolAction(repo, manager, nil)
			err := action.Invoke(actions.ActionArgs{
				workflow.SharedPoolIdKey: actions.ActionArgString("sp-1"),
			})
			require.ErrorContains(t, err, "invalid sharedPool pause/resume state")
			manager.AssertNotCalled(t, "GetClient", mock.Anything)
		})
	}
}

func TestTiDBClusterTemplateUsesNoConstraints(t *testing.T) {
	content, err := os.ReadFile("../../../deployments/templates/tidb_cluster.templ")
	require.NoError(t, err)

	templateLibrary := render.NewTemplateLibrary()
	templateLibrary.SafeNewTemplate("tidb_cluster", string(content))
	rendered, err := templateLibrary.Render("tidb_cluster", map[string]string{
		"ClusterId":      "sp-1",
		"SharedPoolId":   "sp-1",
		"BootStrapSQL":   "bootstrap-sql",
		"ClusterType":    "private",
		"SuspendCompute": "false",
	})
	require.NoError(t, err)

	var cluster struct {
		Spec struct {
			UpgradePolicy string `yaml:"upgradePolicy"`
			SuspendAction struct {
				SuspendCompute bool `yaml:"suspendCompute"`
			} `yaml:"suspendAction"`
		} `yaml:"spec"`
	}
	require.NoError(t, yaml.Unmarshal([]byte(rendered), &cluster))
	assert.Equal(t, "NoConstraints", cluster.Spec.UpgradePolicy)
	assert.False(t, cluster.Spec.SuspendAction.SuspendCompute)
}
