package scheduled

import (
	"github.com/labstack/echo/v4"

	"github.com/pingcap/test-infra/common/model"
	"github.com/pingcap/test-infra/services/tcms/service"
	"github.com/pingcap/test-infra/services/tcms/service/common"
	"github.com/pingcap/test-infra/services/tcms/utils"
)

func NewResourcePoolSyncer(jwtKey []byte, rmsRpcSvc service.RMSRPCService, rmsSvc service.RMSService, resourcePoolSvc service.ResourcePoolService) *resourcePoolSyncer {
	fakeJWTToken := "Bearer " + utils.JWTClaims{
		User: utils.SessionUser{
			ID: 0,
		},
	}.Encode(jwtKey)
	return &resourcePoolSyncer{
		fakeJWTToken:    fakeJWTToken,
		rmsRpcSvc:       rmsRpcSvc,
		rmsSvc:          rmsSvc,
		resourcePoolSvc: resourcePoolSvc,
	}
}

type resourcePoolSyncer struct {
	fakeJWTToken    string
	rmsRpcSvc       service.RMSRPCService
	rmsSvc          service.RMSService
	resourcePoolSvc service.ResourcePoolService
}

func (t *resourcePoolSyncer) Init() {
}

func (t *resourcePoolSyncer) Run() {
	ctx := utils.FakeCtx()
	ctx.Request().Header.Set(echo.HeaderAuthorization, t.fakeJWTToken)

	rmss, err := t.rmsSvc.List(ctx)
	if err != nil {
		ctx.Log().Errorf(err, "resourcePoolSyncer list rms failed")
		return
	}
	for _, rms := range rmss {
		rps, _, err := t.resourcePoolSvc.List(ctx, common.ResourcePoolQueryOpts{
			RmsName: rms.Name,
		})
		if err != nil {
			ctx.Log().Errorf(err, "resourcePoolSyncer query resource pools failed")
			return
		}

		for _, rp := range rps {
			status, serr := t.rmsRpcSvc.GetResourcePoolStatus(rms.Endpoint, rms.Token, rp.Name)
			if serr != nil {
				ctx.Log().Errorf(err, "resourcePoolSyncer request rms failed")
				continue
			}
			rp.TotalResource = status.TotalResource
			rp.NonTestbedOccupiedResource = status.NonTestbedOccupation
			if _, err := t.resourcePoolSvc.UpdateStatus(ctx, []*model.ResourcePool{rp}); err != nil {
				ctx.Log().Errorf(err, "resourcePoolSyncer update resource pool status failed")
				return
			}
		}
	}
}
