package serviceevent

import (
	"context"
	"errors"
	"testing"

	"github.com/stretchr/testify/require"
)

type fakeServiceEventSubscriptionStore struct {
	blockCount    int
	unblockCount  int
	blockReturn   int
	unblockReturn int
	workspaceID   string
	provider      string
	connection    string
	err           error
}

func (store *fakeServiceEventSubscriptionStore) BlockServiceEventSubscriptions(_ context.Context, workspaceID, provider, connectionRef string) (int, error) {
	store.blockCount++
	store.workspaceID = workspaceID
	store.provider = provider
	store.connection = connectionRef
	if store.blockReturn != 0 {
		return store.blockReturn, store.err
	}
	return 3, store.err
}

func (store *fakeServiceEventSubscriptionStore) UnblockServiceEventSubscriptions(_ context.Context, workspaceID, provider, connectionRef string) (int, error) {
	store.unblockCount++
	store.workspaceID = workspaceID
	store.provider = provider
	store.connection = connectionRef
	if store.unblockReturn != 0 {
		return store.unblockReturn, store.err
	}
	return 2, store.err
}

func TestServiceEventSubscriptionServiceNilDependenciesAreNoop(t *testing.T) {
	t.Parallel()

	var service *ServiceEventSubscriptionService
	count, err := service.BlockServiceEventSubscriptions(context.Background(), "wsp", "github", "conn")
	require.NoError(t, err)
	require.Zero(t, count)

	service = NewServiceEventSubscriptionCoordinator(nil)
	count, err = service.UnblockServiceEventSubscriptions(context.Background(), "wsp", "github", "conn")
	require.NoError(t, err)
	require.Zero(t, count)
}

func TestServiceEventSubscriptionServiceTrimsAndDelegatesRuntimeTruth(t *testing.T) {
	t.Parallel()

	canonical := &fakeServiceEventSubscriptionStore{blockReturn: 4, unblockReturn: 5}
	service := NewServiceEventSubscriptionCoordinator(canonical)
	count, err := service.BlockServiceEventSubscriptions(context.Background(), " wsp_1 ", " github ", " conn_1 ")
	require.NoError(t, err)
	require.Equal(t, 4, count)
	require.Equal(t, 1, canonical.blockCount)
	require.Equal(t, "wsp_1", canonical.workspaceID)
	require.Equal(t, "github", canonical.provider)
	require.Equal(t, "conn_1", canonical.connection)

	count, err = service.UnblockServiceEventSubscriptions(context.Background(), " wsp_2 ", " gitea ", " conn_2 ")
	require.NoError(t, err)
	require.Equal(t, 5, count)
	require.Equal(t, 1, canonical.unblockCount)
	require.Equal(t, "wsp_2", canonical.workspaceID)
	require.Equal(t, "gitea", canonical.provider)
	require.Equal(t, "conn_2", canonical.connection)
}

func TestServiceEventSubscriptionServicePropagatesRuntimeErrors(t *testing.T) {
	t.Parallel()

	sentinel := errors.New("store unavailable")
	canonical := &fakeServiceEventSubscriptionStore{err: sentinel, blockReturn: 4}
	service := NewServiceEventSubscriptionCoordinator(canonical)
	count, err := service.BlockServiceEventSubscriptions(context.Background(), "wsp", "github", "conn")
	require.ErrorIs(t, err, sentinel)
	require.Equal(t, 4, count)
	require.Equal(t, 1, canonical.blockCount)
}
