package basic

import (
	"context"
	"fmt"
	"time"

	"github.com/mitchellh/mapstructure"

	"github.com/tidbcloud/eks-provider/controllers/workflow/action"
	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	"github.com/tidbcloud/infra-provider/pkg/consts"
)

// sleepAction
// inputs:
// - duration: the duration to sleep, for example, "10s"
type sleepAction struct{}

type sleepInputs struct {
	Duration string `mapstructure:"duration" json:"duration" validate:"required"`
}

var (
	_ action.Action = &sleepAction{}
)

func init() {
	action.RegisterWorkflowAction(&sleepAction{})
}

func (d *sleepAction) Name() cloudv1.WorkflowActionName {
	return consts.WorkflowActionSleep
}

func (d *sleepAction) PreCheck(ctx context.Context, wf *cloudv1.Workflow, step cloudv1.WorkflowStep) error {
	// check required inputs
	inputs := &sleepInputs{}
	if err := mapstructure.Decode(step.Inputs.Object, inputs); err != nil {
		return fmt.Errorf("decode inputs: %w", err)
	}
	if _, err := time.ParseDuration(inputs.Duration); err != nil {
		return fmt.Errorf("parse duration %v: %w", inputs.Duration, err)
	}
	return nil
}

func (d *sleepAction) Handle(ctx context.Context, wf *cloudv1.Workflow, step cloudv1.WorkflowStep) error {
	return nil
}

func (d *sleepAction) PostHandle(ctx context.Context, wf *cloudv1.Workflow, step cloudv1.WorkflowStep) error {
	stepStatus, _ := wf.StepStatus(ctx, step.Name)

	inputs := &sleepInputs{}
	if err := mapstructure.Decode(step.Inputs.Object, inputs); err != nil {
		return fmt.Errorf("decode inputs: %w", err)
	}
	duration, _ := time.ParseDuration(inputs.Duration)
	now := time.Now()
	if now.After(stepStatus.BeginAt.Time.Add(duration)) {
		// reach the target time
		return nil
	}

	return fmt.Errorf("exepected to run at %s", stepStatus.BeginAt.Add(duration).Format(time.RFC3339))
}
