package model

import (
	"math"
	"testing"

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

func TestIlvlFactor_Geometric(t *testing.T) {
	old := tuning.Get()
	cfg := tuning.DefaultValues()
	cfg.IlvlPerLevelMultiplier = 1.10
	tuning.Set(cfg)
	t.Cleanup(func() { tuning.Set(old) })

	assertNear(t, IlvlFactor(1), 1.0, 1e-9)
	assertNear(t, IlvlFactor(2), 1.10, 1e-9)
	assertNear(t, IlvlFactor(10), math.Pow(1.10, 9), 1e-9)
}

func TestRarityMultiplier_DefaultsAndFallback(t *testing.T) {
	old := tuning.Get()
	cfg := tuning.DefaultValues()
	cfg.RarityMultiplierCommon = 1.00
	cfg.RarityMultiplierUncommon = 1.0877573
	cfg.RarityMultiplierRare = 0
	cfg.RarityMultiplierEpic = 1.2870518
	cfg.RarityMultiplierLegendary = 1.40
	tuning.Set(cfg)
	t.Cleanup(func() { tuning.Set(old) })

	assertNear(t, RarityMultiplier(RarityCommon), 1.00, 1e-9)
	assertNear(t, RarityMultiplier(RarityUncommon), 1.0877573, 1e-9)
	assertNear(t, RarityMultiplier(RarityEpic), 1.2870518, 1e-9)
	assertNear(t, RarityMultiplier(RarityLegendary), 1.40, 1e-9)

	fallbackRare := tuning.DefaultValues().RarityMultiplierRare
	assertNear(t, RarityMultiplier(RarityRare), fallbackRare, 1e-9)
}

func TestScalePrimary_UsesIlvlAndRarity(t *testing.T) {
	old := tuning.Get()
	cfg := tuning.DefaultValues()
	cfg.IlvlPerLevelMultiplier = 1.10
	cfg.RarityMultiplierCommon = 1.00
	cfg.RarityMultiplierLegendary = 1.40
	tuning.Set(cfg)
	t.Cleanup(func() { tuning.Set(old) })

	if got := ScalePrimary(10, 2, RarityCommon); got != 11 {
		t.Fatalf("ScalePrimary common ilvl2 = %d, want 11", got)
	}
	if got := ScalePrimary(10, 1, RarityLegendary); got != 14 {
		t.Fatalf("ScalePrimary legendary ilvl1 = %d, want 14", got)
	}
}

func assertNear(t *testing.T, got float64, want float64, eps float64) {
	t.Helper()
	if math.Abs(got-want) > eps {
		t.Fatalf("got %.12f want %.12f (eps %.1e)", got, want, eps)
	}
}
