package logic

import (
	"context"
	"fmt"
	"sync"

	"code.justin.tv/creator-collab/log/errors"
	"code.justin.tv/eventbus/schema/pkg/channel_endorsement_list"
	autohosterrors "code.justin.tv/live/autohost/internal/errors"
)

// RemoveList removes channelIDs from a userID's autohost channel targets
func (T *Impl) RemoveList(ctx context.Context, callerID, channelID string, userIDsToRemove []string) ([]string, error) {
	// Check callerID authorization
	authorized, err := T.auth.CanEditChannelSettings(ctx, callerID, channelID)
	if err != nil {
		return nil, err
	}
	if !authorized {
		return nil, autohosterrors.Forbidden
	}

	return T.removeListWithoutAuth(ctx, channelID, userIDsToRemove)
}

// RemoveList removes channelIDs from a userID's autohost channel targets
func (T *Impl) removeListWithoutAuth(ctx context.Context, channelID string, userIDsToRemove []string) ([]string, error) {
	oldList, err := T.db.GetList(ctx, channelID)
	if err != nil {
		return nil, err
	}

	if len(userIDsToRemove) == 0 {
		return oldList, nil
	}

	newList := removeElementsFromList(oldList, userIDsToRemove)
	_, removed := listDiff(newList, oldList)
	newList, err = T.db.SetList(ctx, channelID, newList)
	if err != nil {
		return nil, err
	}

	err = T.cache.SetList(ctx, channelID, newList)
	if err != nil {
		T.logger.Error(err)
	}

	wg := sync.WaitGroup{}
	wg.Add(3)

	go func() {
		defer wg.Done()
		if err = T.eventPublisher.ChannelEndorsementListUpdate(ctx, &channel_endorsement_list.ChannelEndorsementListUpdate{UserId: channelID}); err != nil {
			T.logger.Error(errors.Wrap(err, "could not publish channel endorsement list update event", errors.Fields{"channel_id": channelID}))
		}
	}()

	go func() {
		defer wg.Done()
		err := T.setListSNS.SendToTopic(ctx, setListMessage{
			ChannelID: channelID,
			NewList:   newList,
		})
		if err != nil {
			verboseErr := fmt.Errorf("Error sending event (add autohost list) to sns. Error: %s", err)
			T.logger.Error(verboseErr)
		}
	}()

	go func() {
		defer wg.Done()
		err = T.helpers.DeletedChannel(ctx, channelID, removed)
		if err != nil {
			T.logger.Error(err)
		}
	}()

	wg.Wait()

	return newList, nil
}
