package tariff

import (
	"context"
	"log"
	"sync"

	"go.uber.org/zap"
	"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/errors"
	"penahub.gitlab.yandexcloud.net/pena-services/customer/internal/models"
)

type consumer interface {
	FetchPrivileges(context.Context) []models.Privilege
}

type producer interface {
	Send(ctx context.Context, userID string, tariff *models.Tariff) errors.Error
}

type Deps struct {
	Logger   *zap.Logger
	Consumer consumer
	Producer producer
}

type Service struct {
	logger   *zap.Logger
	consumer consumer
	producer producer
}

func New(deps Deps) *Service {
	if deps.Logger == nil {
		log.Panicln("logger is nil on <NewTariffBrokerService>")
	}

	if deps.Consumer == nil {
		log.Panicln("Consumer is nil on <NewTariffBrokerService>")
	}

	if deps.Producer == nil {
		log.Panicln("Producer is nil on <NewTariffBrokerService>")
	}

	return &Service{
		logger:   deps.Logger,
		consumer: deps.Consumer,
		producer: deps.Producer,
	}
}

func (receiver *Service) Send(ctx context.Context, userID string, tariff *models.Tariff) errors.Error {
	if tariff == nil {
		receiver.logger.Error("tarif is nil on <Send> of <TariffBrokerService>")
		return errors.NewWithMessage("tariff is nil", errors.ErrInvalidArgs)
	}

	if err := receiver.producer.Send(ctx, userID, tariff); err != nil {
		receiver.logger.Error("failed to send tariff on <Send> of <TariffBrokerService>", zap.Error(err))
		return err
	}

	return nil
}

func (receiver *Service) SendMany(ctx context.Context, userID string, tariffs []models.Tariff) []errors.Error {
	sendErrors := make([]errors.Error, 0)
	waitGroup := sync.WaitGroup{}

	for _, tariff := range tariffs {
		waitGroup.Add(1)

		go func(currentTariff models.Tariff) {
			defer waitGroup.Done()

			if err := receiver.Send(ctx, userID, &currentTariff); err != nil {
				sendErrors = append(sendErrors, err)
			}
		}(tariff)
	}

	waitGroup.Wait()

	return sendErrors
}

func (receiver *Service) Read(ctx context.Context) []models.Privilege {
	return receiver.consumer.FetchPrivileges(ctx)
}
