package controller

import (
	"fmt"

	"github.com/pingcap/log"
	"github.com/tidbcloud/serverless-service/internal/infra/eventbus"
	"github.com/tidbcloud/serverless-service/internal/infra/eventbus/subscriber"
	"github.com/tidbcloud/tiinf/transport/tieventbus"
	"go.uber.org/zap"
)

type PubSubManager struct {
	eventbus tieventbus.Eventbus
}

func NewPubSubManager() *PubSubManager {
	m := &PubSubManager{}
	err := DiCall(func(service *eventbus.EventbusService) {
		m.eventbus = service.Eventbus
	})
	if err != nil {
		panic(fmt.Sprintf("failed to construct PubSubManager: %s", err))
	}
	return m
}

func (m *PubSubManager) Start() {
	log.Info("starting eventbus", zap.Bool("eventbus", m.eventbus == nil))
	err := DiCall(func(
		spendLimitEventHandler *subscriber.SpendLimitEventHandler,
		clusterEventHandler *subscriber.ClusterEventHandler,
		branchClusterEventHandler *subscriber.BranchClusterEventHandler,
		backupClusterEventHandler *subscriber.BackupClusterEventHandler,
	) {
		subscriber.NewClusterSpendLimitEventSubscriber(m.eventbus).RegisterHandlers(spendLimitEventHandler)
		subscriber.NewClusterEventSubscriber(m.eventbus).RegisterHandlers(clusterEventHandler)
		subscriber.NewBranchClusterEventSubscriber(m.eventbus).RegisterHandlers(branchClusterEventHandler)
		subscriber.NewBackupClusterEventSubscriber(m.eventbus).RegisterHandlers(backupClusterEventHandler)
	})
	if err != nil {
		panic(fmt.Sprintf("failed to start PubSubManager: %s", err))
	}

	err = m.eventbus.Run()
	if err != nil {
		panic(fmt.Sprintf("failed to start eventbus: %s", err))
	}
}

func (m *PubSubManager) StartPublisher() {
	log.Info("starting eventbus publisher", zap.Bool("eventbus", m.eventbus == nil))
	if err := m.eventbus.Run(); err != nil {
		panic(fmt.Sprintf("failed to start eventbus publisher, err=%v", err))
	}
}
