package player

import (
	"eq2emu/internal/entity"
	"eq2emu/internal/quests"
	"eq2emu/internal/skills"
	"eq2emu/internal/spells"
)

// PlayerAware interface for components that need to interact with players
type PlayerAware interface {
	// SetPlayer sets the player reference
	SetPlayer(player *Player)

	// GetPlayer returns the player reference
	GetPlayer() *Player
}

// PlayerManager interface for managing multiple players
type PlayerManager interface {
	// AddPlayer adds a player to management
	AddPlayer(player *Player) error

	// RemovePlayer removes a player from management
	RemovePlayer(playerID int32) error

	// GetPlayer returns a player by ID
	GetPlayer(playerID int32) *Player

	// GetPlayerByName returns a player by name
	GetPlayerByName(name string) *Player

	// GetPlayerByCharacterID returns a player by character ID
	GetPlayerByCharacterID(characterID int32) *Player

	// GetAllPlayers returns all managed players
	GetAllPlayers() []*Player

	// GetPlayersInZone returns all players in a zone
	GetPlayersInZone(zoneID int32) []*Player

	// SendToAll sends a message to all players
	SendToAll(message interface{}) error

	// SendToZone sends a message to all players in a zone
	SendToZone(zoneID int32, message interface{}) error
}

// PlayerDatabase interface for database operations
type PlayerDatabase interface {
	// LoadPlayer loads a player from the database
	LoadPlayer(characterID int32) (*Player, error)

	// SavePlayer saves a player to the database
	SavePlayer(player *Player) error

	// DeletePlayer deletes a player from the database
	DeletePlayer(characterID int32) error

	// LoadPlayerQuests loads player quests
	LoadPlayerQuests(characterID int32) ([]*quests.Quest, error)

	// SavePlayerQuests saves player quests
	SavePlayerQuests(characterID int32, quests []*quests.Quest) error

	// LoadPlayerSkills loads player skills
	LoadPlayerSkills(characterID int32) ([]*skills.Skill, error)

	// SavePlayerSkills saves player skills
	SavePlayerSkills(characterID int32, skills []*skills.Skill) error

	// LoadPlayerSpells loads player spells
	LoadPlayerSpells(characterID int32) ([]*SpellBookEntry, error)

	// SavePlayerSpells saves player spells
	SavePlayerSpells(characterID int32, spells []*SpellBookEntry) error

	// LoadPlayerHistory loads player history
	LoadPlayerHistory(characterID int32) (map[int8]map[int8][]*HistoryData, error)

	// SavePlayerHistory saves player history
	SavePlayerHistory(characterID int32, history map[int8]map[int8][]*HistoryData) error
}

// PlayerPacketHandler interface for handling player packets
type PlayerPacketHandler interface {
	// HandlePacket handles a packet from a player
	HandlePacket(player *Player, packet interface{}) error

	// SendPacket sends a packet to a player
	SendPacket(player *Player, packet interface{}) error

	// BroadcastPacket broadcasts a packet to multiple players
	BroadcastPacket(players []*Player, packet interface{}) error
}

// PlayerEventHandler interface for player events
type PlayerEventHandler interface {
	// OnPlayerLogin called when player logs in
	OnPlayerLogin(player *Player) error

	// OnPlayerLogout called when player logs out
	OnPlayerLogout(player *Player) error

	// OnPlayerDeath called when player dies
	OnPlayerDeath(player *Player, killer entity.Entity) error

	// OnPlayerResurrect called when player resurrects
	OnPlayerResurrect(player *Player) error

	// OnPlayerLevelUp called when player levels up
	OnPlayerLevelUp(player *Player, newLevel int8) error

	// OnPlayerZoneChange called when player changes zones
	OnPlayerZoneChange(player *Player, fromZoneID, toZoneID int32) error

	// OnPlayerQuestComplete called when player completes a quest
	OnPlayerQuestComplete(player *Player, quest *quests.Quest) error

	// OnPlayerSpellCast called when player casts a spell
	OnPlayerSpellCast(player *Player, spell *spells.Spell, target entity.Entity) error
}

// PlayerValidator interface for validating player operations
type PlayerValidator interface {
	// ValidateLogin validates player login
	ValidateLogin(player *Player) error

	// ValidateMovement validates player movement
	ValidateMovement(player *Player, x, y, z, heading float32) error

	// ValidateSpellCast validates spell casting
	ValidateSpellCast(player *Player, spell *spells.Spell, target entity.Entity) error

	// ValidateItemUse validates item usage
	ValidateItemUse(player *Player, item *Item) error

	// ValidateQuestAcceptance validates quest acceptance
	ValidateQuestAcceptance(player *Player, quest *quests.Quest) error

	// ValidateSkillUse validates skill usage
	ValidateSkillUse(player *Player, skill *skills.Skill) error
}

// PlayerSerializer interface for serializing player data
type PlayerSerializer interface {
	// SerializePlayer serializes a player for network transmission
	SerializePlayer(player *Player, version int16) ([]byte, error)

	// SerializePlayerInfo serializes player info for character sheet
	SerializePlayerInfo(player *Player, version int16) ([]byte, error)

	// SerializePlayerSpells serializes player spells
	SerializePlayerSpells(player *Player, version int16) ([]byte, error)

	// SerializePlayerQuests serializes player quests
	SerializePlayerQuests(player *Player, version int16) ([]byte, error)

	// SerializePlayerSkills serializes player skills
	SerializePlayerSkills(player *Player, version int16) ([]byte, error)
}

// PlayerStatistics interface for player statistics tracking
type PlayerStatistics interface {
	// RecordPlayerLogin records a player login
	RecordPlayerLogin(player *Player)

	// RecordPlayerLogout records a player logout
	RecordPlayerLogout(player *Player)

	// RecordPlayerDeath records a player death
	RecordPlayerDeath(player *Player, killer entity.Entity)

	// RecordPlayerKill records a player kill
	RecordPlayerKill(player *Player, victim entity.Entity)

	// RecordQuestComplete records a quest completion
	RecordQuestComplete(player *Player, quest *quests.Quest)

	// RecordSpellCast records a spell cast
	RecordSpellCast(player *Player, spell *spells.Spell)

	// GetStatistics returns player statistics
	GetStatistics(playerID int32) map[string]interface{}
}

// PlayerNotifier interface for player notifications
type PlayerNotifier interface {
	// NotifyLevelUp sends level up notification
	NotifyLevelUp(player *Player, newLevel int8) error

	// NotifyQuestComplete sends quest completion notification
	NotifyQuestComplete(player *Player, quest *quests.Quest) error

	// NotifySkillUp sends skill up notification
	NotifySkillUp(player *Player, skill *skills.Skill, newValue int16) error

	// NotifyDeathPenalty sends death penalty notification
	NotifyDeathPenalty(player *Player, debtAmount float32) error

	// NotifyMessage sends a general message
	NotifyMessage(player *Player, message string, messageType int8) error
}

// PlayerAdapter adapts player functionality for other systems
type PlayerAdapter struct {
	player *Player
}

// NewPlayerAdapter creates a new player adapter
func NewPlayerAdapter(player *Player) *PlayerAdapter {
	return &PlayerAdapter{player: player}
}

// GetPlayer returns the wrapped player
func (pa *PlayerAdapter) GetPlayer() *Player {
	return pa.player
}

// GetEntity returns the player as an entity
func (pa *PlayerAdapter) GetEntity() *entity.Entity {
	return &pa.player.Entity
}

// GetSpawn returns the player as a spawn
func (pa *PlayerAdapter) GetSpawn() *entity.Spawn {
	return &pa.player.Entity.Spawn
}

// IsPlayer always returns true for player adapter
func (pa *PlayerAdapter) IsPlayer() bool {
	return true
}

// GetCharacterID returns the character ID
func (pa *PlayerAdapter) GetCharacterID() int32 {
	return pa.player.GetCharacterID()
}

// GetName returns the player name
func (pa *PlayerAdapter) GetName() string {
	return pa.player.GetName()
}

// GetLevel returns the player level
func (pa *PlayerAdapter) GetLevel() int8 {
	return pa.player.GetLevel()
}

// GetClass returns the player class
func (pa *PlayerAdapter) GetClass() int8 {
	return pa.player.GetClass()
}

// GetRace returns the player race
func (pa *PlayerAdapter) GetRace() int8 {
	return pa.player.GetRace()
}

// GetZoneID returns the current zone ID
func (pa *PlayerAdapter) GetZoneID() int32 {
	return pa.player.GetZone()
}

// GetHP returns current HP
func (pa *PlayerAdapter) GetHP() int32 {
	return pa.player.GetHP()
}

// GetMaxHP returns maximum HP
func (pa *PlayerAdapter) GetMaxHP() int32 {
	return pa.player.GetTotalHP()
}

// GetPower returns current power
func (pa *PlayerAdapter) GetPower() int32 {
	return pa.player.GetPower()
}

// GetMaxPower returns maximum power
func (pa *PlayerAdapter) GetMaxPower() int32 {
	return pa.player.GetTotalPower()
}

// GetX returns X coordinate
func (pa *PlayerAdapter) GetX() float32 {
	return pa.player.GetX()
}

// GetY returns Y coordinate
func (pa *PlayerAdapter) GetY() float32 {
	return pa.player.GetY()
}

// GetZ returns Z coordinate
func (pa *PlayerAdapter) GetZ() float32 {
	return pa.player.GetZ()
}

// GetHeading returns heading
func (pa *PlayerAdapter) GetHeading() float32 {
	return pa.player.GetHeading()
}

// IsDead returns whether the player is dead
func (pa *PlayerAdapter) IsDead() bool {
	return pa.player.IsDead()
}

// IsAlive returns whether the player is alive
func (pa *PlayerAdapter) IsAlive() bool {
	return !pa.player.IsDead()
}

// IsInCombat returns whether the player is in combat
func (pa *PlayerAdapter) IsInCombat() bool {
	return pa.player.GetInfoStruct().GetEngageCommands() != 0
}

// GetDistance returns distance to another spawn
func (pa *PlayerAdapter) GetDistance(other *entity.Spawn) float32 {
	return pa.player.GetDistance(other)
}
