package registry

import (
	"github.com/UpmeshLTD/urus-aio/infrastructure/config/registry/mocks"
	"testing"
	"time"

	"github.com/brianvoe/gofakeit/v6"
	"github.com/spf13/viper"
	"github.com/stretchr/testify/mock"

	. "github.com/onsi/ginkgo/v2"
	. "github.com/onsi/gomega"
)

func TestSuite(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "Registry")
}

var _ = Describe("Registry", func() {
	var (
		name   string
		config = &mocks.Config{}
	)

	BeforeEach(func() {
		name = gofakeit.UUID()
		config = &mocks.Config{}

		config.On("SetDefault", mock.Anything).Return()

		RegisterConfig(name, config)
	})

	Describe("RegisterConfig", func() {
		It("should work with unregistered config", func() {
			RegisterConfig("a-new-config", config)

			// should pass.
		})

		It("should panic with registered config", func() {
			resultChan := make(chan bool)
			didPanic := false

			go func() {
				defer func() {
					if r := recover(); r != nil {
						didPanic = true
						resultChan <- true
					}
				}()

				// Register again, with the same config.
				RegisterConfig(name, &mocks.Config{})
			}()

			<-resultChan

			Expect(didPanic).Should(BeTrue())
		})
	})

	Describe("GetConfig", func() {
		BeforeEach(func() {
			name = gofakeit.UUID()
			RegisterConfig(name, config)
		})

		It("should return nil with unregistered config", func() {
			conf := GetConfig(gofakeit.UUID())
			Expect(conf).Should(BeNil())
		})

		It("should return registered config", func() {
			conf := GetConfig(name)
			Expect(conf).Should(Equal(config))
		})
	})

	Describe("SetDefaultConfigs", func() {
		BeforeEach(func() {
			name = gofakeit.UUID()
			config = &mocks.Config{}
			RegisterConfig(name, config)
		})

		It("should call config SetDefault()", func() {
			resultChan := make(chan bool)

			config.On("SetDefault", mock.Anything).Run(func(args mock.Arguments) {
				resultChan <- true
			}).Return()

			go func() {
				SetDefaultConfigs(&viper.Viper{})
			}()

			time.AfterFunc(time.Second, func() {
				resultChan <- false
			})

			result := <-resultChan
			Expect(result).Should(BeTrue())
		})
	})
})
