package wheel

import (
	"fmt"
	"strings"

	"hyapp/pkg/xerr"
	lotteryengine "hyapp/services/activity-service/internal/domain/lotteryengine"
	domain "hyapp/services/activity-service/internal/domain/wheel"
)

const defaultWheelID = "default"

var wheelTierCounts = map[string]int{
	"classic":  8,
	"luxury":   8,
	"advanced": 12,
}

func NormalizeWheelID(wheelID string) string {
	wheelID = strings.TrimSpace(wheelID)
	if wheelID == "" {
		return defaultWheelID
	}
	return wheelID
}

// NormalizeRuleConfig 是转盘配置发布前的唯一收口。
// 这里强制道具/装扮的 RTP 价值为 0，避免后台展示价值、运营估值或资源原价污染真实返奖率。
func NormalizeRuleConfig(config domain.RuleConfig) domain.RuleConfig {
	config.AppCode = strings.TrimSpace(config.AppCode)
	config.WheelID = NormalizeWheelID(config.WheelID)
	normalized := make([]domain.Tier, 0, len(config.Tiers))
	for _, tier := range config.Tiers {
		tier.TierID = strings.TrimSpace(tier.TierID)
		tier.DisplayName = strings.TrimSpace(tier.DisplayName)
		tier.RewardType = lotteryengine.NormalizePrizeKind(tier.RewardType)
		tier.RewardID = strings.TrimSpace(tier.RewardID)
		tier.MetadataJSON = strings.TrimSpace(tier.MetadataJSON)
		if tier.MetadataJSON == "" {
			tier.MetadataJSON = "{}"
		}
		if tier.RewardCount <= 0 {
			tier.RewardCount = 1
		}
		tier.RTPValueCoins = lotteryengine.NormalizeRTPValueCoins(tier.RewardType, tier.RTPValueCoins)
		normalized = append(normalized, tier)
	}
	config.Tiers = normalized
	return config
}

// ValidateRuleConfig 只验证运行所需的硬边界；概率是否满足产品预期由后台配置页负责展示和二次确认。
func ValidateRuleConfig(config domain.RuleConfig) error {
	config = NormalizeRuleConfig(config)
	if config.WheelID == "" {
		return xerr.New(xerr.InvalidArgument, "wheel_id is required")
	}
	if config.DrawPriceCoins <= 0 {
		return xerr.New(xerr.InvalidArgument, "draw_price_coins must be positive")
	}
	if config.TargetRTPPPM < 0 {
		return xerr.New(xerr.InvalidArgument, "target_rtp_ppm must be non-negative")
	}
	if config.PoolRatePPM < 0 {
		return xerr.New(xerr.InvalidArgument, "pool_rate_ppm must be non-negative")
	}
	if config.SettlementWindowDraws <= 0 {
		return xerr.New(xerr.InvalidArgument, "settlement_window_draws must be positive")
	}
	if len(config.Tiers) == 0 {
		return xerr.New(xerr.InvalidArgument, "wheel tiers are required")
	}
	if expectedCount, ok := wheelTierCounts[config.WheelID]; ok && len(config.Tiers) != expectedCount {
		// H5 每个转盘的视觉格子数是固定契约；服务端发布前强校验数量，避免后台或脚本写入多余档位后，
		// 抽奖结果命中一个 H5 没有位置展示的奖品，造成动画、中奖弹窗和实际发奖对不上。
		return xerr.New(xerr.InvalidArgument, fmt.Sprintf("wheel %s requires %d tiers", config.WheelID, expectedCount))
	}
	seen := map[string]bool{}
	var enabled bool
	for _, tier := range config.Tiers {
		if tier.TierID == "" {
			return xerr.New(xerr.InvalidArgument, "wheel tier_id is required")
		}
		if seen[tier.TierID] {
			return xerr.New(xerr.InvalidArgument, fmt.Sprintf("duplicate wheel tier_id: %s", tier.TierID))
		}
		seen[tier.TierID] = true
		if tier.WeightPPM < 0 {
			return xerr.New(xerr.InvalidArgument, fmt.Sprintf("wheel tier %s weight_ppm must be non-negative", tier.TierID))
		}
		switch tier.RewardType {
		case lotteryengine.PrizeKindCoin:
			if tier.RewardCoins < 0 {
				return xerr.New(xerr.InvalidArgument, fmt.Sprintf("wheel tier %s reward_coins must be non-negative", tier.TierID))
			}
		case lotteryengine.PrizeKindGift:
			if tier.RewardID == "" {
				return xerr.New(xerr.InvalidArgument, fmt.Sprintf("wheel tier %s gift reward_id is required", tier.TierID))
			}
		case lotteryengine.PrizeKindProp, lotteryengine.PrizeKindDress:
			if tier.RewardID == "" {
				return xerr.New(xerr.InvalidArgument, fmt.Sprintf("wheel tier %s prop reward_id is required", tier.TierID))
			}
			if tier.RTPValueCoins != 0 {
				return xerr.New(xerr.InvalidArgument, fmt.Sprintf("wheel tier %s prop rtp_value_coins must be zero", tier.TierID))
			}
		default:
			return xerr.New(xerr.InvalidArgument, fmt.Sprintf("unsupported wheel reward_type: %s", tier.RewardType))
		}
		enabled = enabled || tier.Enabled
	}
	if !enabled {
		return xerr.New(xerr.InvalidArgument, "wheel enabled tiers are required")
	}
	return nil
}
