package serverimp

import (
	"strings"

	"github.com/tech/sendico/payments/quotation/internal/appversion"
	"github.com/tech/sendico/pkg/discovery"
	msg "github.com/tech/sendico/pkg/messaging"
	"github.com/tech/sendico/pkg/mservice"
	"go.uber.org/zap"
)

const quotationDiscoverySender = "payment_quotation"

func (i *Imp) initDiscovery(cfg *config) {
	if i == nil || cfg == nil || cfg.Messaging == nil || cfg.Messaging.Driver == "" {
		return
	}

	logger := i.logger.Named("discovery")
	broker, err := msg.CreateMessagingBroker(logger.Named("bus"), cfg.Messaging)
	if err != nil {
		i.logger.Warn("Failed to initialise discovery broker", zap.Error(err))
		return
	}

	registry := discovery.NewRegistry()
	watcher, err := discovery.NewRegistryWatcher(logger, broker, registry)
	if err != nil {
		i.logger.Warn("Failed to initialise discovery registry watcher", zap.Error(err))
		return
	}
	if err := watcher.Start(); err != nil {
		i.logger.Warn("Failed to start discovery registry watcher", zap.Error(err))
		return
	}

	i.discoveryWatcher = watcher
	i.discoveryReg = registry
	i.logger.Info("Discovery registry watcher started")
}

func (i *Imp) startDiscoveryAnnouncer(cfg *config, producer msg.Producer) {
	if i == nil || cfg == nil || producer == nil || cfg.GRPC == nil {
		return
	}

	invokeURI := strings.TrimSpace(cfg.GRPC.DiscoveryInvokeURI())
	if invokeURI == "" {
		i.logger.Warn("Skipping discovery announcement: missing advertise host/port in gRPC config")
		return
	}

	announce := discovery.Announcement{
		Service:    mservice.PaymentQuotation,
		Operations: []string{discovery.OperationPaymentQuote, discovery.OperationPaymentMultiQuote},
		InvokeURI:  invokeURI,
		Version:    appversion.Create().Short(),
	}

	i.discoveryAnnouncer = discovery.NewAnnouncer(i.logger, producer, quotationDiscoverySender, announce)
	i.discoveryAnnouncer.Start()
	i.logger.Info("Discovery announcer started",
		zap.String("service", announce.Service),
		zap.String("invoke_uri", announce.InvokeURI))
}

func (i *Imp) stopDiscoveryAnnouncer() {
	if i == nil || i.discoveryAnnouncer == nil {
		return
	}
	i.discoveryAnnouncer.Stop()
	i.discoveryAnnouncer = nil
}

func (i *Imp) stopDiscovery() {
	if i == nil {
		return
	}
	i.stopDiscoveryAnnouncer()
	if i.discoveryWatcher != nil {
		i.discoveryWatcher.Stop()
		i.discoveryWatcher = nil
	}
	i.discoveryReg = nil
}
