package spells

import (
	"fmt"
	"sync"
)

// SpellResourceChecker handles checking and consuming spell casting resources
type SpellResourceChecker struct {
	// TODO: Add references to entity system when available
	// entityManager *EntityManager

	mutex sync.RWMutex
}

// ResourceCheckResult represents the result of a resource check
type ResourceCheckResult struct {
	HasSufficient bool    // Whether entity has sufficient resources
	CurrentValue  float32 // Current value of the resource
	RequiredValue float32 // Required value for the spell
	ResourceType  int32   // Type of resource checked
	ErrorMessage  string  // Error message if check failed
}

// NewSpellResourceChecker creates a new resource checker
func NewSpellResourceChecker() *SpellResourceChecker {
	return &SpellResourceChecker{}
}

// CheckPower verifies if the caster has enough power to cast the spell
// Converted from C++ SpellProcess::CheckPower
func (src *SpellResourceChecker) CheckPower(luaSpell *LuaSpell, customPowerReq float32) *ResourceCheckResult {
	if luaSpell == nil || luaSpell.Spell == nil {
		return &ResourceCheckResult{
			HasSufficient: false,
			CurrentValue:  0,
			RequiredValue: 0,
			ResourceType:  ResourceCheckPower,
			ErrorMessage:  "Invalid spell",
		}
	}

	powerRequired := customPowerReq
	if powerRequired == 0 {
		powerRequired = luaSpell.Spell.GetPowerRequired()
	}

	// TODO: Get actual power from entity when entity system is available
	// For now, assume entity has sufficient power
	currentPower := float32(1000.0) // Placeholder

	result := &ResourceCheckResult{
		HasSufficient: currentPower >= powerRequired,
		CurrentValue:  currentPower,
		RequiredValue: powerRequired,
		ResourceType:  ResourceCheckPower,
		ErrorMessage:  "",
	}

	if !result.HasSufficient {
		result.ErrorMessage = fmt.Sprintf("Insufficient power: need %.1f, have %.1f", powerRequired, currentPower)
	}

	return result
}

// TakePower consumes power for spell casting
// Converted from C++ SpellProcess::TakePower
func (src *SpellResourceChecker) TakePower(luaSpell *LuaSpell, customPowerReq float32) bool {
	result := src.CheckPower(luaSpell, customPowerReq)
	if !result.HasSufficient {
		return false
	}

	// TODO: Actually deduct power from entity when entity system is available
	// This would call something like:
	// entity.GetInfoStruct().SetPower(currentPower - powerRequired)
	// entity.GetZone().TriggerCharSheetTimer() // Update client display

	return true
}

// CheckHP verifies if the caster has enough health to cast the spell
// Converted from C++ SpellProcess::CheckHP
func (src *SpellResourceChecker) CheckHP(luaSpell *LuaSpell, customHPReq float32) *ResourceCheckResult {
	if luaSpell == nil || luaSpell.Spell == nil {
		return &ResourceCheckResult{
			HasSufficient: false,
			CurrentValue:  0,
			RequiredValue: 0,
			ResourceType:  ResourceCheckHealth,
			ErrorMessage:  "Invalid spell",
		}
	}

	hpRequired := customHPReq
	if hpRequired == 0 {
		hpRequired = float32(luaSpell.Spell.GetHPRequired())
	}

	// TODO: Get actual HP from entity when entity system is available
	// For now, assume entity has sufficient HP
	currentHP := float32(1000.0) // Placeholder

	result := &ResourceCheckResult{
		HasSufficient: currentHP >= hpRequired,
		CurrentValue:  currentHP,
		RequiredValue: hpRequired,
		ResourceType:  ResourceCheckHealth,
		ErrorMessage:  "",
	}

	if !result.HasSufficient {
		result.ErrorMessage = fmt.Sprintf("Insufficient health: need %.1f, have %.1f", hpRequired, currentHP)
	}

	return result
}

// TakeHP consumes health for spell casting
// Converted from C++ SpellProcess::TakeHP
func (src *SpellResourceChecker) TakeHP(luaSpell *LuaSpell, customHPReq float32) bool {
	result := src.CheckHP(luaSpell, customHPReq)
	if !result.HasSufficient {
		return false
	}

	// TODO: Actually deduct HP from entity when entity system is available
	// This would call something like:
	// entity.GetInfoStruct().SetHP(currentHP - hpRequired)
	// entity.GetZone().TriggerCharSheetTimer() // Update client display

	return true
}

// CheckConcentration verifies if the caster has enough concentration to cast the spell
// Converted from C++ SpellProcess::CheckConcentration
func (src *SpellResourceChecker) CheckConcentration(luaSpell *LuaSpell) *ResourceCheckResult {
	if luaSpell == nil || luaSpell.Spell == nil {
		return &ResourceCheckResult{
			HasSufficient: false,
			CurrentValue:  0,
			RequiredValue: 0,
			ResourceType:  ResourceCheckConcentration,
			ErrorMessage:  "Invalid spell",
		}
	}

	spellData := luaSpell.Spell.GetSpellData()
	if spellData == nil {
		return &ResourceCheckResult{
			HasSufficient: false,
			CurrentValue:  0,
			RequiredValue: 0,
			ResourceType:  ResourceCheckConcentration,
			ErrorMessage:  "Invalid spell data",
		}
	}

	concentrationRequired := float32(spellData.ReqConcentration)

	// TODO: Get actual concentration from entity when entity system is available
	// For now, assume entity has sufficient concentration
	currentConcentration := float32(100.0) // Placeholder

	result := &ResourceCheckResult{
		HasSufficient: currentConcentration >= concentrationRequired,
		CurrentValue:  currentConcentration,
		RequiredValue: concentrationRequired,
		ResourceType:  ResourceCheckConcentration,
		ErrorMessage:  "",
	}

	if !result.HasSufficient {
		result.ErrorMessage = fmt.Sprintf("Insufficient concentration: need %.1f, have %.1f", concentrationRequired, currentConcentration)
	}

	return result
}

// AddConcentration adds concentration for maintained spells
// Converted from C++ SpellProcess::AddConcentration
func (src *SpellResourceChecker) AddConcentration(luaSpell *LuaSpell) bool {
	result := src.CheckConcentration(luaSpell)
	if !result.HasSufficient {
		return false
	}

	// TODO: Actually deduct concentration from entity when entity system is available
	// This would call something like:
	// currentConc := entity.GetInfoStruct().GetCurConcentration()
	// entity.GetInfoStruct().SetCurConcentration(currentConc + concentrationRequired)
	// entity.GetZone().TriggerCharSheetTimer() // Update client display

	return true
}

// CheckSavagery verifies if the caster has enough savagery to cast the spell
// Converted from C++ SpellProcess::CheckSavagery
func (src *SpellResourceChecker) CheckSavagery(luaSpell *LuaSpell) *ResourceCheckResult {
	if luaSpell == nil || luaSpell.Spell == nil {
		return &ResourceCheckResult{
			HasSufficient: false,
			CurrentValue:  0,
			RequiredValue: 0,
			ResourceType:  ResourceCheckSavagery,
			ErrorMessage:  "Invalid spell",
		}
	}

	savageryRequired := float32(luaSpell.Spell.GetSavageryRequired())

	// TODO: Get actual savagery from entity when entity system is available
	// For now, assume entity has sufficient savagery
	currentSavagery := float32(100.0) // Placeholder

	result := &ResourceCheckResult{
		HasSufficient: currentSavagery >= savageryRequired,
		CurrentValue:  currentSavagery,
		RequiredValue: savageryRequired,
		ResourceType:  ResourceCheckSavagery,
		ErrorMessage:  "",
	}

	if !result.HasSufficient {
		result.ErrorMessage = fmt.Sprintf("Insufficient savagery: need %.1f, have %.1f", savageryRequired, currentSavagery)
	}

	return result
}

// TakeSavagery consumes savagery for spell casting
// Converted from C++ SpellProcess::TakeSavagery
func (src *SpellResourceChecker) TakeSavagery(luaSpell *LuaSpell) bool {
	result := src.CheckSavagery(luaSpell)
	if !result.HasSufficient {
		return false
	}

	// TODO: Actually deduct savagery from entity when entity system is available
	// This would call something like:
	// entity.GetInfoStruct().SetSavagery(currentSavagery - savageryRequired)
	// entity.GetZone().TriggerCharSheetTimer() // Update client display

	return true
}

// CheckDissonance verifies if the caster has enough dissonance to cast the spell
// Converted from C++ SpellProcess::CheckDissonance
func (src *SpellResourceChecker) CheckDissonance(luaSpell *LuaSpell) *ResourceCheckResult {
	if luaSpell == nil || luaSpell.Spell == nil {
		return &ResourceCheckResult{
			HasSufficient: false,
			CurrentValue:  0,
			RequiredValue: 0,
			ResourceType:  ResourceCheckDissonance,
			ErrorMessage:  "Invalid spell",
		}
	}

	dissonanceRequired := float32(luaSpell.Spell.GetDissonanceRequired())

	// TODO: Get actual dissonance from entity when entity system is available
	// For now, assume entity has sufficient dissonance
	currentDissonance := float32(100.0) // Placeholder

	result := &ResourceCheckResult{
		HasSufficient: currentDissonance >= dissonanceRequired,
		CurrentValue:  currentDissonance,
		RequiredValue: dissonanceRequired,
		ResourceType:  ResourceCheckDissonance,
		ErrorMessage:  "",
	}

	if !result.HasSufficient {
		result.ErrorMessage = fmt.Sprintf("Insufficient dissonance: need %.1f, have %.1f", dissonanceRequired, currentDissonance)
	}

	return result
}

// AddDissonance adds dissonance for spell casting
// Converted from C++ SpellProcess::AddDissonance
func (src *SpellResourceChecker) AddDissonance(luaSpell *LuaSpell) bool {
	result := src.CheckDissonance(luaSpell)
	if !result.HasSufficient {
		return false
	}

	// TODO: Actually add dissonance to entity when entity system is available
	// This would call something like:
	// entity.GetInfoStruct().SetDissonance(currentDissonance + dissonanceRequired)
	// entity.GetZone().TriggerCharSheetTimer() // Update client display

	return true
}

// CheckAllResources performs a comprehensive resource check for a spell
func (src *SpellResourceChecker) CheckAllResources(luaSpell *LuaSpell, customPowerReq, customHPReq float32) []ResourceCheckResult {
	results := make([]ResourceCheckResult, 0)

	// Check power
	powerResult := src.CheckPower(luaSpell, customPowerReq)
	if powerResult.RequiredValue > 0 {
		results = append(results, *powerResult)
	}

	// Check health
	hpResult := src.CheckHP(luaSpell, customHPReq)
	if hpResult.RequiredValue > 0 {
		results = append(results, *hpResult)
	}

	// Check concentration
	concResult := src.CheckConcentration(luaSpell)
	if concResult.RequiredValue > 0 {
		results = append(results, *concResult)
	}

	// Check savagery
	savageryResult := src.CheckSavagery(luaSpell)
	if savageryResult.RequiredValue > 0 {
		results = append(results, *savageryResult)
	}

	// Check dissonance
	dissonanceResult := src.CheckDissonance(luaSpell)
	if dissonanceResult.RequiredValue > 0 {
		results = append(results, *dissonanceResult)
	}

	return results
}

// ConsumeAllResources attempts to consume all required resources for a spell
func (src *SpellResourceChecker) ConsumeAllResources(luaSpell *LuaSpell, customPowerReq, customHPReq float32) bool {
	// First check all resources
	results := src.CheckAllResources(luaSpell, customPowerReq, customHPReq)

	// Verify all resources are sufficient
	for _, result := range results {
		if !result.HasSufficient {
			return false
		}
	}

	// Consume resources
	success := true

	// Take power if required
	powerResult := src.CheckPower(luaSpell, customPowerReq)
	if powerResult.RequiredValue > 0 {
		success = success && src.TakePower(luaSpell, customPowerReq)
	}

	// Take health if required
	hpResult := src.CheckHP(luaSpell, customHPReq)
	if hpResult.RequiredValue > 0 {
		success = success && src.TakeHP(luaSpell, customHPReq)
	}

	// Add concentration if required (for maintained spells)
	spellData := luaSpell.Spell.GetSpellData()
	if spellData != nil && spellData.CastType == SpellCastTypeToggle {
		concResult := src.CheckConcentration(luaSpell)
		if concResult.RequiredValue > 0 {
			success = success && src.AddConcentration(luaSpell)
		}
	}

	// Take savagery if required
	savageryResult := src.CheckSavagery(luaSpell)
	if savageryResult.RequiredValue > 0 {
		success = success && src.TakeSavagery(luaSpell)
	}

	// Add dissonance if required
	dissonanceResult := src.CheckDissonance(luaSpell)
	if dissonanceResult.RequiredValue > 0 {
		success = success && src.AddDissonance(luaSpell)
	}

	return success
}

// GetResourceSummary returns a summary of all resource requirements for a spell
func (src *SpellResourceChecker) GetResourceSummary(spell *Spell) map[string]float32 {
	summary := make(map[string]float32)

	if spell == nil {
		return summary
	}

	summary["power"] = spell.GetPowerRequired()
	summary["health"] = float32(spell.GetHPRequired())
	summary["savagery"] = float32(spell.GetSavageryRequired())
	summary["dissonance"] = float32(spell.GetDissonanceRequired())

	spellData := spell.GetSpellData()
	if spellData != nil {
		summary["concentration"] = float32(spellData.ReqConcentration)
	}

	return summary
}

// ValidateResourceRequirements checks if resource requirements are reasonable
func (src *SpellResourceChecker) ValidateResourceRequirements(spell *Spell) []string {
	errors := make([]string, 0)

	if spell == nil {
		errors = append(errors, "Spell is nil")
		return errors
	}

	// Check for negative requirements
	if spell.GetPowerRequired() < 0 {
		errors = append(errors, "Power requirement cannot be negative")
	}

	if spell.GetHPRequired() < 0 {
		errors = append(errors, "Health requirement cannot be negative")
	}

	if spell.GetSavageryRequired() < 0 {
		errors = append(errors, "Savagery requirement cannot be negative")
	}

	if spell.GetDissonanceRequired() < 0 {
		errors = append(errors, "Dissonance requirement cannot be negative")
	}

	spellData := spell.GetSpellData()
	if spellData != nil {
		if spellData.ReqConcentration < 0 {
			errors = append(errors, "Concentration requirement cannot be negative")
		}

		// Check for excessive requirements
		if spell.GetPowerRequired() > 10000 {
			errors = append(errors, "Power requirement seems excessive (>10000)")
		}

		if spell.GetHPRequired() > 5000 {
			errors = append(errors, "Health requirement seems excessive (>5000)")
		}
	}

	return errors
}

// GetFailureReason returns an appropriate failure reason code based on resource check results
func (src *SpellResourceChecker) GetFailureReason(results []ResourceCheckResult) int32 {
	for _, result := range results {
		if !result.HasSufficient {
			switch result.ResourceType {
			case ResourceCheckPower:
				return FailureReasonInsufficientPower
			case ResourceCheckHealth:
				return FailureReasonInsufficientHealth
			case ResourceCheckConcentration:
				return FailureReasonInsufficientConc
			default:
				return FailureReasonRequirementNotMet
			}
		}
	}

	return FailureReasonNone
}
