package monsters

import (
	"fmt"

	"dk/internal/database"
)

// Monster represents a monster in the game
type Monster struct {
	ID      int
	Name    string
	MaxHP   int
	MaxDmg  int
	Armor   int
	Level   int
	MaxExp  int
	MaxGold int
	Immune  int
}

// Immunity constants
const (
	ImmuneNone  = 0
	ImmuneHurt  = 1
	ImmuneSleep = 2
)

// New creates a new Monster with sensible defaults
func New() *Monster {
	return &Monster{
		Name:    "",
		MaxHP:   10,
		MaxDmg:  5,
		Armor:   0,
		Level:   1,
		MaxExp:  10,
		MaxGold: 5,
		Immune:  ImmuneNone,
	}
}

// Validate checks if monster has valid values
func (m *Monster) Validate() error {
	if m.Name == "" {
		return fmt.Errorf("monster name cannot be empty")
	}
	if m.MaxHP < 1 {
		return fmt.Errorf("monster MaxHP must be at least 1")
	}
	if m.Level < 1 {
		return fmt.Errorf("monster Level must be at least 1")
	}
	if m.Immune < ImmuneNone || m.Immune > ImmuneSleep {
		return fmt.Errorf("invalid immunity type: %d", m.Immune)
	}
	return nil
}

// CRUD operations
func (m *Monster) Delete() error {
	return database.Exec("DELETE FROM monsters WHERE id = %d", m.ID)
}

func (m *Monster) Insert() error {
	id, err := database.Insert("monsters", m, "ID")
	if err != nil {
		return err
	}
	m.ID = int(id)
	return nil
}

// Query functions
func Find(id int) (*Monster, error) {
	var monster Monster
	err := database.Get(&monster, "SELECT * FROM monsters WHERE id = %d", id)
	if err != nil {
		return nil, fmt.Errorf("monster with ID %d not found", id)
	}
	return &monster, nil
}

func All() ([]*Monster, error) {
	var monsters []*Monster
	err := database.Select(&monsters, "SELECT * FROM monsters ORDER BY level ASC, id ASC")
	return monsters, err
}

func ByLevel(level int) ([]*Monster, error) {
	var monsters []*Monster
	err := database.Select(&monsters, "SELECT * FROM monsters WHERE level = %d ORDER BY id ASC", level)
	return monsters, err
}

func ByLevelRange(minLevel, maxLevel int) ([]*Monster, error) {
	var monsters []*Monster
	err := database.Select(&monsters, "SELECT * FROM monsters WHERE level >= %d AND level <= %d ORDER BY level ASC, id ASC", minLevel, maxLevel)
	return monsters, err
}

func ByImmunity(immunityType int) ([]*Monster, error) {
	var monsters []*Monster
	err := database.Select(&monsters, "SELECT * FROM monsters WHERE immune = %d ORDER BY level ASC, id ASC", immunityType)
	return monsters, err
}

// Helper methods
func (m *Monster) IsHurtImmune() bool {
	return m.Immune == ImmuneHurt
}

func (m *Monster) IsSleepImmune() bool {
	return m.Immune == ImmuneSleep
}

func (m *Monster) HasImmunity() bool {
	return m.Immune != ImmuneNone
}

func (m *Monster) ImmunityName() string {
	switch m.Immune {
	case ImmuneNone:
		return "None"
	case ImmuneHurt:
		return "Hurt Spells"
	case ImmuneSleep:
		return "Sleep Spells"
	default:
		return "Unknown"
	}
}

func (m *Monster) DifficultyRating() float64 {
	if m.Level == 0 {
		return 0
	}
	return float64(m.MaxHP+m.MaxDmg+m.Armor) / float64(m.Level)
}

func (m *Monster) ExpPerHP() float64 {
	if m.MaxHP == 0 {
		return 0
	}
	return float64(m.MaxExp) / float64(m.MaxHP)
}

func (m *Monster) GoldPerHP() float64 {
	if m.MaxHP == 0 {
		return 0
	}
	return float64(m.MaxGold) / float64(m.MaxHP)
}
