package model

import (
	"math"
	"math/rand"

	"github.com/denisovdennis/autohero/internal/tuning"
)

// IlvlFactor returns L(ilvl) = 1 + 0.03 * max(0, ilvl - 1) per spec section 6.4.
func IlvlFactor(ilvl int) float64 {
	d := ilvl - 1
	if d < 0 {
		d = 0
	}
	return 1.0 + tuning.Get().IlvlFactorSlope*float64(d)
}

// RarityMultiplier returns M(rarity) per spec section 6.4.2.
func RarityMultiplier(rarity Rarity) float64 {
	switch rarity {
	case RarityCommon:
		return tuning.Get().RarityMultiplierCommon
	case RarityUncommon:
		return tuning.Get().RarityMultiplierUncommon
	case RarityRare:
		return tuning.Get().RarityMultiplierRare
	case RarityEpic:
		return tuning.Get().RarityMultiplierEpic
	case RarityLegendary:
		return tuning.Get().RarityMultiplierLegendary
	default:
		return 1.00
	}
}

// ScalePrimary computes primaryOut = round(basePrimary * L(ilvl) * M(rarity)).
func ScalePrimary(basePrimary int, ilvl int, rarity Rarity) int {
	return int(math.Round(float64(basePrimary) * IlvlFactor(ilvl) * RarityMultiplier(rarity)))
}

// RollIlvl generates an item level from the monster level per spec section 6.4.5.
// Base enemies: delta in {-1, 0, +1} uniform.
// Elite enemies: delta in {0, +1, +2} with weights 0.4/0.4/0.2.
func RollIlvl(monsterLevel int, isElite bool) int {
	var delta int
	if isElite {
		r := rand.Float64()
		cfg := tuning.Get()
		switch {
		case r < cfg.RollIlvlEliteBaseChance:
			delta = 0
		case r < cfg.RollIlvlEliteBaseChance+cfg.RollIlvlElitePlusOneChance:
			delta = 1
		default:
			delta = 2
		}
	} else {
		delta = rand.Intn(3) - 1 // -1, 0, or +1
	}
	ilvl := monsterLevel + delta
	if ilvl < 1 {
		ilvl = 1
	}
	return ilvl
}
