package common

import (
	"context"
	"fmt"

	batchv1 "k8s.io/api/batch/v1"
	"k8s.io/apimachinery/pkg/types"
	"sigs.k8s.io/controller-runtime/pkg/log"

	"github.com/tidbcloud/eks-provider/controllers/dumpling/task"
	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	"github.com/tidbcloud/infra-provider/pkg/deploy"
)

const tidbPrefix = "tidb"

type Observe struct {
	*task.BaseTask
}

func NewObserve(context *task.Context) *Observe {
	return &Observe{BaseTask: &task.BaseTask{Context: context}}
}

func (task *Observe) Name() string {
	return "Observe"
}

func (task *Observe) Create(ctx context.Context) deploy.Result {
	logger := log.FromContext(ctx)
	logger.Info("begin create in observe task")

	switch phase := task.Dumpling.Status.Phase; phase {
	case cloudv1.DumplingPhaseSucceed:
		logger.Info("Status is DumplingPhaseSucceed, Reconcile Done")
		return deploy.Done()
	case cloudv1.DumplingPhaseRunning:
		cli, err := task.Remote.GetClient(ctx)
		if err != nil {
			return deploy.Panic(fmt.Errorf("get remote client failed: %v", err))
		}

		var dumpling batchv1.Job
		if err := cli.Get(ctx, types.NamespacedName{
			Name:      dumplingPrefix + task.Dumpling.ObjectMeta.Name,
			Namespace: tidbPrefix + task.Dumpling.Spec.ClusterName,
		}, &dumpling); err != nil {
			return deploy.Error(fmt.Errorf("get dumpling job failed: %v", err))
		}

		// get condition status to check dumpling job status
		index := len(dumpling.Status.Conditions) - 1
		if index < 0 {
			return deploy.Panic(fmt.Errorf("wait dumpling job begin: %v", err))
		}

		if dumpling.Status.Conditions[index].Type == batchv1.JobFailed {
			message := dumpling.Status.Conditions[index].Message
			reason := dumpling.Status.Conditions[index].Reason
			task.Dumpling.Status.Phase = cloudv1.DumplingPhaseFailed
			task.Dumpling.Status.Message = message
			return deploy.Panic(fmt.Errorf("dumpling cr failed with message %s and reason %s", message, reason))
		} else if dumpling.Status.Conditions[index].Type == batchv1.JobComplete {
			task.Dumpling.Status.Phase = cloudv1.DumplingPhaseSucceed

			logger.Info("Status set DumplingPhaseSucceed, Reconcile Done")
			return deploy.Done()
		} else {
			logger.Info("Job type is %s with message is %", dumpling.Status.Conditions[index].Type, dumpling.Status.Conditions[index].Message)
		}

	}
	return deploy.Panic(fmt.Errorf("still doing dumpling"))
}
