package action

import (
	"context"
	"fmt"

	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
)

// Action defines and implement a Workflow Action, be referenced in Workflow Step
type Action interface {
	// Name return the name of Action, it should be unique in registry and named by CamelCase such as 'SleepAction'.
	Name() cloudv1.WorkflowActionName
	// PreCheck does some check in initialization of this workflow, for example, check required inputs.
	PreCheck(ctx context.Context, wf *cloudv1.Workflow, step cloudv1.WorkflowStep) error
	// Handle the logic of this Action.
	// Return error means something goes wrong, and whether to retry depends on the RetryPolicy
	// Return nil means this Action is Completed
	Handle(ctx context.Context, wf *cloudv1.Workflow, step cloudv1.WorkflowStep) error
}

type ActionPost interface {
	// PostHandle does some cleanup work after the workflow is finished, such as deleting temporary resources.
	PostHandle(ctx context.Context, wf *cloudv1.Workflow, step cloudv1.WorkflowStep) error
}

// ActionCancel defines an optional interface for Actions that support cancellation.
// Actions implementing this interface can handle cancellation requests and cleanup.
type ActionCancel interface {
	// Cancel handles the cancellation logic when a step is being cancelled.
	Cancel(ctx context.Context, wf *cloudv1.Workflow, step cloudv1.WorkflowStep, dryRun bool) error
	// PostCancel performs cleanup work after a step has been cancelled.
	PostCancel(ctx context.Context, wf *cloudv1.Workflow, step cloudv1.WorkflowStep) error
}

type ActionStepNotCancelableError struct {
	err error
}

func NewActionStepNotCancelableError(err error) error {
	return &ActionStepNotCancelableError{err: err}
}

func (e *ActionStepNotCancelableError) Error() string {
	return fmt.Sprintf("step is not cancelable: %s", e.err.Error())
}

func (e *ActionStepNotCancelableError) Unwrap() error {
	return e.err
}
