package storage

import (
	"code.justin.tv/creator-collab/log/errors"

	"code.justin.tv/live/autohost/internal/logfield"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/dynamodb"
	"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbattribute"
	"github.com/aws/aws-sdk-go/service/dynamodb/expression"
	"golang.org/x/net/context"
)

var autohostListAttribute = "AutohostList"

// GetListFromSettingsTable gets the user's configured autohost list of channels
func (db *storageImpl) GetList(ctx context.Context, userID string) ([]string, error) {
	exp, err := expression.NewBuilder().WithProjection(expression.NamesList(
		expression.Name(autohostListAttribute),
	)).Build()
	if err != nil {
		return nil, errors.Wrap(err, "dynamodb - getting channels on a user's AutoHost list - build expression failed", errors.Fields{
			logfield.HosterChannelID: userID,
		})
	}

	output, err := db.client.GetItemWithContext(ctx, &dynamodb.GetItemInput{
		Key:                      settingsTableKey(userID),
		TableName:                aws.String(db.settingsTableName),
		ProjectionExpression:     exp.Projection(),
		ExpressionAttributeNames: exp.Names(),
	})
	if err != nil {
		return nil, errors.Wrap(err, "dynamodb - getting channels on a user's AutoHost list - GetItem failed", errors.Fields{
			logfield.HosterChannelID: userID,
		})
	}

	var autohostList []string
	err = dynamodbattribute.Unmarshal(output.Item[settingsAttrAutohostList], &autohostList)
	if err != nil {
		return nil, errors.Wrap(err, "dynamodb - getting channels on a user's AutoHost list - unmarshal failed", errors.Fields{
			logfield.HosterChannelID: userID,
		})
	}

	return autohostList, nil
}

// SetListInSettingsTable replaces the current autohost list with a new one
func (db *storageImpl) SetList(ctx context.Context, userID string, channelIDs []string) ([]string, error) {
	// Remove duplicate channel IDs
	duplicateMap := map[string]bool{}
	uniqueChannelIDs := make([]string, 0, len(channelIDs))
	for _, chID := range channelIDs {
		if !duplicateMap[chID] {
			duplicateMap[chID] = true
			uniqueChannelIDs = append(uniqueChannelIDs, chID)
		}
	}

	// Send update request
	setExp := expression.Set(expression.Name(settingsAttrAutohostList), expression.Value(uniqueChannelIDs))
	exp, err := expression.NewBuilder().WithUpdate(setExp).Build()
	if err != nil {
		return nil, errors.Wrap(err, "dynamodb - setting the channels on a user's AutoHost list - build expression failed", errors.Fields{
			logfield.HosterChannelID:      userID,
			logfield.HostTargetChannelIDs: channelIDs,
		})
	}

	output, err := db.client.UpdateItemWithContext(ctx, &dynamodb.UpdateItemInput{
		Key:                       settingsTableKey(userID),
		TableName:                 aws.String(db.settingsTableName),
		UpdateExpression:          exp.Update(),
		ExpressionAttributeNames:  exp.Names(),
		ExpressionAttributeValues: exp.Values(),
		ReturnValues:              aws.String(dynamodb.ReturnValueAllNew),
	})
	if err != nil {
		return nil, errors.Wrap(err, "dynamodb - setting the channels on a user's AutoHost list - UpdateItem failed", errors.Fields{
			logfield.HosterChannelID:      userID,
			logfield.HostTargetChannelIDs: channelIDs,
		})
	}

	var autohostList []string
	err = dynamodbattribute.Unmarshal(output.Attributes[autohostListAttribute], &autohostList)
	if err != nil {
		return nil, errors.Wrap(err, "dynamodb - getting channels on a user's AutoHost list - unmarshal failed", errors.Fields{
			logfield.HosterChannelID: userID,
		})
	}

	return autohostList, nil
}
