package quote_computation_service

import (
	"context"
	"time"

	"github.com/tech/sendico/payments/quotation/internal/service/plan"
	"github.com/tech/sendico/payments/quotation/internal/service/quotation/gateway_funding_profile"
	"github.com/tech/sendico/payments/quotation/internal/service/quotation/graph_path_finder"
	"github.com/tech/sendico/pkg/mlogger"
	"go.uber.org/zap"
)

type Core interface {
	BuildQuote(ctx context.Context, in BuildQuoteInput) (*ComputedQuote, time.Time, error)
}

type ManagedWalletNetworkResolver interface {
	ResolveManagedWalletNetwork(ctx context.Context, managedWalletRef string) (string, error)
}

type LedgerAccountCurrencyResolver interface {
	ResolveLedgerAccountCurrency(ctx context.Context, organizationRef, ledgerAccountRef string) (string, error)
}

type Option func(*QuoteComputationService)

type QuoteComputationService struct {
	core                          Core
	fundingResolver               gateway_funding_profile.FundingProfileResolver
	gatewayRegistry               plan.GatewayRegistry
	managedWalletNetworkResolver  ManagedWalletNetworkResolver
	ledgerAccountCurrencyResolver LedgerAccountCurrencyResolver
	routeStore                    plan.RouteStore
	pathFinder                    *graph_path_finder.GraphPathFinder
	logger                        mlogger.Logger
}

func New(core Core, opts ...Option) *QuoteComputationService {
	svc := &QuoteComputationService{
		core:       core,
		pathFinder: graph_path_finder.New(),
		logger:     zap.NewNop(),
	}
	for _, opt := range opts {
		if opt != nil {
			opt(svc)
		}
	}
	return svc
}

func WithFundingProfileResolver(resolver gateway_funding_profile.FundingProfileResolver) Option {
	return func(svc *QuoteComputationService) {
		if svc != nil {
			svc.fundingResolver = resolver
		}
	}
}

func WithGatewayRegistry(registry plan.GatewayRegistry) Option {
	return func(svc *QuoteComputationService) {
		if svc != nil {
			svc.gatewayRegistry = registry
		}
	}
}

func WithManagedWalletNetworkResolver(resolver ManagedWalletNetworkResolver) Option {
	return func(svc *QuoteComputationService) {
		if svc != nil {
			svc.managedWalletNetworkResolver = resolver
		}
	}
}

func WithLedgerAccountCurrencyResolver(resolver LedgerAccountCurrencyResolver) Option {
	return func(svc *QuoteComputationService) {
		if svc != nil {
			svc.ledgerAccountCurrencyResolver = resolver
		}
	}
}

func WithRouteStore(store plan.RouteStore) Option {
	return func(svc *QuoteComputationService) {
		if svc != nil {
			svc.routeStore = store
		}
	}
}

func WithPathFinder(pathFinder *graph_path_finder.GraphPathFinder) Option {
	return func(svc *QuoteComputationService) {
		if svc != nil && pathFinder != nil {
			svc.pathFinder = pathFinder
		}
	}
}

func WithLogger(logger mlogger.Logger) Option {
	return func(svc *QuoteComputationService) {
		if svc != nil && logger != nil {
			svc.logger = logger.Named("computation")
		}
	}
}
