// Package common add by blacknc <blacknc@163.com> at 2024/08/28 17:17:20
package common

import (
	"context"
	"errors"

	"github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"sigs.k8s.io/controller-runtime/pkg/client"

	eksv1alpha1 "github.com/tidbcloud/eks-provider/api/v1alpha1"
	"github.com/tidbcloud/eks-provider/controllers/dm/task"
	"github.com/tidbcloud/infra-provider/pkg/deploy"
)

// DMPhase manages the status change scaling<->running of dmjob.
type DMPhase struct {
	*task.BaseTask
}

func (t *DMPhase) Name() string {
	return "DMPhase"
}

func NewDMPhase(ctx *task.Context) *DMPhase {
	return &DMPhase{
		BaseTask: &task.BaseTask{Context: ctx},
	}
}

func (t *DMPhase) Create(ctx context.Context) deploy.Result {
	dmCluster := &v1alpha1.DMCluster{
		ObjectMeta: metav1.ObjectMeta{
			Name:      GetDMClusterName(t.DMJob),
			Namespace: GetDMClusterNamespace(t.DMJob, t.GetRegion()),
		},
	}

	if t.DMWorkerSpec == nil {
		return deploy.Panic(errors.New("DMWorkerSpec is nil"))
	}

	found := true
	clusterCli := t.Context.EnvProvider.GetClient()
	if err := clusterCli.Get(ctx, client.ObjectKeyFromObject(dmCluster), dmCluster); err != nil {
		found = false
	}

	switch phase := t.DMJob.Status.Phase; phase {
	case eksv1alpha1.DMJobPhaseRunning:
		if t.DMWorkerSpec.SpecCode != t.DMJob.Status.WorkerSpecCode ||
			t.GetImageTag(t.WorkerImage) != t.DMJob.Status.DMImageTag {
			t.DMJob.Status.Phase = eksv1alpha1.DMJobPhaseScaling
			t.Logger.Info("trans to scaling phase")
		}
	case eksv1alpha1.DMJobPhaseScaling:
		if found && t.DMWorkerSpec.SpecCode == t.DMJob.Status.WorkerSpecCode &&
			t.GetImageTag(t.WorkerImage) == t.DMJob.Status.DMImageTag &&
			dmCluster.Spec.Worker.Labels[specCodeLableKey] == t.DMJob.Status.WorkerSpecCode &&
			dmCluster.Spec.Worker.Labels[imageTagLableKey] == t.DMJob.Status.DMImageTag &&
			t.IsDMClusterReady(dmCluster) && t.MasterNodePoolReady && t.WorkerNodePoolReady {

			t.DMJob.Status.Phase = eksv1alpha1.DMJobPhaseRunning
			t.Logger.Info("trans to running phase")
		}
	}

	return deploy.Done()
}
