package opworker

import (
	"context"
	"time"

	"github.com/tidbcloud/account/internel/dto"

	"github.com/tidbcloud/account/central/events/publish"

	"github.com/tidbcloud/account/internel/svc/msp"
	"github.com/tidbcloud/account/internel/svc/rbac"

	"github.com/tidbcloud/account/internel/dao/entity"

	"github.com/tidbcloud/account/idl/pbgen/proto/account"
	"go.opentelemetry.io/otel"

	"github.com/tidbcloud/account/central/utils"
	"github.com/tidbcloud/account/commons/config"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"go.uber.org/zap"
)

type MspCustomerConvertWorker struct{ GlobalWorker }

// Run
//
//	@Description: query pending customers,MakeCustomerEffect
//	@Author wangletian 2024-01-16 16:07:04
//	@receiver w
//	@param c
//	@return error
func (w MspCustomerConvertWorker) Run(c context.Context) error {
	ctx, span := otel.Tracer(config.TraceComponentNameWorker).Start(c, "MspCustomerConvertWorker")
	defer span.End()
	bm := utils.Begin(ctx, "MspCustomerConvertWorker")
	defer bm.OnExit(ctx)

	mspSvc, _ := msp.GetMspSvc()

	filter := &account.ListPartnerCustomersReq{
		Status: []string{string(entity.Pending)},
	}
	customers, err := mspSvc.ListCustomers(ctx, filter)
	tilog.Info(ctx, "query pending customers", zap.Any("size", len(customers)))
	if err != nil {
		return err
	}
	for _, customer := range customers {
		//tilog.Info(ctx, "query  customers", zap.Any("customer.ID", customer.ID))
		if customer.EffectedAt.Before(time.Now()) {
			err = mspSvc.MakeCustomerEffect(ctx, customer)
			if err != nil {
				tilog.Error(ctx, "MakeCustomerEffect err", zap.Any("customer", c), zap.Error(err))
				return nil
			}
			err := saveUserServicesAgreements(ctx, customer.CustomerOrgID.Uint64())
			tilog.Info(ctx, "", zap.Any("saveUserServicesAgreements result", err == nil))
			if err := publish.PublishOrgEvent(ctx, dto.OrgEventData{OrgId: customer.CustomerOrgID.Uint64(), OrgEventType: entity.EntityEventTypeUpdate}); err != nil {
				tilog.Error(ctx, "PublishOrgEvent err", zap.Any("TenantID", customer.CustomerOrgID.Uint64()), zap.Error(err))

			}

			if err := publish.PublishOrgEvent(ctx, dto.OrgEventData{OrgId: customer.CustomerOrgID.Uint64(), OrgEventType: entity.EntityEventTypeScheduleActivate}); err != nil {
				tilog.Error(ctx, "PublishOrgEvent err", zap.Any("TenantID", customer.CustomerOrgID.Uint64()), zap.Error(err))

			}

			tilog.Info(ctx, "MspCustomerConvertWorker success", zap.Any("customer", customer))

		}

	}

	return nil
}
func saveUserServicesAgreements(ctx context.Context, customerOrgId uint64) error {
	roleBindingSvc, _ := rbac.GetRbacRoleBindingSvc()

	userIds, err := roleBindingSvc.GetUserIdsInOrgs(ctx, []uint64{customerOrgId})
	if err != nil {
		return err
	}
	tilog.Info(ctx, "query org's  userId", zap.Any("userIds", userIds))
	var mspUserServicesAgreements []entity.MspUserServicesAgreement

	for _, userId := range userIds {
		obj := entity.MspUserServicesAgreement{
			UserID:        entity.ID(userId),
			CustomerOrgID: entity.ID(customerOrgId),
			IsAgree:       false,
			Status:        string(entity.Active),
		}
		mspUserServicesAgreements = append(mspUserServicesAgreements, obj)
	}
	mspSvc, _ := msp.GetMspSvc()
	return mspSvc.BatchCreateMspUserServicesAgreements(ctx, mspUserServicesAgreements)
}
