package model import ( "testing" "time" "github.com/denisovdennis/autohero/internal/tuning" ) func TestApplyBuffQuotaRollover_RefillsWhenWindowPassed(t *testing.T) { end := time.Date(2026, 3, 1, 12, 0, 0, 0, time.UTC) h := &Hero{ BuffFreeChargesRemaining: 0, BuffQuotaPeriodEnd: &end, } now := end.Add(time.Hour) if !h.ApplyBuffQuotaRollover(now) { t.Fatal("expected rollover to mutate hero") } want := int(tuning.DefaultValues().FreeBuffActivationsPerPeriod) if h.BuffFreeChargesRemaining != want { t.Fatalf("charges: want %d, got %d", want, h.BuffFreeChargesRemaining) } if !h.BuffQuotaPeriodEnd.After(end) { t.Fatalf("expected period end to advance, got %v", h.BuffQuotaPeriodEnd) } } func TestApplyBuffQuotaRollover_NoOpWhenSubscribed(t *testing.T) { end := time.Date(2026, 3, 1, 12, 0, 0, 0, time.UTC) h := &Hero{ SubscriptionActive: true, BuffFreeChargesRemaining: 0, BuffQuotaPeriodEnd: &end, } if h.ApplyBuffQuotaRollover(end.Add(48 * time.Hour)) { t.Fatal("subscription should skip rollover") } } func TestResetBuffCharges_SubscriberGetsSubscriberCap(t *testing.T) { now := time.Date(2026, 3, 15, 12, 0, 0, 0, time.UTC) bt := BuffRush h := &Hero{ SubscriptionActive: true, BuffCharges: map[string]BuffChargeState{ string(bt): {Remaining: 0, PeriodEnd: nil}, }, } h.ResetBuffCharges(&bt, now) st := h.BuffCharges[string(bt)] if st.Remaining != BuffSubscriberChargesPerType[bt] { t.Fatalf("subscriber refill: want remaining %d, got %d", BuffSubscriberChargesPerType[bt], st.Remaining) } }