//go:generate ${GOBIN}/mockgen -destination provider_mock.go -package=transaction ${GO_MODULE}/infra/database/transaction Provider
package transaction

import (
	"context"

	"gorm.io/gorm"
)

// ProviderOption configures a Provider created by NewProvider.
type ProviderOption func(*providerImp)

// WithNestedTransaction controls whether Transaction starts a nested
// transaction when the context already carries an active transaction.
//
// When disabled, nested Transaction calls reuse the current transaction and
// execute the callback directly. When enabled, nested Transaction calls use
// GORM's nested transaction support.
func WithNestedTransaction() ProviderOption {
	return func(p *providerImp) {
		p.enableNestedTransaction = true
	}
}

// Provider provides a context-aware DB handle and transaction management.
type Provider interface {
	// DB returns a GORM DB bound to ctx.
	//
	// If ctx carries an active transaction created by Transaction, DB returns
	// the transactional DB handle. Otherwise, it returns the base DB handle with
	// ctx attached.
	DB(ctx context.Context) *gorm.DB

	// Transaction executes cb in a database transaction.
	//
	// The callback receives a derived context carrying the transactional DB
	// handle, so repository code should call DB with that callback context.
	// Returning an error from cb rolls the transaction back; returning nil
	// commits it.
	Transaction(ctx context.Context, cb func(ctx context.Context) error) error
}
