package races

import (
	"math/rand"
	"strings"
)

// RaceUtils provides utility functions for race operations
type RaceUtils struct {
	races *Races
}

// NewRaceUtils creates a new race utilities instance
func NewRaceUtils() *RaceUtils {
	return &RaceUtils{
		races: GetGlobalRaces(),
	}
}

// ParseRaceName attempts to parse a race name from various input formats
func (ru *RaceUtils) ParseRaceName(input string) int8 {
	if input == "" {
		return -1
	}

	// Try direct lookup first
	raceID := ru.races.GetRaceID(input)
	if raceID != -1 {
		return raceID
	}

	// 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 raceID := ru.races.GetRaceID(variation); raceID != -1 {
			return raceID
		}
	}

	// Try matching against friendly names (case insensitive)
	inputLower := strings.ToLower(input)
	allRaces := ru.races.GetAllRaces()
	for raceID, friendlyName := range allRaces {
		if strings.ToLower(friendlyName) == inputLower {
			return raceID
		}
	}

	return -1 // Not found
}

// FormatRaceName returns a properly formatted race name
func (ru *RaceUtils) FormatRaceName(raceID int8, format string) string {
	switch strings.ToLower(format) {
	case "display", "friendly", "proper":
		return ru.races.GetRaceNameCase(raceID)
	case "upper", "uppercase":
		return ru.races.GetRaceName(raceID)
	case "lower", "lowercase":
		return strings.ToLower(ru.races.GetRaceName(raceID))
	default:
		return ru.races.GetRaceNameCase(raceID) // Default to friendly name
	}
}

// GetRandomRaceByAlignment returns a random race for the specified alignment
func (ru *RaceUtils) GetRandomRaceByAlignment(alignment string) int8 {
	switch strings.ToLower(alignment) {
	case AlignmentGood:
		return ru.races.GetRandomGoodRace()
	case AlignmentEvil:
		return ru.races.GetRandomEvilRace()
	default:
		// For neutral or any other alignment, pick from all races
		allRaces := ru.races.GetAllRaces()
		if len(allRaces) == 0 {
			return DefaultRaceID
		}

		// Convert map to slice for random selection
		raceIDs := make([]int8, 0, len(allRaces))
		for raceID := range allRaces {
			raceIDs = append(raceIDs, raceID)
		}

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

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

// GetRaceDescription returns a description of the race
func (ru *RaceUtils) GetRaceDescription(raceID int8) string {
	// This would typically come from a database or configuration
	// For now, provide basic descriptions based on race

	switch raceID {
	case RaceHuman:
		return "Versatile and adaptable, humans are found throughout Norrath."
	case RaceBarbarian:
		return "Hardy warriors from the frozen lands of Everfrost."
	case RaceDarkElf:
		return "Cunning and magical, the dark elves hail from Neriak."
	case RaceDwarf:
		return "Stout and strong, dwarves are master craftsmen and fighters."
	case RaceErudite:
		return "Intelligent and scholarly, erudites value knowledge above all."
	case RaceFroglok:
		return "Honorable amphibians who have overcome great adversity."
	case RaceGnome:
		return "Small but ingenious, gnomes are masters of tinkering and magic."
	case RaceHalfElf:
		return "Caught between two worlds, half elves combine human adaptability with elven grace."
	case RaceHalfling:
		return "Small and nimble, halflings are natural rogues and adventurers."
	case RaceHighElf:
		return "Noble and proud, high elves are paragons of magical prowess."
	case RaceIksar:
		return "Ancient lizardfolk with a proud warrior tradition."
	case RaceKerra:
		return "Feline humanoids known for their agility and curiosity."
	case RaceOgre:
		return "Massive and powerful, ogres are fearsome warriors."
	case RaceRatonga:
		return "Clever rodent-folk who excel at stealth and cunning."
	case RaceTroll:
		return "Large and brutish, trolls possess incredible strength and regeneration."
	case RaceWoodElf:
		return "Forest dwellers with unmatched skill in archery and nature magic."
	case RaceFae:
		return "Magical fairy-folk with wings and a connection to nature."
	case RaceArasai:
		return "Dark counterparts to the Fae, corrupted by shadow magic."
	case RaceSarnak:
		return "Draconic humanoids with scales and ancient wisdom."
	case RaceVampire:
		return "Undead beings with supernatural powers and bloodthirst."
	case RaceAerakyn:
		return "Dragon-blooded humanoids with draconic heritage and flight."
	default:
		return "An unknown race with mysterious origins."
	}
}

// GetRaceStatModifiers returns racial stat modifiers for character creation
// This is a placeholder for future stat system integration
func (ru *RaceUtils) GetRaceStatModifiers(raceID int8) map[string]int8 {
	// TODO: Implement racial stat modifiers when stat system is available
	// This would typically come from database or configuration files

	modifiers := make(map[string]int8)

	// Example modifiers (these would need to be balanced and come from data)
	switch raceID {
	case RaceBarbarian:
		modifiers["strength"] = 2
		modifiers["stamina"] = 1
		modifiers["intelligence"] = -1
	case RaceDarkElf:
		modifiers["intelligence"] = 2
		modifiers["agility"] = 1
		modifiers["wisdom"] = -1
	case RaceDwarf:
		modifiers["stamina"] = 2
		modifiers["strength"] = 1
		modifiers["agility"] = -1
	case RaceErudite:
		modifiers["intelligence"] = 3
		modifiers["wisdom"] = 1
		modifiers["strength"] = -2
	case RaceGnome:
		modifiers["intelligence"] = 2
		modifiers["agility"] = 1
		modifiers["strength"] = -2
	case RaceHighElf:
		modifiers["intelligence"] = 2
		modifiers["wisdom"] = 1
		modifiers["stamina"] = -1
	case RaceOgre:
		modifiers["strength"] = 3
		modifiers["stamina"] = 2
		modifiers["intelligence"] = -2
		modifiers["agility"] = -1
	case RaceTroll:
		modifiers["strength"] = 2
		modifiers["stamina"] = 3
		modifiers["intelligence"] = -2
		modifiers["wisdom"] = -1
	default:
		// Humans and other races have no modifiers (balanced)
		break
	}

	return modifiers
}

// GetRaceStartingLocation returns the starting city/zone for a race
func (ru *RaceUtils) GetRaceStartingLocation(raceID int8) string {
	// TODO: This would typically come from database configuration
	switch raceID {
	case RaceHuman, RaceBarbarian, RaceErudite, RaceKerra:
		return "Qeynos"
	case RaceDarkElf, RaceOgre, RaceRatonga, RaceTroll:
		return "Freeport"
	case RaceDwarf, RaceGnome, RaceHalfling:
		return "New Halas"
	case RaceHighElf, RaceWoodElf, RaceHalfElf:
		return "Kelethin"
	case RaceIksar, RaceSarnak:
		return "Gorowyn"
	case RaceFroglok:
		return "Temple of Cazic-Thule"
	case RaceFae:
		return "Greater Faydark"
	case RaceArasai:
		return "Darklight Wood"
	case RaceVampire:
		return "Neriak"
	case RaceAerakyn:
		return "Draconic Starting Area"
	default:
		return "Qeynos" // Default starting location
	}
}

// GetCompatibleRaces returns races that can interact peacefully
func (ru *RaceUtils) GetCompatibleRaces(raceID int8) []int8 {
	// This is based on lore and alignment - races of similar alignment are generally compatible
	alignment := ru.races.GetRaceAlignment(raceID)
	return ru.races.GetRacesByAlignment(alignment)
}

// FormatRaceList returns a formatted string of race names
func (ru *RaceUtils) FormatRaceList(raceIDs []int8, separator string) string {
	if len(raceIDs) == 0 {
		return ""
	}

	names := make([]string, len(raceIDs))
	for i, raceID := range raceIDs {
		names[i] = ru.races.GetRaceNameCase(raceID)
	}

	return strings.Join(names, separator)
}

// GetRacesByPattern returns races matching a name pattern
func (ru *RaceUtils) GetRacesByPattern(pattern string) []int8 {
	pattern = strings.ToLower(pattern)
	result := make([]int8, 0)

	allRaces := ru.races.GetAllRaces()
	for raceID, friendlyName := range allRaces {
		if strings.Contains(strings.ToLower(friendlyName), pattern) {
			result = append(result, raceID)
		}
	}

	return result
}

// ValidateRaceTransition checks if a race change is allowed
func (ru *RaceUtils) ValidateRaceTransition(fromRaceID, toRaceID int8) (bool, string) {
	if !ru.races.IsValidRaceID(fromRaceID) {
		return false, "Invalid source race"
	}

	if !ru.races.IsValidRaceID(toRaceID) {
		return false, "Invalid target race"
	}

	if fromRaceID == toRaceID {
		return false, "Cannot change to the same race"
	}

	// TODO: Implement specific race change restrictions when needed
	// For now, allow all transitions
	return true, ""
}

// GetRaceAliases returns common aliases for a race
func (ru *RaceUtils) GetRaceAliases(raceID int8) []string {
	aliases := make([]string, 0)

	switch raceID {
	case RaceDarkElf:
		aliases = append(aliases, "DE", "Dark Elf", "Teir'Dal")
	case RaceHighElf:
		aliases = append(aliases, "HE", "High Elf", "Koada'Dal")
	case RaceWoodElf:
		aliases = append(aliases, "WE", "Wood Elf", "Feir'Dal")
	case RaceHalfElf:
		aliases = append(aliases, "Half-Elf", "Half Elf", "Ayr'Dal")
	case RaceFae:
		aliases = append(aliases, "Fairy", "Pixie")
	case RaceArasai:
		aliases = append(aliases, "Dark Fae", "Shadow Fae")
	case RaceVampire:
		aliases = append(aliases, "Vamp", "Undead")
	case RaceAerakyn:
		aliases = append(aliases, "Dragon-kin", "Dragonborn")
	}

	// Always include the official names
	aliases = append(aliases, ru.races.GetRaceName(raceID))
	aliases = append(aliases, ru.races.GetRaceNameCase(raceID))

	return aliases
}

// GetRaceStatistics returns statistics about the race system
func (ru *RaceUtils) GetRaceStatistics() map[string]interface{} {
	stats := make(map[string]interface{})

	stats["total_races"] = ru.races.GetRaceCount()
	stats["good_races"] = ru.races.GetGoodRaceCount()
	stats["evil_races"] = ru.races.GetEvilRaceCount()

	// Count neutral races (appear in both lists)
	neutralCount := 0
	allRaces := ru.races.GetAllRaces()
	for raceID := range allRaces {
		if ru.races.IsNeutralRace(raceID) {
			neutralCount++
		}
	}
	stats["neutral_races"] = neutralCount

	// Race distribution by alignment
	alignmentDistribution := make(map[string][]string)
	for raceID, friendlyName := range allRaces {
		alignment := ru.races.GetRaceAlignment(raceID)
		alignmentDistribution[alignment] = append(alignmentDistribution[alignment], friendlyName)
	}
	stats["alignment_distribution"] = alignmentDistribution

	return stats
}
