package user

import (
	"context"
	"errors"
	"fmt"
	"time"

	"bindbox-game/internal/repository/mysql/model"

	"gorm.io/gorm"
)

func (s *service) AddCoupon(ctx context.Context, userID int64, couponID int64) error {
	tpl, err := s.readDB.SystemCoupons.WithContext(ctx).Where(s.readDB.SystemCoupons.ID.Eq(couponID)).First()
	if err != nil {
		return err
	}
	if tpl == nil || tpl.Status != 1 {
		// 模板不存在或未启用
		fmt.Printf("[发券] 模板不可用 coupon_id=%d status=%d\n", couponID, func() int32 {
			if tpl != nil {
				return tpl.Status
			}
			return -1
		}())
		return errors.New("coupon not found or disabled")
	}
	// 配额检查：若 TotalQuantity > 0 则限制发放总量
	if tpl.TotalQuantity > 0 {
		issued, ierr := s.readDB.UserCoupons.WithContext(ctx).Where(s.readDB.UserCoupons.CouponID.Eq(couponID)).Count()
		if ierr != nil {
			return ierr
		}
		if issued >= tpl.TotalQuantity {
			fmt.Printf("[发券] 模板配额已满 coupon_id=%d issued=%d total=%d\n", couponID, issued, tpl.TotalQuantity)
			return gorm.ErrInvalidData
		}
	}
	// 允许用户重复持有相同模板的未使用优惠券
	item := &model.UserCoupons{UserID: userID, CouponID: couponID, Status: 1}
	if !tpl.ValidStart.IsZero() {
		item.ValidStart = tpl.ValidStart
	} else {
		item.ValidStart = time.Now()
	}
	if !tpl.ValidEnd.IsZero() {
		item.ValidEnd = tpl.ValidEnd
	}
	do := s.writeDB.UserCoupons.WithContext(ctx).Omit(s.readDB.UserCoupons.UsedAt, s.readDB.UserCoupons.UsedOrderID)
	if tpl.ValidEnd.IsZero() {
		do = do.Omit(s.writeDB.UserCoupons.ValidEnd)
	}
	if err := do.Create(item); err != nil {
		return err
	}
	// 直减金额券初始化余额（分）；其他类型余额置0
	if tpl.DiscountType == 1 && tpl.DiscountValue > 0 {
		_, _ = s.writeDB.UserCoupons.WithContext(ctx).Where(s.writeDB.UserCoupons.ID.Eq(item.ID)).Updates(map[string]any{"balance_amount": tpl.DiscountValue})
	} else {
		_, _ = s.writeDB.UserCoupons.WithContext(ctx).Where(s.writeDB.UserCoupons.ID.Eq(item.ID)).Updates(map[string]any{"balance_amount": 0})
	}
	return nil
}

func (s *service) VoidUserCoupon(ctx context.Context, adminID int64, userID int64, userCouponID int64) error {
	if userID <= 0 || userCouponID <= 0 {
		return fmt.Errorf("invalid_params")
	}
	uc, err := s.readDB.UserCoupons.WithContext(ctx).
		Where(s.readDB.UserCoupons.ID.Eq(userCouponID)).
		Where(s.readDB.UserCoupons.UserID.Eq(userID)).
		First()
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return fmt.Errorf("not_found")
		}
		return err
	}
	if uc.Status != 1 {
		return fmt.Errorf("invalid_status")
	}
	db := s.repo.GetDbW()
	if uc.BalanceAmount > 0 {
		nb := int64(0)
		if err := db.Exec("UPDATE user_coupons SET status=?, balance_amount=?, updated_at=NOW(3) WHERE id=? AND user_id=? AND status=1", 3, nb, userCouponID, userID).Error; err != nil {
			return err
		}
		ledger := &model.UserCouponLedger{
			UserID:       userID,
			UserCouponID: userCouponID,
			ChangeAmount: -uc.BalanceAmount,
			BalanceAfter: nb,
			OrderID:      0,
			Action:       "void_by_admin",
			CreatedAt:    time.Now(),
		}
		if err := db.Create(ledger).Error; err != nil {
			return err
		}
		return nil
	}
	if err := db.Exec("UPDATE user_coupons SET status=?, updated_at=NOW(3) WHERE id=? AND user_id=? AND status=1", 3, userCouponID, userID).Error; err != nil {
		return err
	}
	_ = adminID
	return nil
}
