package suite

import (
	"context"
	"time"

	"github.com/golang/protobuf/ptypes/timestamp"

	"code.justin.tv/eventbus/schema/pkg/clock"

	"code.justin.tv/eventbus/controlplane/e2e/internal/e2eutil"
	"code.justin.tv/eventbus/controlplane/e2e/internal/report"
	"code.justin.tv/eventbus/controlplane/e2e/internal/test/common"
	"code.justin.tv/eventbus/controlplane/internal/e2eaccounts"
)

var _ Runner = &ClientsTestSuite{}

// ClientsTestSuite ensures two services can be set up, one to publish to an
// event stream and another to subscribe to that event stream. The resulting
// services should be able to publish an event to that stream, and the subscriber
// should be able to use the client to receive the published event.
type ClientsTestSuite struct {
	*DefaultTestSuite // Use the default suite as ground work
}

func NewClientsTestSuite(suiteName string) (Runner, error) {
	// Base setup, testing, and cleaning procedures
	defaultTestSuite, err := NewDefaultTestSuite(suiteName)
	if err != nil {
		return nil, err
	}
	// Wrap the basic tooling with some extra tests
	return &ClientsTestSuite{
		DefaultTestSuite: defaultTestSuite,
	}, nil
}

// Setup is nothing on top of the default setup phase
func (t *ClientsTestSuite) Setup(ctx context.Context) report.Error {
	ctx = e2eutil.AppendTestPath(ctx, t.TestName())
	return t.DefaultTestSuite.Setup(ctx)
}

// Test includes the default testing, plus extra tests to publish
// and receive an event using the client libraries
func (t *ClientsTestSuite) Test(ctx context.Context) {
	ctx = e2eutil.AppendTestPath(ctx, t.TestName())
	t.DefaultTestSuite.Test(ctx)

	// Setup and run common client publisher and subscriber tests
	event := &clock.ClockUpdate{
		Time: &timestamp.Timestamp{
			Seconds: time.Now().Unix(),
		},
	}
	pubTest := &common.ClientPublisherTest{
		TestRunner:  t,
		AWSConfig:   e2eaccounts.AccountCredentials().PublisherConfig(),
		Event:       event,
		Publication: t.Publications[0],
	}
	pubTest.Test(ctx)

	subTest := &common.ClientSubscriberTest{
		TestRunner:   t,
		AWSConfig:    e2eaccounts.AccountCredentials().SubscriberConfig(),
		Event:        event,
		Subscription: t.Subscriptions[0],
	}
	subTest.Test(ctx)
}

func (t *ClientsTestSuite) Clean(ctx context.Context) []report.Error {
	ctx = e2eutil.AppendTestPath(ctx, t.TestName())
	return t.DefaultTestSuite.Clean(ctx)
}

func (t *ClientsTestSuite) TestName() string {
	return "ClientTestSuite"
}
