package tests

import (
	"context"
	"fmt"
	"testing"

	. "github.com/smartystreets/goconvey/convey"
	"github.com/tidbcloud/pkgv2/pubsub"
	"github.com/tidbcloud/pkgv2/pubsub/mock_pubsub"
	"go.uber.org/mock/gomock"
)

type fakeEvent struct {
	A int
	B string
}

func Test_pubsub(t *testing.T) {
	Convey("Test_pubsub", t, func() {
		ctrl := gomock.NewController(t)
		defer ctrl.Finish()

		mockSub := mock_pubsub.NewMockSubscriber(ctrl)
		ps := pubsub.NewPublisher(mockSub)
		ctx := context.Background()
		ev := &fakeEvent{
			A: 1,
			B: "bbb",
		}
		mockSub.EXPECT().Name().AnyTimes()

		Convey("should call OnEvent when ev is focused by subscriber", func() {
			mockSub.EXPECT().Focused(ctx, ev).Return(true)
			mockSub.EXPECT().OnEvent(ctx, ev)

			err := ps.Publish(ctx, ev)
			So(err, ShouldBeNil)
		})
		Convey("should skip when ev is NOT focused by subscriber", func() {
			mockSub.EXPECT().Focused(ctx, ev).Return(false)

			err := ps.Publish(ctx, ev)
			So(err, ShouldBeNil)
		})
		Convey("should skip when sub1.OnEvent failed", func() {
			mockSub2 := mock_pubsub.NewMockSubscriber(ctrl)
			mockSub2.EXPECT().Name().AnyTimes()
			ps := pubsub.NewPublisher(mockSub, mockSub2)
			mockSub.EXPECT().Focused(ctx, ev).Return(true)
			mockSub.EXPECT().OnEvent(ctx, ev).Return(fmt.Errorf("some error"))
			mockSub2.EXPECT().Focused(ctx, ev).Return(true)
			mockSub2.EXPECT().OnEvent(ctx, ev)

			err := ps.Publish(ctx, ev)
			So(err, ShouldBeNil)
		})
	})
}
