package gateway

import (
	"context"

	gatewayoutbox "github.com/tech/sendico/gateway/common/outbox"
	"github.com/tech/sendico/pkg/db/transaction"
	me "github.com/tech/sendico/pkg/messaging/envelope"
)

type tgOutboxProvider interface {
	Outbox() gatewayoutbox.Store
}

type tgTransactionProvider interface {
	TransactionFactory() transaction.Factory
}

func (s *Service) outboxStore() gatewayoutbox.Store {
	provider, ok := s.repo.(tgOutboxProvider)
	if !ok || provider == nil {
		return nil
	}
	return provider.Outbox()
}

func (s *Service) startOutboxReliableProducer(_ context.Context) error {
	if s == nil || s.repo == nil {
		return nil
	}
	return s.outbox.Start(s.logger, s.producer, s.outboxStore(), s.msgCfg) //nolint:contextcheck // Reliable runtime start API does not accept context.
}

func (s *Service) sendWithOutbox(ctx context.Context, env me.Envelope) error {
	if err := s.startOutboxReliableProducer(ctx); err != nil {
		return err
	}
	return s.outbox.Send(ctx, env)
}

func (s *Service) executeTransaction(ctx context.Context, cb transaction.Callback) (any, error) {
	provider, ok := s.repo.(tgTransactionProvider)
	if !ok || provider == nil || provider.TransactionFactory() == nil {
		return cb(ctx)
	}
	return provider.TransactionFactory().CreateTransaction().Execute(ctx, cb)
}
