package workers

import (
	"github.com/pingcap/dbaas/billing2/config"
	"github.com/pingcap/dbaas/billing2/db"
	"github.com/pingcap/dbaas/billing2/db/entity"
	"github.com/pingcap/dbaas/billing2/model/marketing"
	"github.com/pingcap/dbaas/billing2/utils/concurrency"
	"github.com/pingcap/dbaas/billing2/utils/log"
	"github.com/pingcap/dbaas/billing2/utils/timeutils"
	"go.uber.org/zap"
)

var rechargeModel = &marketing.RechargeCreditsModel{}

func RechargeByTenant(tenantID uint) {
	now := timeutils.GetNow()
	err := entity.NewTenantRechargeCreditsPlanQuerySet(db.GetDB()).TenantIDEq(tenantID).ExpiredDateLte(now).ClosedAtIsNull().GetUpdater().SetClosedAt(&now).Update()
	if err != nil {
		log.Error("expired recharge plan failed", zap.Error(err))
	}
	tenantPlans, err := rechargeModel.ListTenantPlansNeedRecharge(tenantID)
	if err != nil {
		log.Error("failed to list tenantPlan need recharge", zap.Error(err), zap.Uint("tenantID", tenantID))
		return
	}
	for _, plan := range tenantPlans {
		if _, e := rechargeModel.TryRecharge(plan.PlanID); e != nil {
			err = e
			log.Error("failed to recharge credits", zap.Error(e), zap.Uint("tenantPlanID", plan.PlanID), zap.Uint("mainPlanID", plan.MainPlanID))
		}
	}
}

func RechargeCreditWorker() (err error) {
	err = concurrency.RunInPoolWithAllTenants(
		config.Get().GetUint(config.DefaultWorkerConcurrency),
		RechargeByTenant,
	)
	return
}

func ExpireCreditRechargePlan() error {
	now := timeutils.GetNow()
	err := entity.NewRechargeCreditsPlanQuerySet(db.GetDB()).ExpiredDateLte(now).GetUpdater().SetClosedAt(&now).Update()
	if err != nil {
		log.Error("expired recharge plan failed", zap.Error(err))
	}
	return err
}
