package douyin

import (
	"context"
	"encoding/json"
	"fmt"
	"time"

	"bindbox-game/internal/repository/mysql/model"
	"bindbox-game/internal/service/game"
	"bindbox-game/internal/service/user"
)

// TitleAssigner 称号发放接口（只需要 AssignUserTitle 方法）
type TitleAssigner interface {
	AssignUserTitle(ctx context.Context, userID int64, titleID int64, expiresAt *time.Time, remark string) error
}

// RewardPayload 奖励参数结构
type RewardPayload struct {
	// game_ticket
	GameCode string `json:"game_code,omitempty"`
	// points
	Points int64 `json:"points,omitempty"`
	// coupon
	CouponID int64 `json:"coupon_id,omitempty"`
	// product
	ProductID int64 `json:"product_id,omitempty"`
	// item_card
	CardID int64 `json:"card_id,omitempty"`
	// title
	TitleID int64 `json:"title_id,omitempty"`
}

// RewardDispatcher 奖励发放器
type RewardDispatcher struct {
	ticketSvc game.TicketService
	userSvc   user.Service
	titleSvc  TitleAssigner
}

// NewRewardDispatcher 创建奖励发放器
func NewRewardDispatcher(ticketSvc game.TicketService, userSvc user.Service, titleSvc TitleAssigner) *RewardDispatcher {
	return &RewardDispatcher{
		ticketSvc: ticketSvc,
		userSvc:   userSvc,
		titleSvc:  titleSvc,
	}
}

// GrantReward 根据奖励配置发放奖励
// userID: 用户ID
// reward: 奖励配置
// productCount: 商品数量（会乘以 reward.Quantity）
// source: 来源标识
// sourceID: 来源ID（如订单ID）
func (d *RewardDispatcher) GrantReward(ctx context.Context, userID int64, reward model.DouyinProductRewards, productCount int, source string, sourceID int64) error {
	if reward.Status != 1 {
		return nil // 规则未启用，跳过
	}

	// 解析 payload
	var payload RewardPayload
	if reward.RewardPayload != "" {
		_ = json.Unmarshal([]byte(reward.RewardPayload), &payload)
	}

	totalQuantity := int(reward.Quantity) * productCount
	if totalQuantity <= 0 {
		totalQuantity = productCount
	}
	remark := fmt.Sprintf("购买商品奖励 (规则ID: %d)", reward.ID)

	switch reward.RewardType {
	case "game_ticket":
		// 发放游戏资格
		gameCode := payload.GameCode
		if gameCode == "" {
			gameCode = "minesweeper" // 默认扫雷
		}
		return d.ticketSvc.GrantTicket(ctx, userID, gameCode, totalQuantity, source, sourceID, remark)

	case "points":
		// 发放积分
		points := payload.Points
		if points <= 0 {
			points = 1
		}
		totalPoints := points * int64(totalQuantity)
		return d.userSvc.AddPointsWithAction(ctx, userID, totalPoints, "order_reward", remark, "douyin_product_reward", nil, nil)

	case "coupon":
		// 发放优惠券
		if payload.CouponID <= 0 {
			return fmt.Errorf("coupon_id not configured")
		}
		for i := 0; i < totalQuantity; i++ {
			if err := d.userSvc.AddCoupon(ctx, userID, payload.CouponID); err != nil {
				return err
			}
		}
		return nil

	case "product":
		// 发放商品到用户库存
		if payload.ProductID <= 0 {
			return fmt.Errorf("product_id not configured")
		}
		_, err := d.userSvc.GrantReward(ctx, userID, user.GrantRewardRequest{
			ProductID: payload.ProductID,
			Quantity:  totalQuantity,
			Remark:    remark,
		})
		return err

	case "item_card":
		// 发放道具卡
		if payload.CardID <= 0 {
			return fmt.Errorf("card_id not configured")
		}
		return d.userSvc.AddItemCard(ctx, userID, payload.CardID, totalQuantity)

	case "title":
		// 发放称号（称号不支持数量叠加，只发一次）
		if payload.TitleID <= 0 {
			return fmt.Errorf("title_id not configured")
		}
		return d.titleSvc.AssignUserTitle(ctx, userID, payload.TitleID, nil, remark)

	default:
		return fmt.Errorf("unknown reward type: %s", reward.RewardType)
	}
}

// IsFlipCardReward 判断是否为翻牌游戏奖励（需要特殊处理，不自动发放）
func (d *RewardDispatcher) IsFlipCardReward(reward model.DouyinProductRewards) bool {
	if reward.RewardType != "game_ticket" {
		return false
	}
	var payload RewardPayload
	if reward.RewardPayload != "" {
		_ = json.Unmarshal([]byte(reward.RewardPayload), &payload)
	}
	return payload.GameCode == "flip_card"
}
