package combat

import "time"

// BuffDef defines a buff/debuff type.
type BuffDef struct {
	ID           uint32
	Name         string
	IsDebuff     bool
	DamagePerTick int32 // for DoTs (debuff); heal per tick for HoTs (buff)
	StatModifier  StatMod
}

// StatMod is a temporary stat modification from a buff.
type StatMod struct {
	StrBonus int32
	DexBonus int32
	IntBonus int32
}

// ActiveBuff is an active buff/debuff on an entity.
type ActiveBuff struct {
	Def          *BuffDef
	CasterID     uint64
	Remaining    time.Duration
	TickInterval time.Duration
	NextTick     time.Duration // time until next tick
}

// Tick advances the buff by dt. Returns damage/heal to apply this tick (0 if no tick).
func (b *ActiveBuff) Tick(dt time.Duration) int32 {
	b.Remaining -= dt
	var tickValue int32

	if b.TickInterval > 0 {
		b.NextTick -= dt
		if b.NextTick <= 0 {
			tickValue = b.Def.DamagePerTick
			b.NextTick += b.TickInterval
		}
	}

	return tickValue
}

// IsExpired returns true if the buff has no remaining duration.
func (b *ActiveBuff) IsExpired() bool {
	return b.Remaining <= 0
}

// BuffRegistry holds all buff/debuff definitions.
type BuffRegistry struct {
	buffs map[uint32]*BuffDef
}

// NewBuffRegistry creates a registry with default buffs.
func NewBuffRegistry() *BuffRegistry {
	r := &BuffRegistry{buffs: make(map[uint32]*BuffDef)}
	r.registerDefaults()
	return r
}

// Get returns a buff definition.
func (r *BuffRegistry) Get(id uint32) *BuffDef {
	return r.buffs[id]
}

func (r *BuffRegistry) registerDefaults() {
	// Poison DoT (referenced by skill ID 5, effect Value=1)
	r.buffs[1] = &BuffDef{
		ID:            1,
		Name:          "Poison",
		IsDebuff:      true,
		DamagePerTick: 8,
	}

	// Power Up buff (referenced by skill ID 6, effect Value=2)
	r.buffs[2] = &BuffDef{
		ID:       2,
		Name:     "Power Up",
		IsDebuff: false,
		StatModifier: StatMod{
			StrBonus: 20,
		},
	}
}
