// This file is generated by tools, DO NOT EDIT.
package taskgen

import (
	"context"
	"encoding/json"
	"fmt"
	"time"

	"github.com/cloudcarver/anclax/pkg/zgen/apigen"
	"github.com/cloudcarver/anclax/pkg/taskcore"
	"github.com/cloudcarver/anclax/pkg/taskcore/worker"
	"github.com/cloudcarver/anclax/pkg/utils"
	"github.com/pkg/errors"
	"github.com/jackc/pgx/v5"
)

func init() {
	utils.Noop()
}

const ( 
	DeleteOpaqueKey = "deleteOpaqueKey" 
)



type TaskRunner interface { 
    // Delete an opaque key
	RunDeleteOpaqueKey(ctx context.Context, params *DeleteOpaqueKeyParameters, overrides ...taskcore.TaskOverride) (int32, error)
    // Delete an opaque key
	RunDeleteOpaqueKeyWithTx(ctx context.Context, tx pgx.Tx, params *DeleteOpaqueKeyParameters, overrides ...taskcore.TaskOverride) (int32, error)
}

type Client struct {
	taskStore taskcore.TaskStoreInterface
	now       func() time.Time
}

func NewTaskRunner(taskStore taskcore.TaskStoreInterface) TaskRunner {
	return &Client{
		taskStore: taskStore,
		now:       time.Now,
	}
}


func (c *Client) RunDeleteOpaqueKey(ctx context.Context, params *DeleteOpaqueKeyParameters, overrides ...taskcore.TaskOverride) (int32, error) {
	return c.runDeleteOpaqueKey(ctx, c.taskStore, params, overrides...)
}

func (c *Client) RunDeleteOpaqueKeyWithTx(ctx context.Context, tx pgx.Tx, params *DeleteOpaqueKeyParameters, overrides ...taskcore.TaskOverride) (int32, error) {
	return c.runDeleteOpaqueKey(ctx, c.taskStore.WithTx(tx), params, overrides...)
}

func (c *Client) runDeleteOpaqueKey(ctx context.Context, taskstore taskcore.TaskStoreInterface, params *DeleteOpaqueKeyParameters, overrides ...taskcore.TaskOverride) (int32, error) {
	payload, err := params.Marshal()
	if err != nil {
		return 0, err
	}

	spec := apigen.TaskSpec{
		Type:    DeleteOpaqueKey,
		Payload: payload,
	}
	attributes := apigen.TaskAttributes{}
	
	attributes.RetryPolicy = &apigen.TaskRetryPolicy{
		Interval:    "30m",
		MaxAttempts: -1,
	}
	
	task := &apigen.Task{
		Attributes: attributes,
		Spec:       spec,
		Status:     apigen.Pending,
	}
	
	for _, override := range overrides {
		if err := override(task); err != nil {
			return 0, errors.Wrap(err, "failed to apply task override")
		}
	}
	taskID, err := taskstore.PushTask(ctx, task)
	if err != nil {
		return 0, err
	}
	return taskID, nil
}


type DeleteOpaqueKeyParameters struct { 
    // The ID of the opaque key to delete
	KeyID int64 `json:"keyID" yaml:"keyID"`
}

func (r *DeleteOpaqueKeyParameters) Parse(spec json.RawMessage) error {
	return json.Unmarshal(spec, r)
}

func (r *DeleteOpaqueKeyParameters) Marshal() (json.RawMessage, error) {
	return json.Marshal(r)
}

type ExecutorInterface interface { 
    // Delete an opaque key
	ExecuteDeleteOpaqueKey(ctx context.Context, tx pgx.Tx, params *DeleteOpaqueKeyParameters) error

	// Hook called when deleteOpaqueKey fails
	OnDeleteOpaqueKeyFailed(ctx context.Context, taskID int32, params *DeleteOpaqueKeyParameters, tx pgx.Tx) error
}

type TaskHandler struct {
	executor ExecutorInterface

	externalTaskHandler []worker.TaskHandler
}

func NewTaskHandler(executor ExecutorInterface) worker.TaskHandler {
	return &TaskHandler{
		executor: executor,
	}
}

func (f *TaskHandler) RegisterTaskHandler(handler worker.TaskHandler) {
	f.externalTaskHandler = append(f.externalTaskHandler, handler)
}

func (f *TaskHandler) HandleTask(ctx context.Context, tx pgx.Tx, spec worker.TaskSpec) error {
	for _, handler := range f.externalTaskHandler {
		if err := handler.HandleTask(ctx, tx, spec); err != nil {
			if errors.Is(err, worker.ErrUnknownTaskType) {
				continue
			}
			return err
		}
		return nil
	}

	switch spec.GetType() { 
	case DeleteOpaqueKey:
		var params DeleteOpaqueKeyParameters
		if err := params.Parse(spec.GetPayload()); err != nil {
			return fmt.Errorf("failed to parse deleteOpaqueKey parameters: %w", err)
		}
		return f.executor.ExecuteDeleteOpaqueKey(ctx, tx, &params)
		
	default:
		return errors.Wrapf(worker.ErrUnknownTaskType, "unknown task type: %s", spec.GetType())
	}
}

func (f *TaskHandler) OnTaskFailed(ctx context.Context, tx pgx.Tx, failedTaskSpec worker.TaskSpec, taskID int32) error {
	for _, handler := range f.externalTaskHandler {
		if err := handler.OnTaskFailed(ctx, tx, failedTaskSpec, taskID); err != nil {
			if errors.Is(err, worker.ErrUnknownTaskType) {
				continue
			}
			return err
		}
		return nil
	}

	// Call the appropriate OnXXXFailed hook method
	switch failedTaskSpec.GetType() { 
	case DeleteOpaqueKey:
		var params DeleteOpaqueKeyParameters
		if err := params.Parse(failedTaskSpec.GetPayload()); err != nil {
			return fmt.Errorf("failed to parse deleteOpaqueKey parameters: %w", err)
		}
		return f.executor.OnDeleteOpaqueKeyFailed(ctx, taskID, &params, tx)
	default:
		return nil // No hook configured for this task type
	}
}
