package mq

import (
	"fmt"
	"strings"
)

// NormalizeSubscriptionSet validates and canonicalizes a module declaration.
func NormalizeSubscriptionSet(set SubscriptionSet) (SubscriptionSet, error) {
	set.Owner = strings.TrimSpace(set.Owner)
	set.Provider = strings.ToLower(strings.TrimSpace(set.Provider))
	if set.Owner == "" {
		return SubscriptionSet{}, fmt.Errorf("mq subscription owner is empty")
	}
	if set.Provider != ProviderEMQX && set.Provider != ProviderRabbitMQ {
		return SubscriptionSet{}, fmt.Errorf("unsupported mq provider %q", set.Provider)
	}
	if len(set.Topics) == 0 {
		return SubscriptionSet{}, fmt.Errorf("mq subscription topics are empty")
	}
	seen := make(map[string]struct{}, len(set.Topics))
	for index := range set.Topics {
		set.Topics[index].Topic = strings.TrimSpace(set.Topics[index].Topic)
		if set.Topics[index].Topic == "" {
			return SubscriptionSet{}, fmt.Errorf("mq subscription topic at index %d is empty", index)
		}
		if set.Topics[index].QoS > ExactlyOnce {
			return SubscriptionSet{}, fmt.Errorf("invalid mq qos %d for topic %q", set.Topics[index].QoS, set.Topics[index].Topic)
		}
		if set.Topics[index].Handler == nil {
			return SubscriptionSet{}, fmt.Errorf("mq subscription handler is nil for topic %q", set.Topics[index].Topic)
		}
		if _, exists := seen[set.Topics[index].Topic]; exists {
			return SubscriptionSet{}, fmt.Errorf("duplicate mq subscription topic %q", set.Topics[index].Topic)
		}
		seen[set.Topics[index].Topic] = struct{}{}
	}
	return set, nil
}

// ApplySubscriptions activates dependency-bearing module contributors.
func ApplySubscriptions(registrar SubscriptionRegistrar, contributors ...SubscriptionContributor) error {
	if registrar == nil {
		return fmt.Errorf("mq subscription registrar is nil")
	}
	for _, contributor := range contributors {
		if contributor == nil {
			continue
		}
		if err := contributor.RegisterSubscriptions(registrar); err != nil {
			return err
		}
	}
	return nil
}
