package main

import (
	"context"
	"encoding/json"
	"fmt"
	"testing"
	"time"

	"code.justin.tv/foundation/history-service/internal/awsmocks"
	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/service/ecs"
	"github.com/aws/aws-sdk-go/service/sqs"
	"github.com/stretchr/testify/mock"
	"github.com/stretchr/testify/suite"
)

type GenerateReportHandlerSuite struct {
	mockedSQS *awsmocks.SQSAPI
	mockedECS *awsmocks.ECSAPI

	handler *generateReportHandler
	suite.Suite
}

func (s *GenerateReportHandlerSuite) SetupTest() {

	s.mockedSQS = new(awsmocks.SQSAPI)
	s.mockedECS = new(awsmocks.ECSAPI)
	s.handler = &generateReportHandler{
		queue:       s.mockedSQS,
		ecs:         s.mockedECS,
		queueURL:    "fake-queue-url",
		clusterName: "fake-cluster-name",
		taskDefn:    "fake-task-defn-arn",
		subnets: []*string{
			aws.String("fake-subnet-1"),
			aws.String("fake-subnet-2"),
		},
	}
}

func (s *GenerateReportHandlerSuite) TeardownTest() {
	s.mockedSQS.AssertExpectations(s.T())
	s.mockedECS.AssertExpectations(s.T())
}

func (s *GenerateReportHandlerSuite) TestExecuteStreamEventTypeNotInsert() {
	e := events.DynamoDBEvent{
		Records: []events.DynamoDBEventRecord{
			{
				EventName: string(events.DynamoDBOperationTypeModify),
			},
			{
				EventName: string(events.DynamoDBOperationTypeRemove),
			},
		},
	}

	err := s.handler.execute(context.Background(), e)
	s.Assert().NoError(err)
}

func (s *GenerateReportHandlerSuite) TestExecuteStreamEventTypeInsert() {
	ctx := context.Background()
	s.mockedSQS.On("SendMessageWithContext", ctx, mock.Anything).Run(func(args mock.Arguments) {
		input := args.Get(1).(*sqs.SendMessageInput)
		s.Assert().Contains(aws.StringValue(input.MessageBody), `"user_id":"1234"`)
	}).Return(&sqs.SendMessageOutput{}, nil)

	s.mockedECS.On("RunTaskWithContext", ctx, mock.Anything).Return(&ecs.RunTaskOutput{}, nil).Once()
	err := s.handler.execute(context.Background(), s.buildDDBStreamRecordInsert("1234"))
	s.Assert().NoError(err)
}
func (s *GenerateReportHandlerSuite) buildDDBStreamRecordInsert(userID string) events.DynamoDBEvent {

	davUID := []byte(fmt.Sprintf(`{"S": "%s"}`, userID))
	var avUID events.DynamoDBAttributeValue
	err := json.Unmarshal(davUID, &avUID)

	if err != nil {
		s.Require().NoError(err)
	}

	davTS := []byte(fmt.Sprintf(`{"N": "%d"}`, time.Now().Unix()))
	var avTS events.DynamoDBAttributeValue
	err = json.Unmarshal(davTS, &avTS)

	if err != nil {
		s.Require().NoError(err)
	}

	return events.DynamoDBEvent{
		Records: []events.DynamoDBEventRecord{
			{
				EventName: string(events.DynamoDBOperationTypeInsert),
				Change: events.DynamoDBStreamRecord{
					NewImage: map[string]events.DynamoDBAttributeValue{
						"user_id":   avUID,
						"timestamp": avTS,
					},
				},
			},
		},
	}
}

func TestGenerateReportHandler(t *testing.T) {
	suite.Run(t, new(GenerateReportHandlerSuite))
}
