package adapter

import (
	"context"
	"fmt"

	"gitea.dwysokinski.me/twhelp/corev3/internal/domain"
	"gitea.dwysokinski.me/twhelp/corev3/internal/watermill/watermillmsg"
	"github.com/ThreeDotsLabs/watermill/message"
)

type EnnoblementWatermillPublisher struct {
	marshaler        watermillmsg.Marshaler
	publisher        message.Publisher
	cmdSyncTopic     string
	eventSyncedTopic string
}

func NewEnnoblementWatermillPublisher(
	publisher message.Publisher,
	marshaler watermillmsg.Marshaler,
	cmdSyncTopic string,
	eventSyncedTopic string,
) *EnnoblementWatermillPublisher {
	return &EnnoblementWatermillPublisher{
		publisher:        publisher,
		marshaler:        marshaler,
		cmdSyncTopic:     cmdSyncTopic,
		eventSyncedTopic: eventSyncedTopic,
	}
}

func (pub *EnnoblementWatermillPublisher) CmdSync(
	ctx context.Context,
	payloads ...domain.SyncEnnoblementsCmdPayload,
) error {
	msgs := make([]*message.Message, 0, len(payloads))

	for _, p := range payloads {
		msg, err := pub.marshaler.Marshal(ctx, watermillmsg.SyncEnnoblementsCmdPayload{
			ServerKey:   p.ServerKey(),
			ServerURL:   p.ServerURL(),
			VersionCode: p.VersionCode(),
		})
		if err != nil {
			return fmt.Errorf("%s: couldn't marshal SyncEnnoblementsCmdPayload: %w", p.ServerKey(), err)
		}

		msgs = append(msgs, msg)
	}

	if err := pub.publisher.Publish(pub.cmdSyncTopic, msgs...); err != nil {
		return fmt.Errorf("couldn't publish messages to topic '%s': %w", pub.cmdSyncTopic, err)
	}

	return nil
}

func (pub *EnnoblementWatermillPublisher) EventSynced(
	ctx context.Context,
	payloads ...domain.EnnoblementsSyncedEventPayload,
) error {
	msgs := make([]*message.Message, 0, len(payloads))

	for _, p := range payloads {
		msg, err := pub.marshaler.Marshal(ctx, watermillmsg.EnnoblementsSyncedEventPayload{
			ServerKey:   p.ServerKey(),
			ServerURL:   p.ServerURL(),
			VersionCode: p.VersionCode(),
		})
		if err != nil {
			return fmt.Errorf("%s: couldn't marshal EnnoblementsSyncedEventPayload: %w", p.ServerKey(), err)
		}

		msgs = append(msgs, msg)
	}

	if err := pub.publisher.Publish(pub.eventSyncedTopic, msgs...); err != nil {
		return fmt.Errorf("couldn't publish message to topic '%s': %w", pub.eventSyncedTopic, err)
	}

	return nil
}
