package spade

import (
	"fmt"

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

	telemetry "code.justin.tv/amzn/TwitchTelemetry"
	"code.justin.tv/hygienic/spade"
	"code.justin.tv/hygienic/spade/spademetrics/statsdmetrics"
	"code.justin.tv/hygienic/spade/spademetrics/telemetrymetrics"
	"github.com/cactus/go-statsd-client/statsd"
)

type InsertedRecommendationTrackingProperties struct {
	TrackingID   string `json:"tracking_id"`
	RequestID    string `json:"request_id"`
	ItemType     string `json:"item_type"`
	ItemID       string `json:"item_id"`
	ItemPosition int    `json:"item_position"`
	RowPosition  int    `json:"row_position"`
	SourceType   string `json:"source_type"`
}

// Client is an interface wrapper around spade.Client
type Client interface {
	QueueEvent(eventName string, properties interface{})
	QueueEvents(events ...spade.Event)
	QueueInsertedRecommendationEvents(productID string, items ...InsertedRecommendationTrackingProperties)
}

type clientImpl struct {
	spadeClient spade.Client
}

func NewSpadeClient(statsClient statsd.Statter, sampleReporter *telemetry.SampleReporter, logger log.Logger) (Client, error) {
	spadeConfig := &spade.StaticConfig{}

	telemetryReporter := &telemetrymetrics.Reporter{
		SampleReporter: sampleReporter,
	}

	statsdReporter := &statsdmetrics.Reporter{
		Statter:    statsClient,
		SampleRate: 0.1,
	}

	spadeClient := spade.Client{
		Config: spadeConfig,
		Logger: &spadeLogger{logger: logger},
		Reporter: &spade.MultiReporter{
			Reporters: []spade.Reporter{
				telemetryReporter,
				statsdReporter,
			},
		},
	}

	err := spadeClient.Setup()
	if err != nil {
		return nil, errors.Wrap(err, "spade.Setup failed")
	}

	go func() {
		err := spadeClient.Start()
		if err != nil {
			logger.Error(errors.Wrap(err, "error starting spade client"))
		}
	}()

	return &clientImpl{
		spadeClient: spadeClient,
	}, nil
}

func (c *clientImpl) QueueInsertedRecommendationEvents(productID string, items ...InsertedRecommendationTrackingProperties) {
	if len(items) == 0 {
		return
	}

	events := make([]spade.Event, len(items))
	for i, item := range items {
		event := spade.Event{
			Name:       fmt.Sprintf("%s_response_item_server", productID),
			Properties: item,
		}
		events[i] = event
	}

	c.QueueEvents(events...)
}

func (c *clientImpl) QueueEvent(eventName string, properties interface{}) {
	event := spade.Event{
		Name:       eventName,
		Properties: properties,
	}

	c.spadeClient.QueueEvents(event)
}

func (c *clientImpl) QueueEvents(events ...spade.Event) {
	c.spadeClient.QueueEvents(events...)
}
