package skills

// AddSkillBonus adds a skill bonus from a spell
func (psl *PlayerSkillList) AddSkillBonus(spellID int32, skillID int32, value float32) {
	if value == 0 {
		return
	}

	psl.bonusMutex.Lock()
	defer psl.bonusMutex.Unlock()

	// Get or create skill bonus entry for this spell
	skillBonus, exists := psl.skillBonusList[spellID]
	if !exists {
		skillBonus = &SkillBonus{
			SpellID: spellID,
			Skills:  make(map[int32]*SkillBonusValue),
		}
		psl.skillBonusList[spellID] = skillBonus
	}

	// Add or update the skill bonus value
	if skillBonus.Skills[skillID] == nil {
		skillBonus.Skills[skillID] = &SkillBonusValue{
			SkillID: skillID,
			Value:   value,
		}
	}
}

// GetSkillBonus returns skill bonus for a spell
func (psl *PlayerSkillList) GetSkillBonus(spellID int32) *SkillBonus {
	psl.bonusMutex.RLock()
	defer psl.bonusMutex.RUnlock()

	if bonus, exists := psl.skillBonusList[spellID]; exists {
		return bonus
	}

	return nil
}

// RemoveSkillBonus removes all skill bonuses from a spell
func (psl *PlayerSkillList) RemoveSkillBonus(spellID int32) {
	psl.bonusMutex.Lock()
	defer psl.bonusMutex.Unlock()

	if skillBonus, exists := psl.skillBonusList[spellID]; exists {
		// Clean up skill bonus values
		for _, bonusValue := range skillBonus.Skills {
			_ = bonusValue // In C++, this would be safe_delete(bonusValue)
		}

		delete(psl.skillBonusList, spellID)
	}
}

// CalculateSkillValue calculates a skill's value including bonuses
func (psl *PlayerSkillList) CalculateSkillValue(skillID int32, currentVal int16) int16 {
	if currentVal <= 5 {
		return currentVal
	}

	psl.bonusMutex.RLock()
	defer psl.bonusMutex.RUnlock()

	newVal := currentVal

	// Apply all skill bonuses
	for _, skillBonus := range psl.skillBonusList {
		if bonusValue, exists := skillBonus.Skills[skillID]; exists {
			newVal += int16(bonusValue.Value)
		}
	}

	return newVal
}

// CalculateSkillMaxValue calculates a skill's max value including bonuses
func (psl *PlayerSkillList) CalculateSkillMaxValue(skillID int32, maxVal int16) int16 {
	psl.bonusMutex.RLock()
	defer psl.bonusMutex.RUnlock()

	newVal := maxVal

	// Apply all skill bonuses to max value
	for _, skillBonus := range psl.skillBonusList {
		if bonusValue, exists := skillBonus.Skills[skillID]; exists {
			newVal += int16(bonusValue.Value)
		}
	}

	return newVal
}

// GetAllSkillBonuses returns all skill bonuses (for debugging/admin)
func (psl *PlayerSkillList) GetAllSkillBonuses() map[int32]*SkillBonus {
	psl.bonusMutex.RLock()
	defer psl.bonusMutex.RUnlock()

	// Return a copy to prevent external modification
	bonuses := make(map[int32]*SkillBonus)
	for spellID, bonus := range psl.skillBonusList {
		// Deep copy the skill bonus
		newBonus := &SkillBonus{
			SpellID: bonus.SpellID,
			Skills:  make(map[int32]*SkillBonusValue),
		}

		for skillID, bonusValue := range bonus.Skills {
			newBonus.Skills[skillID] = &SkillBonusValue{
				SkillID: bonusValue.SkillID,
				Value:   bonusValue.Value,
			}
		}

		bonuses[spellID] = newBonus
	}

	return bonuses
}

// RemoveAllSkillBonuses removes all skill bonuses (for cleanup)
func (psl *PlayerSkillList) RemoveAllSkillBonuses() {
	psl.bonusMutex.Lock()
	defer psl.bonusMutex.Unlock()

	// Clean up all skill bonuses
	for spellID := range psl.skillBonusList {
		if skillBonus, exists := psl.skillBonusList[spellID]; exists {
			for _, bonusValue := range skillBonus.Skills {
				_ = bonusValue // In C++, this would be safe_delete(bonusValue)
			}
		}
	}

	psl.skillBonusList = make(map[int32]*SkillBonus)
}

// GetSkillBonusTotal returns the total bonus for a specific skill
func (psl *PlayerSkillList) GetSkillBonusTotal(skillID int32) float32 {
	psl.bonusMutex.RLock()
	defer psl.bonusMutex.RUnlock()

	var total float32

	for _, skillBonus := range psl.skillBonusList {
		if bonusValue, exists := skillBonus.Skills[skillID]; exists {
			total += bonusValue.Value
		}
	}

	return total
}

// HasSkillBonuses returns whether the player has any skill bonuses
func (psl *PlayerSkillList) HasSkillBonuses() bool {
	psl.bonusMutex.RLock()
	defer psl.bonusMutex.RUnlock()

	return len(psl.skillBonusList) > 0
}

// GetSpellsWithSkillBonuses returns all spell IDs that provide skill bonuses
func (psl *PlayerSkillList) GetSpellsWithSkillBonuses() []int32 {
	psl.bonusMutex.RLock()
	defer psl.bonusMutex.RUnlock()

	spellIDs := make([]int32, 0, len(psl.skillBonusList))
	for spellID := range psl.skillBonusList {
		spellIDs = append(spellIDs, spellID)
	}

	return spellIDs
}
