package classes

import (
	"math/rand"
	"strings"
)

// ClassUtils provides utility functions for class operations
type ClassUtils struct {
	classes *Classes
}

// NewClassUtils creates a new class utilities instance
func NewClassUtils() *ClassUtils {
	return &ClassUtils{
		classes: GetGlobalClasses(),
	}
}

// ParseClassName attempts to parse a class name from various input formats
func (cu *ClassUtils) ParseClassName(input string) int8 {
	if input == "" {
		return -1
	}

	// Try direct lookup first
	classID := cu.classes.GetClassID(input)
	if classID != -1 {
		return classID
	}

	// Try with common variations
	variations := []string{
		strings.ToUpper(input),
		strings.ReplaceAll(strings.ToUpper(input), " ", ""),
		strings.ReplaceAll(strings.ToUpper(input), "_", ""),
		strings.ReplaceAll(strings.ToUpper(input), "-", ""),
	}

	for _, variation := range variations {
		if classID := cu.classes.GetClassID(variation); classID != -1 {
			return classID
		}
	}

	// Try matching against friendly names (case insensitive)
	inputLower := strings.ToLower(input)
	allClasses := cu.classes.GetAllClasses()
	for classID, displayName := range allClasses {
		if strings.ToLower(displayName) == inputLower {
			return classID
		}
	}

	return -1 // Not found
}

// FormatClassName returns a properly formatted class name
func (cu *ClassUtils) FormatClassName(classID int8, format string) string {
	switch strings.ToLower(format) {
	case "display", "friendly", "proper":
		return cu.classes.GetClassNameCase(classID)
	case "upper", "uppercase":
		return cu.classes.GetClassName(classID)
	case "lower", "lowercase":
		return strings.ToLower(cu.classes.GetClassName(classID))
	default:
		return cu.classes.GetClassNameCase(classID) // Default to friendly name
	}
}

// GetRandomClassByType returns a random class of the specified type
func (cu *ClassUtils) GetRandomClassByType(classType string) int8 {
	allClasses := cu.classes.GetAllClasses()
	validClasses := make([]int8, 0)

	for classID := range allClasses {
		if cu.classes.GetClassType(classID) == classType {
			validClasses = append(validClasses, classID)
		}
	}

	if len(validClasses) == 0 {
		return DefaultClassID
	}

	return validClasses[rand.Intn(len(validClasses))]
}

// GetRandomAdventureClass returns a random adventure class
func (cu *ClassUtils) GetRandomAdventureClass() int8 {
	return cu.GetRandomClassByType(ClassTypeAdventure)
}

// GetRandomTradeskillClass returns a random tradeskill class
func (cu *ClassUtils) GetRandomTradeskillClass() int8 {
	return cu.GetRandomClassByType(ClassTypeTradeskill)
}

// ValidateClassForRace checks if a class is valid for a specific race
// This is a placeholder for future race-class restrictions
func (cu *ClassUtils) ValidateClassForRace(classID, raceID int8) bool {
	// TODO: Implement race-class restrictions when race system is available
	// For now, all classes can be all races
	return cu.classes.IsValidClassID(classID)
}

// GetClassDescription returns a description of the class
func (cu *ClassUtils) GetClassDescription(classID int8) string {
	// This would typically come from a database or configuration
	// For now, provide basic descriptions based on class

	switch classID {
	case ClassCommoner:
		return "A starting class for all characters before choosing their path."
	case ClassFighter:
		return "Warriors who excel in melee combat and defense."
	case ClassWarrior:
		return "Masters of weapons and armor, the ultimate melee combatants."
	case ClassGuardian:
		return "Defensive warriors who protect their allies with shield and sword."
	case ClassBerserker:
		return "Rage-fueled fighters who sacrifice defense for devastating attacks."
	case ClassBrawler:
		return "Hand-to-hand combat specialists who fight with fists and focus."
	case ClassMonk:
		return "Disciplined fighters who use martial arts and inner peace."
	case ClassBruiser:
		return "Brutal brawlers who overwhelm enemies with raw power."
	case ClassCrusader:
		return "Holy warriors who blend combat prowess with divine magic."
	case ClassShadowknight:
		return "Dark knights who wield unholy magic alongside martial skill."
	case ClassPaladin:
		return "Champions of good who protect the innocent with sword and spell."
	case ClassPriest:
		return "Divine casters who channel the power of the gods."
	case ClassCleric:
		return "Healers and supporters who keep their allies alive and fighting."
	case ClassTemplar:
		return "Protective priests who shield allies from harm."
	case ClassInquisitor:
		return "Militant clerics who combine healing with righteous fury."
	case ClassDruid:
		return "Nature priests who harness the power of the natural world."
	case ClassWarden:
		return "Protective druids who shield allies with nature's blessing."
	case ClassFury:
		return "Destructive druids who unleash nature's wrath upon enemies."
	case ClassShaman:
		return "Spirit-workers who commune with ancestors and totems."
	case ClassMystic:
		return "Supportive shamans who provide wards and spiritual guidance."
	case ClassDefiler:
		return "Dark shamans who corrupt and weaken their enemies."
	case ClassMage:
		return "Wielders of arcane magic who bend reality to their will."
	case ClassSorcerer:
		return "Destructive mages who specialize in damaging spells."
	case ClassWizard:
		return "Scholarly sorcerers who master the elements."
	case ClassWarlock:
		return "Dark sorcerers who deal in forbidden magic."
	case ClassEnchanter:
		return "Mind-controlling mages who manipulate enemies and allies."
	case ClassIllusionist:
		return "Deceptive enchanters who confuse and misdirect."
	case ClassCoercer:
		return "Dominating enchanters who force enemies to obey."
	case ClassSummoner:
		return "Mages who call forth creatures to fight for them."
	case ClassConjuror:
		return "Elemental summoners who command earth and air."
	case ClassNecromancer:
		return "Death mages who raise undead minions and drain life."
	case ClassScout:
		return "Agile fighters who rely on speed and cunning."
	case ClassRogue:
		return "Stealthy combatants who strike from the shadows."
	case ClassSwashbuckler:
		return "Dashing rogues who fight with finesse and flair."
	case ClassBrigand:
		return "Brutal rogues who prefer dirty fighting tactics."
	case ClassBard:
		return "Musical combatants who inspire allies and demoralize foes."
	case ClassTroubador:
		return "Supportive bards who strengthen their allies."
	case ClassDirge:
		return "Dark bards who weaken enemies with haunting melodies."
	case ClassPredator:
		return "Hunters who excel at tracking and ranged combat."
	case ClassRanger:
		return "Nature-loving predators who protect the wilderness."
	case ClassAssassin:
		return "Deadly predators who eliminate targets with precision."
	case ClassAnimalist:
		return "Beast masters who fight alongside animal companions."
	case ClassBeastlord:
		return "Animalists who have formed powerful bonds with their pets."
	case ClassShaper:
		return "Mystic priests who manipulate spiritual energy."
	case ClassChanneler:
		return "Shapers who focus spiritual power through channeling."
	case ClassArtisan:
		return "Crafters who create useful items for adventurers."
	case ClassCraftsman:
		return "Specialized artisans who work with physical materials."
	case ClassProvisioner:
		return "Food and drink specialists who create consumables."
	case ClassWoodworker:
		return "Crafters who work with wood to create furniture and tools."
	case ClassCarpenter:
		return "Master woodworkers who create complex wooden items."
	case ClassOutfitter:
		return "Equipment crafters who create armor and weapons."
	case ClassArmorer:
		return "Specialists in creating protective armor."
	case ClassWeaponsmith:
		return "Masters of weapon crafting and enhancement."
	case ClassTailor:
		return "Cloth workers who create clothing and soft armor."
	case ClassScholar:
		return "Academic crafters who create magical and scholarly items."
	case ClassJeweler:
		return "Specialists in creating jewelry and accessories."
	case ClassSage:
		return "Book and scroll crafters who preserve knowledge."
	case ClassAlchemist:
		return "Potion makers who brew magical elixirs and potions."
	default:
		return "An unknown class with mysterious abilities."
	}
}

// GetClassProgression returns the class progression path
func (cu *ClassUtils) GetClassProgression(classID int8) []int8 {
	progression := make([]int8, 0)

	// Always start with Commoner (except for Commoner itself)
	if classID != ClassCommoner {
		progression = append(progression, ClassCommoner)
	}

	// Add base class if different from current
	baseClass := cu.classes.GetBaseClass(classID)
	if baseClass != classID && baseClass != ClassCommoner {
		progression = append(progression, baseClass)
	}

	// Add secondary base class if different
	secondaryBase := cu.classes.GetSecondaryBaseClass(classID)
	if secondaryBase != classID && secondaryBase != baseClass && secondaryBase != ClassCommoner {
		progression = append(progression, secondaryBase)
	}

	// Add the final class
	progression = append(progression, classID)

	return progression
}

// GetClassesForBaseClass returns all classes that belong to a base class
func (cu *ClassUtils) GetClassesForBaseClass(baseClassID int8) []int8 {
	result := make([]int8, 0)
	allClasses := cu.classes.GetAllClasses()

	for classID := range allClasses {
		if cu.classes.GetBaseClass(classID) == baseClassID {
			result = append(result, classID)
		}
	}

	return result
}

// GetClassesBySecondaryBase returns all classes that belong to a secondary base class
func (cu *ClassUtils) GetClassesBySecondaryBase(secondaryBaseID int8) []int8 {
	result := make([]int8, 0)
	allClasses := cu.classes.GetAllClasses()

	for classID := range allClasses {
		if cu.classes.GetSecondaryBaseClass(classID) == secondaryBaseID {
			result = append(result, classID)
		}
	}

	return result
}

// GetClassesByPattern returns classes matching a name pattern
func (cu *ClassUtils) GetClassesByPattern(pattern string) []int8 {
	pattern = strings.ToLower(pattern)
	result := make([]int8, 0)

	allClasses := cu.classes.GetAllClasses()
	for classID, displayName := range allClasses {
		if strings.Contains(strings.ToLower(displayName), pattern) {
			result = append(result, classID)
		}
	}

	return result
}

// ValidateClassTransition checks if a class change is allowed
func (cu *ClassUtils) ValidateClassTransition(fromClassID, toClassID int8) (bool, string) {
	if !cu.classes.IsValidClassID(fromClassID) {
		return false, "Invalid source class"
	}

	if !cu.classes.IsValidClassID(toClassID) {
		return false, "Invalid target class"
	}

	if fromClassID == toClassID {
		return false, "Cannot change to the same class"
	}

	// Basic progression validation - can only advance, not go backward
	fromProgression := cu.GetClassProgression(fromClassID)
	toProgression := cu.GetClassProgression(toClassID)

	// Check if the target class is a valid advancement
	if len(toProgression) <= len(fromProgression) {
		return false, "Cannot regress to a lower tier class"
	}

	// Check if the progressions are compatible (share the same base path)
	for i := 0; i < len(fromProgression); i++ {
		if i >= len(toProgression) || fromProgression[i] != toProgression[i] {
			return false, "Incompatible class progression paths"
		}
	}

	return true, ""
}

// GetClassAliases returns common aliases for a class
func (cu *ClassUtils) GetClassAliases(classID int8) []string {
	aliases := make([]string, 0)

	switch classID {
	case ClassShadowknight:
		aliases = append(aliases, "SK", "Shadow Knight", "Dark Knight")
	case ClassSwashbuckler:
		aliases = append(aliases, "Swash", "Swashy")
	case ClassTroubador:
		aliases = append(aliases, "Troub", "Troubadour")
	case ClassIllusionist:
		aliases = append(aliases, "Illy", "Illusion")
	case ClassConjuror:
		aliases = append(aliases, "Conj", "Conjurer")
	case ClassNecromancer:
		aliases = append(aliases, "Necro", "Nec")
	case ClassBeastlord:
		aliases = append(aliases, "BL", "Beast Lord")
	case ClassWeaponsmith:
		aliases = append(aliases, "WS", "Weapon Smith")
	}

	// Always include the official names
	aliases = append(aliases, cu.classes.GetClassName(classID))
	aliases = append(aliases, cu.classes.GetClassNameCase(classID))

	return aliases
}

// GetClassStatistics returns statistics about the class system
func (cu *ClassUtils) GetClassStatistics() map[string]interface{} {
	stats := make(map[string]interface{})

	allClasses := cu.classes.GetAllClasses()
	stats["total_classes"] = len(allClasses)

	adventureCount := 0
	tradeskillCount := 0
	specialCount := 0

	for classID := range allClasses {
		switch cu.classes.GetClassType(classID) {
		case ClassTypeAdventure:
			adventureCount++
		case ClassTypeTradeskill:
			tradeskillCount++
		default:
			specialCount++
		}
	}

	stats["adventure_classes"] = adventureCount
	stats["tradeskill_classes"] = tradeskillCount
	stats["special_classes"] = specialCount

	// Base class distribution
	baseClassDistribution := make(map[string][]string)
	for classID, displayName := range allClasses {
		if cu.classes.IsAdventureClass(classID) {
			baseClassID := cu.classes.GetBaseClass(classID)
			baseClassName := cu.classes.GetClassNameCase(baseClassID)
			baseClassDistribution[baseClassName] = append(baseClassDistribution[baseClassName], displayName)
		}
	}
	stats["base_class_distribution"] = baseClassDistribution

	return stats
}

// FormatClassList returns a formatted string of class names
func (cu *ClassUtils) FormatClassList(classIDs []int8, separator string) string {
	if len(classIDs) == 0 {
		return ""
	}

	names := make([]string, len(classIDs))
	for i, classID := range classIDs {
		names[i] = cu.classes.GetClassNameCase(classID)
	}

	return strings.Join(names, separator)
}

// GetEQClassName returns the EQ-style class name for a given class and level
// This is a placeholder for the original C++ GetEQClassName functionality
func (cu *ClassUtils) GetEQClassName(classID int8, level int8) string {
	// TODO: Implement level-based class names when level system is available
	// For now, just return the display name
	return cu.classes.GetClassNameCase(classID)
}

// GetStartingClass returns the appropriate starting class for character creation
func (cu *ClassUtils) GetStartingClass() int8 {
	return ClassCommoner
}

// IsBaseClass checks if a class is a base class (Fighter, Priest, Mage, Scout)
func (cu *ClassUtils) IsBaseClass(classID int8) bool {
	return classID == ClassFighter || classID == ClassPriest || classID == ClassMage || classID == ClassScout
}

// IsSecondaryBaseClass checks if a class is a secondary base class
func (cu *ClassUtils) IsSecondaryBaseClass(classID int8) bool {
	// Check if any class has this as their secondary base
	allClasses := cu.classes.GetAllClasses()
	for checkClassID := range allClasses {
		if cu.classes.GetSecondaryBaseClass(checkClassID) == classID && checkClassID != classID {
			return true
		}
	}
	return false
}
