package opagg

import (
	"github.com/tech/sendico/payments/storage/model"
	"github.com/tech/sendico/pkg/mlogger"
	"go.uber.org/zap"
)

// Aggregator compacts compatible quote items into recipient-level execution groups.
type Aggregator interface {
	Aggregate(in Input) (*Output, error)
}

// Input contains quote/intents selected for one execution request scope.
type Input struct {
	Items []Item
}

// MergeMode controls whether an item can be compacted with compatible peers.
type MergeMode string

const (
	MergeModeUnspecified MergeMode = ""
	MergeModeByRecipient MergeMode = "merge_by_recipient"
	MergeModeNever       MergeMode = "never_merge"
)

// Item is one quote-intent pair candidate for aggregation.
type Item struct {
	IntentRef      string
	IntentSnapshot model.PaymentIntent
	QuoteSnapshot  *model.PaymentQuoteSnapshot
	MergeMode      MergeMode
	MergeKey       string
	PolicyTag      string
}

// GroupMember preserves one original batch member inside an aggregated group.
type GroupMember struct {
	IntentRef      string
	IntentSnapshot model.PaymentIntent
	QuoteSnapshot  *model.PaymentQuoteSnapshot
}

// Group is one aggregated recipient operation group.
type Group struct {
	RecipientKey   string
	IntentRefs     []string
	IntentSnapshot model.PaymentIntent
	QuoteSnapshot  *model.PaymentQuoteSnapshot
	Members        []GroupMember
}

// Output is the aggregation result.
type Output struct {
	Groups []Group
}

// Dependencies configures operation aggregator integrations.
type Dependencies struct {
	Logger mlogger.Logger
}

func New(deps ...Dependencies) Aggregator {
	var dep Dependencies
	if len(deps) > 0 {
		dep = deps[0]
	}
	logger := dep.Logger
	if logger == nil {
		logger = zap.NewNop()
	}
	return &svc{logger: logger.Named("opagg")}
}
