package sqspoller

import (
	"fmt"
	"time"

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

type HookEvent interface {
	String() string
	Error() error
}

// HookEventPollError signifies an error that occurred when we asked SQS for more messages.
type HookEventPollError struct {
	PollerID int
	Request  *sqs.ReceiveMessageInput
	Err      error
}

func (h *HookEventPollError) String() string { return h.Err.Error() }
func (h *HookEventPollError) Error() error   { return h.Err }

type HookEventAckError struct {
	Request        *sqs.DeleteMessageBatchInput
	Err            error
	ReceiptHandles []string
}

func (h *HookEventAckError) String() string {
	return fmt.Sprintf("Failed batch ack on handles %v with error %s", h.ReceiptHandles, h.Err.Error())
}

func (h *HookEventAckError) Error() error {
	return h.Err
}

type HookEventAckPartialFail struct {
	FailedHandles []string
	Request       *sqs.DeleteMessageBatchInput
	Result        *sqs.DeleteMessageBatchOutput
}

func (h *HookEventAckPartialFail) String() string {
	var messages []string
	for i, handle := range h.FailedHandles {
		failed := h.Result.Failed[i]
		messages = append(messages, fmt.Sprintf("handle %q with code %q and message %s", handle, aws.StringValue(failed.Code), aws.StringValue(failed.Message)))
	}
	return fmt.Sprintf("Partially failed batch ack: %d failed with messages: %v", len(h.FailedHandles), messages)
}

func (h *HookEventAckPartialFail) Error() error { return nil }

type HookEventBatchDelivered struct {
	Messages    []*sqs.Message
	DeliveredIn time.Duration
}

func (h *HookEventBatchDelivered) String() string {
	return fmt.Sprintf("%d messages delivered to channel in %s", len(h.Messages), h.DeliveredIn.Round(time.Microsecond))
}

func (h *HookEventBatchDelivered) Error() error { return nil }
