package sqs

import (
	"context"

	"github.com/aws/aws-sdk-go-v2/service/sqs"

	"wucher/internal/resilience"
)

type resilientAPI struct {
	next     API
	executor *resilience.Executor
}

func NewResilientAPI(next API, executor *resilience.Executor) API {
	if next == nil || executor == nil || !executor.Enabled() {
		return next
	}
	return &resilientAPI{
		next:     next,
		executor: executor,
	}
}

func (r *resilientAPI) SendMessage(ctx context.Context, params *sqs.SendMessageInput, optFns ...func(*sqs.Options)) (*sqs.SendMessageOutput, error) {
	return resilience.Do(ctx, r.executor, func(ctx context.Context) (*sqs.SendMessageOutput, error) {
		return r.next.SendMessage(ctx, params, optFns...)
	})
}

func (r *resilientAPI) ReceiveMessage(ctx context.Context, params *sqs.ReceiveMessageInput, optFns ...func(*sqs.Options)) (*sqs.ReceiveMessageOutput, error) {
	return resilience.Do(ctx, r.executor, func(ctx context.Context) (*sqs.ReceiveMessageOutput, error) {
		return r.next.ReceiveMessage(ctx, params, optFns...)
	})
}

func (r *resilientAPI) DeleteMessageBatch(ctx context.Context, params *sqs.DeleteMessageBatchInput, optFns ...func(*sqs.Options)) (*sqs.DeleteMessageBatchOutput, error) {
	return resilience.Do(ctx, r.executor, func(ctx context.Context) (*sqs.DeleteMessageBatchOutput, error) {
		return r.next.DeleteMessageBatch(ctx, params, optFns...)
	})
}

func (r *resilientAPI) ChangeMessageVisibility(ctx context.Context, params *sqs.ChangeMessageVisibilityInput, optFns ...func(*sqs.Options)) (*sqs.ChangeMessageVisibilityOutput, error) {
	return resilience.Do(ctx, r.executor, func(ctx context.Context) (*sqs.ChangeMessageVisibilityOutput, error) {
		return r.next.ChangeMessageVisibility(ctx, params, optFns...)
	})
}

func (r *resilientAPI) GetQueueAttributes(ctx context.Context, params *sqs.GetQueueAttributesInput, optFns ...func(*sqs.Options)) (*sqs.GetQueueAttributesOutput, error) {
	return resilience.Do(ctx, r.executor, func(ctx context.Context) (*sqs.GetQueueAttributesOutput, error) {
		return r.next.GetQueueAttributes(ctx, params, optFns...)
	})
}
