package suite

import (
	"context"
	"errors"

	"code.justin.tv/eventbus/controlplane/e2e/internal/e2eutil"
	"code.justin.tv/eventbus/controlplane/e2e/internal/httpserver"
	"code.justin.tv/eventbus/controlplane/e2e/internal/report"
	"code.justin.tv/eventbus/controlplane/e2e/internal/resource"
)

// Unsubscribing an SQS queue from an SNS topic prevents resubscribing to that topic for 72
// hours, unless the unsubscribe is done from the subscribing account. This test verifies that
// we don't regress the ability to unsubscribe and resubscribe.

var _ Runner = &ResubscribeTestSuite{}

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

func NewResubscribeTestSuite(suiteName string) (Runner, error) {
	defaultTest, err := NewDefaultTestSuite(suiteName)
	if err != nil {
		return nil, err
	}
	return &ResubscribeTestSuite{
		DefaultTestSuite: defaultTest,
	}, nil
}

func (r *ResubscribeTestSuite) Setup(ctx context.Context) report.Error {
	// Standard setup - includes initial queue and subscription
	ctx = e2eutil.AppendTestPath(ctx, r.TestName())
	err := r.DefaultTestSuite.Setup(ctx)
	if err != nil {
		return err
	}

	// Unsubscribe and converge
	for _, s := range r.Subscriptions {
		target, err := httpserver.Target(s.ServiceCatalogID, s.TargetName, e2eutil.JobID(ctx))
		if err != nil {
			return report.ErrorFromContext(ctx, "Could not fetch target for unsubscribing", err)
		}
		err = httpserver.Unsubscribe(target.Id, e2eutil.Suffix(s.EventType, e2eutil.JobID(ctx)), s.Environment)
		if err != nil {
			return report.ErrorFromContext(ctx, "Could not unsubscribe through the API", err)
		}
	}
	r.Log(ctx, "Running controlplane converger")
	convergeErr := e2eutil.Converge()
	if convergeErr != nil {
		return report.ErrorFromContext(ctx, "Failure running converger for unsubscribing", convergeErr)
	}

	// Verify unsubscribed
	for _, s := range r.Subscriptions {
		_, err := s.AWSSubscription(ctx)
		if err == nil {
			return report.ErrorFromContext(ctx, "Subscription should be deleted", errors.New("subscription should not exist"))
		}
		if err != resource.ErrSubscriptionNotFound {
			return report.ErrorFromContext(ctx, "Unknown status for deleted subscription", err)
		}
	}

	// We re-invoke setup in order to re-create the deleted subscription. This should not cause any other infrastructure operations.
	for _, s := range r.Subscriptions {
		err = s.Setup(ctx)
		if err != nil {
			return err
		}
	}
	r.Log(ctx, "Running controlplane converger")
	convergeErr = e2eutil.Converge()
	if convergeErr != nil {
		report.ErrorFromContext(ctx, "Failure running converger for resubscribing", convergeErr)
	}

	return nil
}

func (r *ResubscribeTestSuite) TestName() string {
	return "ResubscribeTestSuite"
}
