package streaming

import (
	"context"

	"github.com/nexuscrm/backend/internal/domain/ports"
	domainEvents "github.com/nexuscrm/shared/pkg/events"
	"github.com/rs/zerolog/log"
)

// WebSocketBroadcaster interface for pushing events to WebSocket clients
type WebSocketBroadcaster interface {
	Broadcast(channel string, data interface{})
}

// EventBridge subscribes to EventBus events and forwards them to registered broadcasters
type EventBridge struct {
	eventBus     ports.EventPublisher
	broadcasters []WebSocketBroadcaster
	unsubFuncs   []func()
}

// NewEventBridge creates a bridge between EventBus and broadcasters
func NewEventBridge(eventBus ports.EventPublisher, broadcasters ...WebSocketBroadcaster) *EventBridge {
	return &EventBridge{
		eventBus:     eventBus,
		broadcasters: broadcasters,
		unsubFuncs:   make([]func(), 0),
	}
}

// Start subscribes to relevant events and bridges them to WebSocket
func (b *EventBridge) Start() {
	// Subscribe to record events
	b.subscribeAndBridge(domainEvents.RecordCreated, "/topic/records/created")
	b.subscribeAndBridge(domainEvents.RecordUpdated, "/topic/records/updated")
	b.subscribeAndBridge(domainEvents.RecordDeleted, "/topic/records/deleted")

	// Subscribe to metadata events
	b.subscribeAndBridge(domainEvents.ObjectCreated, "/topic/metadata/object_created")
	b.subscribeAndBridge(domainEvents.ObjectUpdated, "/topic/metadata/object_updated")
	b.subscribeAndBridge(domainEvents.ObjectDeleted, "/topic/metadata/object_deleted")
	b.subscribeAndBridge(domainEvents.FieldCreated, "/topic/metadata/field_created")
	b.subscribeAndBridge(domainEvents.FieldUpdated, "/topic/metadata/field_updated")
	b.subscribeAndBridge(domainEvents.FieldDeleted, "/topic/metadata/field_deleted")

	// Subscribe to action events
	b.subscribeAndBridge(domainEvents.ActionCreated, "/topic/metadata/action_created")
	b.subscribeAndBridge(domainEvents.ActionUpdated, "/topic/metadata/action_updated")
	b.subscribeAndBridge(domainEvents.ActionDeleted, "/topic/metadata/action_deleted")

	log.Info().Msg("EventBridge started - bridging events to WebSocket")
}

// subscribeAndBridge subscribes to an event type and broadcasts to a channel
func (b *EventBridge) subscribeAndBridge(eventType domainEvents.EventType, wsChannel string) {
	unsub := b.eventBus.Subscribe(eventType, func(ctx context.Context, payload interface{}) error {
		log.Debug().
			Str("event_type", string(eventType)).
			Str("ws_channel", wsChannel).
			Int("broadcasters", len(b.broadcasters)).
			Msg("Bridging event to broadcasters")

		for _, broadcaster := range b.broadcasters {
			broadcaster.Broadcast(wsChannel, payload)
		}
		return nil
	})
	b.unsubFuncs = append(b.unsubFuncs, unsub)
}

// Stop unsubscribes from all events
func (b *EventBridge) Stop() {
	for _, unsub := range b.unsubFuncs {
		unsub()
	}
	b.unsubFuncs = nil
	log.Info().Msg("EventBridge stopped")
}
