package backupv2_test

import (
	"testing"

	"github.com/stretchr/testify/suite"
	"github.com/tidbcloud/dataflow-service/app/internal/status_matrix"
	"github.com/tidbcloud/dataflow-service/app/models/backup/impl"
	"github.com/tidbcloud/dataflow-service/app/repo/entity"
)

type pitBackupSwitchTestSuite struct {
	suite.Suite
	statusMatrix status_matrix.StatusMatrix
}

func TestPitBackupSwitchTestSuite(t *testing.T) {
	suite.Run(t, new(pitBackupSwitchTestSuite))
}

func (s *pitBackupSwitchTestSuite) SetupSuite() {
	s.statusMatrix = impl.NewPitBackupSwitchStatusMatrix()
}

//nolint:funlen
func (s *pitBackupSwitchTestSuite) TestPitBackupSwitchStatusMatrixHappyCases() {
	type testCase struct {
		name          string
		currentStatus entity.PitBackupSwitchStatus
		currentAction []string

		action       entity.PitBackupSwitchActionType
		steadyAction bool

		targetStatus entity.PitBackupSwitchStatus
		targetAction []string
	}

	caseList := []testCase{
		{
			name:          "from disabled to enabling",
			action:        entity.PitBackupSwitchActionEnable,
			currentStatus: entity.PitBackupStatusDisabled,
			currentAction: []string{},
			targetStatus:  entity.PitBackupStatusWaitingForEnabling,
			targetAction:  []string{string(entity.PitBackupSwitchActionEnable)},
		},

		{
			name:          "from enabling to doing backup",
			action:        entity.PitBackupSwitchActionDoEnable,
			currentStatus: entity.PitBackupStatusWaitingForEnabling,
			currentAction: []string{string(entity.PitBackupSwitchActionEnable)},
			targetStatus:  entity.PitBackupStatusEnabling,
			targetAction:  []string{string(entity.PitBackupSwitchActionDoEnable)},
		},

		{
			name:          "from enabling to disabled(cancel enable)",
			action:        entity.PitBackupSwitchActionDisable,
			currentStatus: entity.PitBackupStatusWaitingForEnabling,
			currentAction: []string{string(entity.PitBackupSwitchActionEnable)},
			targetStatus:  entity.PitBackupStatusDisabled,
			targetAction:  []string{string(entity.PitBackupSwitchActionDisable)},
		},

		{
			name:          "from enabled to disabling",
			action:        entity.PitBackupSwitchActionDisable,
			currentStatus: entity.PitBackupStatusEnabled,
			currentAction: []string{},
			targetStatus:  entity.PitBackupStatusDisabling,
			targetAction:  []string{string(entity.PitBackupSwitchActionDisable)},
		},

		{
			name:          "from enabled to need_restart",
			action:        entity.PitBackupSwitchActionRestart,
			currentStatus: entity.PitBackupStatusEnabled,
			currentAction: []string{},
			targetStatus:  entity.PitBackupStatusWaitingForRestarting,
			targetAction:  []string{string(entity.PitBackupSwitchActionRestart)},
		},

		{
			name:          "from need_restart to  do_restart",
			action:        entity.PitBackupSwitchActionDoRestart,
			currentStatus: entity.PitBackupStatusWaitingForRestarting,
			currentAction: []string{string(entity.PitBackupSwitchActionRestart)},
			targetStatus:  entity.PitBackupStatusRestarting,
			targetAction:  []string{string(entity.PitBackupSwitchActionDoRestart)},
		},
		{
			name:          "retry compensated restart with no current action",
			action:        entity.PitBackupSwitchActionDoRestart,
			currentStatus: entity.PitBackupStatusWaitingForRestarting,
			currentAction: []string{},
			targetStatus:  entity.PitBackupStatusRestarting,
			targetAction:  []string{string(entity.PitBackupSwitchActionDoRestart)},
		},

		{
			name:          "from need_restart to disabled(cancel restart)",
			action:        entity.PitBackupSwitchActionCancelRestart,
			currentStatus: entity.PitBackupStatusWaitingForRestarting,
			currentAction: []string{string(entity.PitBackupSwitchActionRestart)},
			targetStatus:  entity.PitBackupStatusEnabled,
			targetAction:  []string{string(entity.PitBackupSwitchActionCancelRestart)},
		},
		{
			name:          "cancel compensated restart with no current action",
			action:        entity.PitBackupSwitchActionCancelRestart,
			currentStatus: entity.PitBackupStatusWaitingForRestarting,
			currentAction: []string{},
			targetStatus:  entity.PitBackupStatusEnabled,
			targetAction:  []string{string(entity.PitBackupSwitchActionCancelRestart)},
		},
	}

	for _, c := range caseList {
		s.Run(c.name, func() {
			req := status_matrix.CurrentStatus{Status: string(c.currentStatus), Actions: c.currentAction}
			nextStatus := s.statusMatrix.CalculateNextStatusForAction(req, string(c.action))
			s.NotNil(nextStatus, "next status should not be nil")
			s.Equal(c.targetStatus, entity.PitBackupSwitchStatus(nextStatus.Status), "target status not match")
			s.Equal(c.targetAction, nextStatus.Actions, "target action not match")
		})
	}
}
