package player

import (
	"eq2emu/internal/entity"
)

// InCombat sets the player's combat state
func (p *Player) InCombat(val bool, ranged bool) {
	if val {
		// Entering combat
		if ranged {
			p.SetCharacterFlag(CF_RANGED_AUTO_ATTACK)
			p.SetRangeAttack(true)
		} else {
			p.SetCharacterFlag(CF_AUTO_ATTACK)
		}

		// Set combat state in info struct
		prevState := p.GetInfoStruct().GetEngageCommands()
		if ranged {
			p.GetInfoStruct().SetEngageCommands(prevState | RANGE_COMBAT_STATE)
		} else {
			p.GetInfoStruct().SetEngageCommands(prevState | MELEE_COMBAT_STATE)
		}
	} else {
		// Leaving combat
		if ranged {
			p.ResetCharacterFlag(CF_RANGED_AUTO_ATTACK)
			p.SetRangeAttack(false)
			prevState := p.GetInfoStruct().GetEngageCommands()
			p.GetInfoStruct().SetEngageCommands(prevState & ^RANGE_COMBAT_STATE)
		} else {
			p.ResetCharacterFlag(CF_AUTO_ATTACK)
			prevState := p.GetInfoStruct().GetEngageCommands()
			p.GetInfoStruct().SetEngageCommands(prevState & ^MELEE_COMBAT_STATE)
		}

		// Clear combat target if leaving all combat
		if p.GetInfoStruct().GetEngageCommands() == 0 {
			p.combatTarget = nil
		}
	}

	p.SetCharSheetChanged(true)
}

// ProcessCombat processes combat actions
func (p *Player) ProcessCombat() {
	// Check if in combat
	if p.GetInfoStruct().GetEngageCommands() == 0 {
		return
	}

	// Check if we have a valid target
	if p.combatTarget == nil || p.combatTarget.IsDead() {
		p.StopCombat(0)
		return
	}

	// Check distance to target
	distance := p.GetDistance(&p.combatTarget.Spawn)

	// Process based on combat type
	if p.rangeAttack {
		// Ranged combat
		maxRange := p.GetRangeWeaponRange()
		if distance > maxRange {
			// Too far for ranged
			// TODO: Send out of range message
			return
		}

		// TODO: Process ranged auto-attack
	} else {
		// Melee combat
		maxRange := p.GetMeleeWeaponRange()
		if distance > maxRange {
			// Too far for melee
			// TODO: Send out of range message
			return
		}

		// TODO: Process melee auto-attack
	}
}

// GetRangeWeaponRange returns the range of the equipped ranged weapon
func (p *Player) GetRangeWeaponRange() float32 {
	// TODO: Get from equipped ranged weapon
	return 35.0 // Default bow range
}

// GetMeleeWeaponRange returns the range of melee weapons
func (p *Player) GetMeleeWeaponRange() float32 {
	// TODO: Adjust based on weapon type and mob size
	return 5.0 // Default melee range
}

// SetCombatTarget sets the current combat target
func (p *Player) SetCombatTarget(target *entity.Entity) {
	p.combatTarget = target
}

// GetCombatTarget returns the current combat target
func (p *Player) GetCombatTarget() *entity.Entity {
	return p.combatTarget
}

// DamageEquippedItems damages equipped items by durability
func (p *Player) DamageEquippedItems(amount int8, client *Client) bool {
	// TODO: Implement item durability damage
	// This would:
	// 1. Get all equipped items
	// 2. Reduce durability by amount
	// 3. Check if any items broke
	// 4. Send updates to client
	return false
}

// GetTSArrowColor returns the arrow color for tradeskill con
func (p *Player) GetTSArrowColor(level int8) int8 {
	levelDiff := int(level) - int(p.GetTSLevel())

	if levelDiff >= 10 {
		return 4 // Red
	} else if levelDiff >= 5 {
		return 3 // Orange
	} else if levelDiff >= 1 {
		return 2 // Yellow
	} else if levelDiff >= -5 {
		return 1 // White
	} else if levelDiff >= -9 {
		return 0 // Blue
	} else {
		return 6 // Green
	}
}

// CheckLevelStatus checks and updates level-based statuses
func (p *Player) CheckLevelStatus(newLevel int16) bool {
	// TODO: Implement level status checks
	// This would check things like:
	// - Mentoring status
	// - Level-locked abilities
	// - Zone level requirements
	// - etc.
	return true
}

// CalculatePlayerHPPower calculates HP and Power for the player
func (p *Player) CalculatePlayerHPPower(newLevel int16) {
	if newLevel == 0 {
		newLevel = int16(p.GetLevel())
	}

	// TODO: Implement proper HP/Power calculation
	// This is a simplified version

	// Base HP calculation
	baseHP := int32(50 + (newLevel * 20))
	staminaBonus := p.GetInfoStruct().GetSta() * 10
	totalHP := baseHP + staminaBonus

	// Base Power calculation
	basePower := int32(50 + (newLevel * 10))
	primaryStatBonus := p.GetPrimaryStat() * 10
	totalPower := basePower + primaryStatBonus

	// Set the values
	p.SetTotalHP(totalHP)
	p.SetTotalPower(totalPower)

	// Set current values if needed
	if p.GetHP() > totalHP {
		p.SetHP(totalHP)
	}
	if p.GetPower() > totalPower {
		p.SetPower(totalPower)
	}
}

// IsAllowedCombatEquip checks if combat equipment changes are allowed
func (p *Player) IsAllowedCombatEquip(slot int8, sendMessage bool) bool {
	// Can't change equipment while:
	// - Dead
	// - In combat (for certain slots)
	// - Casting
	// - Stunned/Mezzed

	if p.IsDead() {
		if sendMessage {
			// TODO: Send "You cannot change equipment while dead" message
		}
		return false
	}

	// Check if in combat
	if p.GetInfoStruct().GetEngageCommands() != 0 {
		// Some slots can't be changed in combat
		// TODO: Define which slots are restricted
		restrictedSlots := []int8{0, 1, 2} // Example: primary, secondary, ranged
		for _, restrictedSlot := range restrictedSlots {
			if slot == restrictedSlot || slot == 255 { // 255 = all slots
				if sendMessage {
					// TODO: Send "You cannot change that equipment in combat" message
				}
				return false
			}
		}
	}

	// Check if casting
	if p.IsCasting() {
		if sendMessage {
			// TODO: Send "You cannot change equipment while casting" message
		}
		return false
	}

	// Check control effects
	if p.IsStunned() || p.IsMezzed() {
		if sendMessage {
			// TODO: Send appropriate message
		}
		return false
	}

	return true
}

// IsCasting returns whether the player is currently casting
func (p *Player) IsCasting() bool {
	// TODO: Check actual casting state
	return false
}

// DismissAllPets dismisses all of the player's pets
func (p *Player) DismissAllPets() {
	// TODO: Implement pet dismissal
	// This would:
	// 1. Get all pets (combat, non-combat, deity, etc.)
	// 2. Remove them from world
	// 3. Clear pet references
	// 4. Send updates to client
}

// MentorTarget mentors the current target
func (p *Player) MentorTarget() {
	target := p.GetTarget()
	if target == nil || !target.IsPlayer() {
		// TODO: Send "Invalid mentor target" message
		return
	}

	targetPlayer, ok := target.(*Player)
	if !ok {
		return
	}

	// Check if target is valid for mentoring
	if targetPlayer.GetLevel() >= p.GetLevel() {
		// TODO: Send "Target must be lower level" message
		return
	}

	// Set mentor stats
	p.SetMentorStats(int32(targetPlayer.GetLevel()), targetPlayer.GetCharacterID(), true)
}

// SetMentorStats sets the player's effective level for mentoring
func (p *Player) SetMentorStats(effectiveLevel int32, targetCharID int32, updateStats bool) {
	if effectiveLevel < 1 || effectiveLevel > int32(p.GetLevel()) {
		effectiveLevel = int32(p.GetLevel())
	}

	p.GetInfoStruct().SetEffectiveLevel(int8(effectiveLevel))

	if updateStats {
		// TODO: Recalculate all stats for new effective level
		p.CalculatePlayerHPPower(int16(effectiveLevel))
		// TODO: Update other stats (mitigation, avoidance, etc.)
	}

	if effectiveLevel < int32(p.GetLevel()) {
		p.EnableResetMentorship()
	}

	p.SetCharSheetChanged(true)
}
