package promotion

import (
	"github.com/pingcap/dbaas/billing2/db/entity"
	"github.com/pingcap/dbaas/billing2/forms"
	"github.com/pingcap/dbaas/billing2/utils/log"
	"go.uber.org/zap"
)

// RewardReferralSignup triggers signup reward for the referrer (A)
// when a new user registers with a referral code.
func RewardReferralSignup(referralCode string, tenantID uint) error {
	if referralCode == "" {
		log.Info("promotion: RewardReferralSignup skipped, no referral code",
			zap.Uint("tenantID", tenantID))
		return nil
	}
	log.Info("promotion: RewardReferralSignup called",
		zap.String("referralCode", referralCode),
		zap.Uint("tenantID", tenantID))

	amounts := getRewardAmounts()

	if !referralModel.HasEvent(tenantID, entity.ReferralEventType_Signup) {
		resp, err := referralModel.TriggerReward(&forms.ReferralRewardReq{
			ReferralCode:    referralCode,
			RefereeTenantID: tenantID,
			EventType:       entity.ReferralEventType_Signup,
			CreditsAmount:   amounts.Signup,
		})
		if err != nil {
			log.Error("promotion: RewardReferralSignup referrer reward failed",
				zap.String("referralCode", referralCode),
				zap.Uint("tenantID", tenantID),
				zap.Error(err))
			return err
		}
		log.Info("promotion: RewardReferralSignup referrer reward done",
			zap.String("referralCode", referralCode),
			zap.Uint("tenantID", tenantID),
			zap.Bool("rewarded", resp.Rewarded),
			zap.String("skipReason", resp.SkipReason))
	} else {
		log.Info("promotion: RewardReferralSignup referrer reward skipped, event already exists",
			zap.Uint("tenantID", tenantID))
	}

	log.Info("promotion: RewardReferralSignup done",
		zap.String("referralCode", referralCode),
		zap.Uint("tenantID", tenantID))
	return nil
}

// RewardReferralBindCard triggers bindcard reward for the referrer (A)
// when a referred user binds a credit card.
func RewardReferralBindCard(tenantID uint) error {
	log.Info("promotion: RewardReferralBindCard called",
		zap.Uint("tenantID", tenantID))

	code, err := referralModel.FindReferralCodeBySignupEvent(tenantID)
	if err != nil {
		log.Info("promotion: RewardReferralBindCard skipped, not a referred user",
			zap.Uint("tenantID", tenantID), zap.Error(err))
		return nil
	}

	amounts := getRewardAmounts()

	if !referralModel.HasEvent(tenantID, entity.ReferralEventType_BindCard) {
		resp, err := referralModel.TriggerReward(&forms.ReferralRewardReq{
			ReferralCode:    code,
			RefereeTenantID: tenantID,
			EventType:       entity.ReferralEventType_BindCard,
			CreditsAmount:   amounts.BindCard,
		})
		if err != nil {
			log.Error("promotion: RewardReferralBindCard referrer reward failed",
				zap.Uint("tenantID", tenantID),
				zap.String("referralCode", code),
				zap.Error(err))
			return err
		}
		log.Info("promotion: RewardReferralBindCard referrer reward done",
			zap.Uint("tenantID", tenantID),
			zap.Bool("rewarded", resp.Rewarded),
			zap.String("skipReason", resp.SkipReason))
	} else {
		log.Info("promotion: RewardReferralBindCard referrer reward skipped, event already exists",
			zap.Uint("tenantID", tenantID))
	}

	log.Info("promotion: RewardReferralBindCard done",
		zap.Uint("tenantID", tenantID))
	return nil
}

// RewardReferralContinuousUse triggers referee_continuous_use reward for the referrer (A)
// when a referred user (B) achieves continuous usage.
func RewardReferralContinuousUse(tenantID uint) {
	amounts := getRewardAmounts()
	referralModel.TriggerReferrerContinuousUseReward(tenantID, amounts.RefereeContinuousUse)
}
