package prepo

import (
	"context"
	"time"

	"github.com/tech/sendico/payments/orchestrator/internal/service/orchestrationv2/agg"
	"github.com/tech/sendico/pkg/mlogger"
	"go.mongodb.org/mongo-driver/v2/bson"
	"go.mongodb.org/mongo-driver/v2/mongo"
)

// Repository persists orchestration-v2 payment aggregates.
type Repository interface {
	Create(ctx context.Context, payment *agg.Payment) error
	UpdateCAS(ctx context.Context, payment *agg.Payment, expectedVersion uint64) error
	GetByPaymentRef(ctx context.Context, orgRef bson.ObjectID, paymentRef string) (*agg.Payment, error)
	GetByPaymentRefGlobal(ctx context.Context, paymentRef string) (*agg.Payment, error)
	GetByIdempotencyKey(ctx context.Context, orgRef bson.ObjectID, idempotencyKey string) (*agg.Payment, error)
	ListByQuotationRef(ctx context.Context, in ListByQuotationRefInput) (*ListOutput, error)
	ListByState(ctx context.Context, in ListByStateInput) (*ListOutput, error)
	ListByStateGlobal(ctx context.Context, in ListByStateGlobalInput) (*ListOutput, error)
}

// ListCursor is a stable pagination cursor sorted by created_at desc then id desc.
type ListCursor struct {
	CreatedAt time.Time
	ID        bson.ObjectID
}

// ListOutput is a page of payment aggregates.
type ListOutput struct {
	Items      []*agg.Payment
	NextCursor *ListCursor
}

// ListByQuotationRefInput defines listing scope by quotation_ref.
type ListByQuotationRefInput struct {
	OrganizationRef bson.ObjectID
	QuotationRef    string
	Limit           int32
	Cursor          *ListCursor
}

// ListByStateInput defines listing scope by aggregate state.
type ListByStateInput struct {
	OrganizationRef bson.ObjectID
	State           agg.State
	Limit           int32
	Cursor          *ListCursor
}

// ListByStateGlobalInput defines global listing scope by aggregate state.
type ListByStateGlobalInput struct {
	State  agg.State
	Limit  int32
	Cursor *ListCursor
}

// Dependencies configures repository integrations.
type Dependencies struct {
	Logger mlogger.Logger
}

// NewMongo constructs a Mongo-backed payment repository-v2.
func NewMongo(collection *mongo.Collection, deps ...Dependencies) (Repository, error) {
	var dep Dependencies
	if len(deps) > 0 {
		dep = deps[0]
	}
	return newWithStoreLogger(newMongoStore(collection), dep.Logger)
}
