package suite

import (
	"context"
	"strconv"

	"code.justin.tv/eventbus/controlplane/e2e/internal/httpserver"
	"github.com/twitchtv/twirp"

	"code.justin.tv/eventbus/controlplane/e2e/internal/e2eutil"
	"code.justin.tv/eventbus/controlplane/e2e/internal/expected"
	"code.justin.tv/eventbus/controlplane/rpc"
)

var _ Runner = &IAMRoleDeleteTestSuite{}

type IAMRoleDeleteTestSuite struct {
	*DefaultTestSuite // Use the default suite as ground work
}

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

// Test includes the default testing, plus an extra test to publish
// an event to the stream
func (s *IAMRoleDeleteTestSuite) Test(ctx context.Context) {
	ctx = e2eutil.AppendTestPath(ctx, s.TestName())
	s.DefaultTestSuite.Test(ctx)

	c := rpc.NewServicesProtobufClient(expected.TwirpEndpoint, e2eutil.HTTPClientWithLDAP())

	service, err := httpserver.Service("666")
	if err != nil {
		s.Error(ctx, "error fetching service", err)
		return
	}

	if len(service.GetIamRoles()) != 2 {
		s.Error(ctx, "expected exactly 2 IAM roles, found "+strconv.Itoa(len(service.GetIamRoles())), nil)
		return
	}

	expectedARN := "arn:aws:iam::311539646041:role/e2e-subscriber-role"

	// Delete the IAM role
	_, err = c.DeleteIAMRole(ctx, &rpc.DeleteIAMRoleReq{
		Arn: expectedARN,
	})
	if err != nil {
		s.Error(ctx, "could not delete IAM role", err)
	}

	// Ensure IAM role is gone
	service, err = httpserver.Service("666")
	if err != nil {
		s.Error(ctx, "error fetching service", err)
		return
	}

	if len(service.GetIamRoles()) != 1 {
		s.Error(ctx, "expecting IAM role to be gone", nil)
	}

	// Trying to delete a role that has dangling permissions should fail
	c = rpc.NewServicesProtobufClient(expected.TwirpEndpoint, e2eutil.HTTPClientWithLDAPUserAndGroups("not-authed", []string{"team-e2e-group1"}))
	_, err = c.DeleteIAMRole(ctx, &rpc.DeleteIAMRoleReq{
		Arn: "arn:aws:iam::567312298267:role/e2e-publisher-role",
	})
	if err == nil {
		s.Error(ctx, "expecting an error when removing IAM roles", nil)
		return
	} else if twirpErr, ok := err.(twirp.Error); !ok || twirpErr.Code() != twirp.FailedPrecondition {
		s.Error(ctx, "got wrong error type from IAM role delete", err)
		return
	}

	// Trying to delete a role without authorization will fail
	c = rpc.NewServicesProtobufClient(expected.TwirpEndpoint, e2eutil.HTTPClientWithLDAPUserAndGroups("not-authed", []string{"team-cant-do-anything"}))
	_, err = c.DeleteIAMRole(ctx, &rpc.DeleteIAMRoleReq{
		Arn: "arn:aws:iam::567312298267:role/e2e-publisher-role",
	})
	if err == nil {
		s.Error(ctx, "expecting an error when removing IAM roles", nil)
		return
	} else if twirpErr, ok := err.(twirp.Error); !ok || twirpErr.Code() != twirp.PermissionDenied {
		s.Error(ctx, "got wrong error type from IAM role delete", err)
		return
	}
}

func (s *IAMRoleDeleteTestSuite) TestName() string {
	return "IAMRoleDeleteTestSuite"
}
