package races

import (
	"fmt"
)

// RaceAware interface for entities that have race information
type RaceAware interface {
	GetRace() int8
	SetRace(int8)
}

// EntityWithRace interface extends RaceAware with additional entity properties
type EntityWithRace interface {
	RaceAware
	GetID() int32
	GetName() string
}

// RaceIntegration provides race-related functionality for other systems
type RaceIntegration struct {
	races *Races
	utils *RaceUtils
}

// NewRaceIntegration creates a new race integration helper
func NewRaceIntegration() *RaceIntegration {
	return &RaceIntegration{
		races: GetGlobalRaces(),
		utils: NewRaceUtils(),
	}
}

// ValidateEntityRace validates an entity's race and provides detailed information
func (ri *RaceIntegration) ValidateEntityRace(entity RaceAware) (bool, string, map[string]interface{}) {
	raceID := entity.GetRace()

	if !ri.races.IsValidRaceID(raceID) {
		return false, fmt.Sprintf("Invalid race ID: %d", raceID), nil
	}

	raceInfo := ri.races.GetRaceInfo(raceID)
	return true, "Valid race", raceInfo
}

// ApplyRacialBonuses applies racial stat bonuses to an entity
// This would integrate with the stat system when available
func (ri *RaceIntegration) ApplyRacialBonuses(entity RaceAware, stats map[string]*int16) {
	raceID := entity.GetRace()
	if !ri.races.IsValidRaceID(raceID) {
		return
	}

	// Get racial modifiers
	modifiers := ri.utils.GetRaceStatModifiers(raceID)

	// Apply modifiers to stats
	for statName, modifier := range modifiers {
		if statPtr, exists := stats[statName]; exists && statPtr != nil {
			*statPtr += int16(modifier)
		}
	}
}

// GetEntityRaceInfo returns comprehensive race information for an entity
func (ri *RaceIntegration) GetEntityRaceInfo(entity EntityWithRace) map[string]interface{} {
	info := make(map[string]interface{})

	// Basic entity info
	info["entity_id"] = entity.GetID()
	info["entity_name"] = entity.GetName()

	// Race information
	raceID := entity.GetRace()
	raceInfo := ri.races.GetRaceInfo(raceID)
	info["race"] = raceInfo

	// Additional race-specific info
	info["description"] = ri.utils.GetRaceDescription(raceID)
	info["starting_location"] = ri.utils.GetRaceStartingLocation(raceID)
	info["stat_modifiers"] = ri.utils.GetRaceStatModifiers(raceID)
	info["aliases"] = ri.utils.GetRaceAliases(raceID)
	info["compatible_races"] = ri.utils.GetCompatibleRaces(raceID)

	return info
}

// ChangeEntityRace changes an entity's race with validation
func (ri *RaceIntegration) ChangeEntityRace(entity RaceAware, newRaceID int8) error {
	if !ri.races.IsValidRaceID(newRaceID) {
		return fmt.Errorf("invalid race ID: %d", newRaceID)
	}

	oldRaceID := entity.GetRace()

	// Validate the race transition
	if valid, reason := ri.utils.ValidateRaceTransition(oldRaceID, newRaceID); !valid {
		return fmt.Errorf("race change not allowed: %s", reason)
	}

	// Perform the race change
	entity.SetRace(newRaceID)

	return nil
}

// GetRandomRaceForEntity returns a random race appropriate for an entity
func (ri *RaceIntegration) GetRandomRaceForEntity(alignment string) int8 {
	return ri.utils.GetRandomRaceByAlignment(alignment)
}

// CheckRaceCompatibility checks if two entities' races are compatible
func (ri *RaceIntegration) CheckRaceCompatibility(entity1, entity2 RaceAware) bool {
	race1 := entity1.GetRace()
	race2 := entity2.GetRace()

	if !ri.races.IsValidRaceID(race1) || !ri.races.IsValidRaceID(race2) {
		return false
	}

	// Same race is always compatible
	if race1 == race2 {
		return true
	}

	// Check alignment compatibility
	alignment1 := ri.races.GetRaceAlignment(race1)
	alignment2 := ri.races.GetRaceAlignment(race2)

	// Neutral races are compatible with everyone
	if alignment1 == AlignmentNeutral || alignment2 == AlignmentNeutral {
		return true
	}

	// Same alignment races are compatible
	return alignment1 == alignment2
}

// FormatEntityRace returns a formatted race name for an entity
func (ri *RaceIntegration) FormatEntityRace(entity RaceAware, format string) string {
	raceID := entity.GetRace()
	return ri.utils.FormatRaceName(raceID, format)
}

// GetEntityRaceAlignment returns an entity's race alignment
func (ri *RaceIntegration) GetEntityRaceAlignment(entity RaceAware) string {
	raceID := entity.GetRace()
	return ri.races.GetRaceAlignment(raceID)
}

// IsEntityGoodRace checks if an entity is a good-aligned race
func (ri *RaceIntegration) IsEntityGoodRace(entity RaceAware) bool {
	raceID := entity.GetRace()
	return ri.races.IsGoodRace(raceID)
}

// IsEntityEvilRace checks if an entity is an evil-aligned race
func (ri *RaceIntegration) IsEntityEvilRace(entity RaceAware) bool {
	raceID := entity.GetRace()
	return ri.races.IsEvilRace(raceID)
}

// IsEntityNeutralRace checks if an entity is a neutral race
func (ri *RaceIntegration) IsEntityNeutralRace(entity RaceAware) bool {
	raceID := entity.GetRace()
	return ri.races.IsNeutralRace(raceID)
}

// GetEntitiesByRace filters entities by race
func (ri *RaceIntegration) GetEntitiesByRace(entities []RaceAware, raceID int8) []RaceAware {
	result := make([]RaceAware, 0)

	for _, entity := range entities {
		if entity.GetRace() == raceID {
			result = append(result, entity)
		}
	}

	return result
}

// GetEntitiesByAlignment filters entities by race alignment
func (ri *RaceIntegration) GetEntitiesByAlignment(entities []RaceAware, alignment string) []RaceAware {
	result := make([]RaceAware, 0)

	for _, entity := range entities {
		entityAlignment := ri.GetEntityRaceAlignment(entity)
		if entityAlignment == alignment {
			result = append(result, entity)
		}
	}

	return result
}

// ValidateRaceForClass checks if a race/class combination is valid
func (ri *RaceIntegration) ValidateRaceForClass(raceID, classID int8) (bool, string) {
	if !ri.races.IsValidRaceID(raceID) {
		return false, "Invalid race"
	}

	// Use the utility function (which currently allows all combinations)
	if ri.utils.ValidateRaceForClass(raceID, classID) {
		return true, ""
	}

	raceName := ri.races.GetRaceNameCase(raceID)
	return false, fmt.Sprintf("Race %s cannot be class %d", raceName, classID)
}

// GetRaceStartingStats returns the starting stats for a race
func (ri *RaceIntegration) GetRaceStartingStats(raceID int8) map[string]int16 {
	baseStats := map[string]int16{
		"strength":     50,
		"stamina":      50,
		"agility":      50,
		"wisdom":       50,
		"intelligence": 50,
	}

	// Apply racial modifiers
	modifiers := ri.utils.GetRaceStatModifiers(raceID)
	for statName, modifier := range modifiers {
		if baseStat, exists := baseStats[statName]; exists {
			baseStats[statName] = baseStat + int16(modifier)
		}
	}

	return baseStats
}

// CreateRaceSpecificEntity creates entity data with race-specific properties
func (ri *RaceIntegration) CreateRaceSpecificEntity(raceID int8) map[string]interface{} {
	if !ri.races.IsValidRaceID(raceID) {
		return nil
	}

	entityData := make(map[string]interface{})

	// Basic race info
	entityData["race_id"] = raceID
	entityData["race_name"] = ri.races.GetRaceNameCase(raceID)
	entityData["alignment"] = ri.races.GetRaceAlignment(raceID)

	// Starting stats
	entityData["starting_stats"] = ri.GetRaceStartingStats(raceID)

	// Starting location
	entityData["starting_location"] = ri.utils.GetRaceStartingLocation(raceID)

	// Race description
	entityData["description"] = ri.utils.GetRaceDescription(raceID)

	return entityData
}

// GetRaceSelectionData returns data for race selection UI
func (ri *RaceIntegration) GetRaceSelectionData() map[string]interface{} {
	data := make(map[string]interface{})

	// All available races
	allRaces := ri.races.GetAllRaces()
	raceList := make([]map[string]interface{}, 0, len(allRaces))

	for raceID, friendlyName := range allRaces {
		raceData := map[string]interface{}{
			"id":          raceID,
			"name":        friendlyName,
			"alignment":   ri.races.GetRaceAlignment(raceID),
			"description": ri.utils.GetRaceDescription(raceID),
			"stats":       ri.GetRaceStartingStats(raceID),
		}
		raceList = append(raceList, raceData)
	}

	data["races"] = raceList
	data["statistics"] = ri.utils.GetRaceStatistics()

	return data
}

// Global race integration instance
var globalRaceIntegration *RaceIntegration

// GetGlobalRaceIntegration returns the global race integration helper
func GetGlobalRaceIntegration() *RaceIntegration {
	if globalRaceIntegration == nil {
		globalRaceIntegration = NewRaceIntegration()
	}
	return globalRaceIntegration
}
