package clusteraction

import (
	"context"
	"fmt"
	"strconv"

	opent "github.com/tidbcloud/devops/entity/operation"
	"github.com/tidbcloud/devops/pkg/infra/clients/dataflowcli"
	"github.com/tidbcloud/devops/pkg/service/operation/actions"
)

var (
	ActionResetDMJob opent.ActionMetadata = opent.ActionMetadata{
		Name: "ResetDMJob",
		Type: opent.ActionTypeAuto,
	}
)

type resetDMJob struct {
	actions.BaseAction
	comps *actions.Components
}

func NewResetDMJob(comps *actions.Components) actions.AutoAction {
	return &resetDMJob{comps: comps}
}

func (a *resetDMJob) Metadata() opent.ActionMetadata {
	return ActionResetDMJob
}

func (a *resetDMJob) PreCheck(ctx context.Context, instance *opent.Instance) error {
	_, _, err := a.getParam(instance)
	if err != nil {
		return err
	}

	return nil
}

func (a *resetDMJob) Start(ctx context.Context, instance *opent.Instance) (*actions.ActionResult, error) {
	req, agentURL, err := a.getParam(instance)
	if err != nil {
		return actions.FailedActionResult(err), nil
	}

	err = a.comps.DataflowCli.ResetDMJob(ctx, agentURL, req)
	if err != nil {
		return actions.FailedActionResult(err), nil
	}

	return actions.RunningActionResult("sent request to reset DM job", nil), nil
}

func (a *resetDMJob) Result(ctx context.Context, instance *opent.Instance) (*actions.ActionResult, error) {
	// TODO: how to determine whether the job is reset
	return actions.SucceededActionResult(nil), nil

}

func (a *resetDMJob) getParam(instance *opent.Instance) (dataflowcli.ResetDMJobParam, string, error) {
	p := dataflowcli.ResetDMJobParam{}
	cidStr, _ := instance.GetParam(opent.ParamClusterID)
	if len(cidStr) == 0 {
		return p, "", fmt.Errorf("cluster_id is required")
	}
	p.ClusterID = cidStr

	// check whether the cluster id is in the white list
	info, ok := a.comps.Conf.OperationClusterWhiteList[cidStr]
	if !ok {
		return p, "", fmt.Errorf("cluster %s is not allowed to execute reset DM job", cidStr)
	}

	jobID, _ := instance.GetParam(opent.ParamJobID)
	if len(jobID) == 0 {
		return p, "", fmt.Errorf("job_id is required")
	}
	id, err := strconv.ParseUint(jobID, 10, 64)
	if err != nil {
		return p, "", fmt.Errorf("parse job_id failed: %v", err)
	}
	p.JobId = id

	return p, info.ClusterAgentURL, nil
}
