package utils

import (
	"fmt"
	"time"

	perrors "github.com/pingcap/errors"
)

// IsRealError checks if the given error is a real error.
// If err is the type of `RequeueAfterError` but its Caused is nil,
// it means that the given error is not an error, actually.
func IsRealError(err error) bool {
	if err == nil {
		return false
	}

	if requeueErr, ok := err.(*RequeueAfterError); ok && requeueErr.Caused == nil {
		return false
	}

	return true
}

type RequeueAfterError struct {
	Caused error
	// RequeueAfter is the duration after which the request should be enqueued again.
	RequeueAfter time.Duration
}

func New(requeueAfter time.Duration, cause error) *RequeueAfterError {
	return &RequeueAfterError{
		Caused:       cause,
		RequeueAfter: requeueAfter,
	}
}

func (e *RequeueAfterError) Cause() error {
	return e.Caused
}

func (e *RequeueAfterError) Error() string {
	if e.Caused == nil {
		return fmt.Sprintf("requeue in %s", e.RequeueAfter)
	}

	return fmt.Sprintf("requeue in %s due to %s", e.RequeueAfter, perrors.Cause(e.Caused))
}
