package model

import "time"

// GameState represents the hero's current activity state.
type GameState string

const (
	StateWalking  GameState = "walking"
	StateFighting GameState = "fighting"
	StateDead     GameState = "dead"
	StateResting  GameState = "resting"  // in town, resting
	StateInTown   GameState = "in_town"  // in town, interacting with NPCs
)

// CombatState holds the state of an active combat encounter.
type CombatState struct {
	HeroID          int64     `json:"heroId"`
	Hero            *Hero     `json:"-"` // hero reference, not serialised to avoid circular refs
	Enemy           Enemy     `json:"enemy"`
	HeroNextAttack  time.Time `json:"heroNextAttack"`
	EnemyNextAttack time.Time `json:"enemyNextAttack"`
	StartedAt       time.Time `json:"startedAt"`
	LastTickAt      time.Time `json:"-"` // tracks previous tick for periodic effects
}

// AttackEvent is a min-heap entry for scheduling attacks by next_attack_at.
type AttackEvent struct {
	NextAttackAt time.Time `json:"nextAttackAt"`
	IsHero       bool      `json:"isHero"`  // true = hero attacks, false = enemy attacks
	CombatID     int64     `json:"combatId"` // reference to the combat session
}

// AttackQueue implements container/heap.Interface for scheduling attacks.
type AttackQueue []*AttackEvent

func (q AttackQueue) Len() int            { return len(q) }
func (q AttackQueue) Less(i, j int) bool  { return q[i].NextAttackAt.Before(q[j].NextAttackAt) }
func (q AttackQueue) Swap(i, j int)       { q[i], q[j] = q[j], q[i] }

func (q *AttackQueue) Push(x any) {
	*q = append(*q, x.(*AttackEvent))
}

func (q *AttackQueue) Pop() any {
	old := *q
	n := len(old)
	item := old[n-1]
	old[n-1] = nil // avoid memory leak
	*q = old[:n-1]
	return item
}

// CombatEvent is broadcast over WebSocket to clients observing combat.
type CombatEvent struct {
	Type           string    `json:"type"`                      // "attack", "death", "buff_applied", "debuff_applied", "combat_start", "combat_end"
	HeroID         int64     `json:"heroId"`
	Damage         int       `json:"damage,omitempty"`
	Source         string    `json:"source"`                    // "hero" or "enemy"
	IsCrit         bool      `json:"isCrit,omitempty"`
	DebuffApplied  string    `json:"debuffApplied,omitempty"`  // debuff type applied this event, if any
	HeroHP         int       `json:"heroHp"`
	EnemyHP        int       `json:"enemyHp"`
	Timestamp      time.Time `json:"timestamp"`
}
