package http

import (
	"github.com/sony/gobreaker/v2"
	"golang.source-fellows.com/pattern/circuitbreaker/internal"
	"log"
	"time"
)

func NewCircuitBreakerDecorator(
	wrapped internal.PaymentServiceProvider) *CircuitBreakerDecorator {

	settings := gobreaker.Settings{
		Name:        "",
		MaxRequests: 1,
		Interval:    30 * time.Second,
		Timeout:     15 * time.Second,
		ReadyToTrip: func(counts gobreaker.Counts) bool {
			return true
		},
		OnStateChange: func(name string,
			from gobreaker.State,
			to gobreaker.State) {

			log.Println("state changed", name, from, to)
		},
		IsSuccessful: nil,
	}
	cb := gobreaker.NewCircuitBreaker[internal.TxResult](settings)
	return &CircuitBreakerDecorator{wrapped: wrapped, circuitBreaker: cb}
}

type CircuitBreakerDecorator struct {
	wrapped        internal.PaymentServiceProvider
	circuitBreaker *gobreaker.CircuitBreaker[internal.TxResult]
}

func (c *CircuitBreakerDecorator) RequestPayment(
	amount float64,
	data internal.CustomerData) (internal.TxResult, error) {

	transactionResult, err := c.circuitBreaker.Execute(
		func() (internal.TxResult, error) {

			result, err := c.wrapped.RequestPayment(amount, data)
			return result, err
		})

	return transactionResult, err
}
