package cluster_svc

import (
	"context"
	"testing"

	. "github.com/smartystreets/goconvey/convey"
	"github.com/tidbcloud/pkgv2/bizerr"
	"github.com/tidbcloud/serverless-service/internal/config"
	"github.com/tidbcloud/serverless-service/internal/domain/entity"
	"github.com/tidbcloud/serverless-service/internal/domain/facade"
	"github.com/tidbcloud/serverless-service/internal/domain/facade/mock_facade"
	"github.com/tidbcloud/serverless-service/internal/domain/repo/mock_repo"
	"go.uber.org/mock/gomock"
)

func Test_DowntimeService_Execute(t *testing.T) {
	ctx := context.Background()
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()
	o11yFacade := mock_facade.NewMockO11yFacade(ctrl)
	downtimeRepo := mock_repo.NewMockDowntimeRepo(ctrl)
	svc := NewDowntimeService(o11yFacade, downtimeRepo)

	res := map[string]facade.DowntimeRes{
		"1001:1136185446:vip":  {DownRate: 0.1, Connections: 100},
		"1001:1136185446:free": {DownRate: 0.2, Connections: 200},
	}

	Convey("Test_Execute", t, func() {
		Convey("test w/o regional config", func() {
			So(svc.Execute(ctx), ShouldBeNil)
		})

		Convey("test w/ regional config", func() {
			config.Global().WorkerConfig.RegionalConfig = []config.RegionalConfig{
				{Region: "region1", K8sConfig: []config.K8sConfig{{Kubernetes: "k1", O11yUrl: "url1"}}},
				{Region: "region2", K8sConfig: []config.K8sConfig{{Kubernetes: "k2", O11yUrl: "url2"}}},
			}

			Convey("if one region failed", func() {
				e := bizerr.New(bizerr.ErrCodeUnknown, "failed")
				o11yFacade.EXPECT().GetDowntimes(gomock.Any(), "url1").Return(nil, e)
				o11yFacade.EXPECT().GetDowntimes(gomock.Any(), "url2").Return(res, nil)
				downtimeRepo.EXPECT().MultiSave(gomock.Any(), gomock.Any()).DoAndReturn(
					func(ctx context.Context, records []*entity.Downtime) bizerr.BizError {
						So(records, ShouldHaveLength, 2)
						return nil
					},
				)
				So(svc.Execute(ctx), ShouldBeNil)
			})

			Convey("should succeed", func() {
				o11yFacade.EXPECT().GetDowntimes(gomock.Any(), "url1").Return(res, nil)
				o11yFacade.EXPECT().GetDowntimes(gomock.Any(), "url2").Return(res, nil)
				downtimeRepo.EXPECT().MultiSave(gomock.Any(), gomock.Any()).DoAndReturn(
					func(ctx context.Context, records []*entity.Downtime) bizerr.BizError {
						So(records, ShouldHaveLength, 4)
						return nil
					},
				)
				So(svc.Execute(ctx), ShouldBeNil)
			})
		})
	})
}
