package classes

import (
	"fmt"
)

// ClassAware interface for entities that have class information
type ClassAware interface {
	GetClass() int8
	SetClass(int8)
}

// EntityWithClass interface extends ClassAware with additional entity properties
type EntityWithClass interface {
	ClassAware
	GetID() int32
	GetName() string
	GetLevel() int8
}

// ClassIntegration provides class-related functionality for other systems
type ClassIntegration struct {
	classes *Classes
	utils   *ClassUtils
}

// NewClassIntegration creates a new class integration helper
func NewClassIntegration() *ClassIntegration {
	return &ClassIntegration{
		classes: GetGlobalClasses(),
		utils:   NewClassUtils(),
	}
}

// ValidateEntityClass validates an entity's class and provides detailed information
func (ci *ClassIntegration) ValidateEntityClass(entity ClassAware) (bool, string, map[string]interface{}) {
	classID := entity.GetClass()

	if !ci.classes.IsValidClassID(classID) {
		return false, fmt.Sprintf("Invalid class ID: %d", classID), nil
	}

	classInfo := ci.classes.GetClassInfo(classID)
	return true, "Valid class", classInfo
}

// GetEntityClassInfo returns comprehensive class information for an entity
func (ci *ClassIntegration) GetEntityClassInfo(entity EntityWithClass) map[string]interface{} {
	info := make(map[string]interface{})

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

	// Class information
	classID := entity.GetClass()
	classInfo := ci.classes.GetClassInfo(classID)
	info["class"] = classInfo

	// Additional class-specific info
	info["description"] = ci.utils.GetClassDescription(classID)
	info["eq_class_name"] = ci.utils.GetEQClassName(classID, entity.GetLevel())
	info["progression"] = ci.utils.GetClassProgression(classID)
	info["aliases"] = ci.utils.GetClassAliases(classID)
	info["is_base_class"] = ci.utils.IsBaseClass(classID)
	info["is_secondary_base"] = ci.utils.IsSecondaryBaseClass(classID)

	return info
}

// ChangeEntityClass changes an entity's class with validation
func (ci *ClassIntegration) ChangeEntityClass(entity ClassAware, newClassID int8) error {
	if !ci.classes.IsValidClassID(newClassID) {
		return fmt.Errorf("invalid class ID: %d", newClassID)
	}

	oldClassID := entity.GetClass()

	// Validate the class transition
	if valid, reason := ci.utils.ValidateClassTransition(oldClassID, newClassID); !valid {
		return fmt.Errorf("class change not allowed: %s", reason)
	}

	// Perform the class change
	entity.SetClass(newClassID)

	return nil
}

// GetRandomClassForEntity returns a random class appropriate for an entity
func (ci *ClassIntegration) GetRandomClassForEntity(classType string) int8 {
	return ci.utils.GetRandomClassByType(classType)
}

// CheckClassCompatibility checks if two entities' classes are compatible for grouping
func (ci *ClassIntegration) CheckClassCompatibility(entity1, entity2 ClassAware) bool {
	class1 := entity1.GetClass()
	class2 := entity2.GetClass()

	if !ci.classes.IsValidClassID(class1) || !ci.classes.IsValidClassID(class2) {
		return false
	}

	// Same class is always compatible
	if class1 == class2 {
		return true
	}

	// Check if they share the same base class (good for grouping)
	// base1 := ci.classes.GetBaseClass(class1)
	// base2 := ci.classes.GetBaseClass(class2)

	// Different base classes can group together (provides diversity)
	// Same base class provides synergy
	return true // For now, all classes are compatible for grouping
}

// FormatEntityClass returns a formatted class name for an entity
func (ci *ClassIntegration) FormatEntityClass(entity EntityWithClass, format string) string {
	classID := entity.GetClass()
	level := entity.GetLevel()

	switch format {
	case "eq":
		return ci.utils.GetEQClassName(classID, level)
	default:
		return ci.utils.FormatClassName(classID, format)
	}
}

// GetEntityBaseClass returns an entity's base class
func (ci *ClassIntegration) GetEntityBaseClass(entity ClassAware) int8 {
	classID := entity.GetClass()
	return ci.classes.GetBaseClass(classID)
}

// GetEntitySecondaryBaseClass returns an entity's secondary base class
func (ci *ClassIntegration) GetEntitySecondaryBaseClass(entity ClassAware) int8 {
	classID := entity.GetClass()
	return ci.classes.GetSecondaryBaseClass(classID)
}

// IsEntityAdventureClass checks if an entity has an adventure class
func (ci *ClassIntegration) IsEntityAdventureClass(entity ClassAware) bool {
	classID := entity.GetClass()
	return ci.classes.IsAdventureClass(classID)
}

// IsEntityTradeskillClass checks if an entity has a tradeskill class
func (ci *ClassIntegration) IsEntityTradeskillClass(entity ClassAware) bool {
	classID := entity.GetClass()
	return ci.classes.IsTradeskillClass(classID)
}

// GetEntitiesByClass filters entities by class
func (ci *ClassIntegration) GetEntitiesByClass(entities []ClassAware, classID int8) []ClassAware {
	result := make([]ClassAware, 0)

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

	return result
}

// GetEntitiesByBaseClass filters entities by base class
func (ci *ClassIntegration) GetEntitiesByBaseClass(entities []ClassAware, baseClassID int8) []ClassAware {
	result := make([]ClassAware, 0)

	for _, entity := range entities {
		if ci.GetEntityBaseClass(entity) == baseClassID {
			result = append(result, entity)
		}
	}

	return result
}

// GetEntitiesByClassType filters entities by class type (adventure/tradeskill)
func (ci *ClassIntegration) GetEntitiesByClassType(entities []ClassAware, classType string) []ClassAware {
	result := make([]ClassAware, 0)

	for _, entity := range entities {
		classID := entity.GetClass()
		if ci.classes.GetClassType(classID) == classType {
			result = append(result, entity)
		}
	}

	return result
}

// ValidateClassForRace checks if a class/race combination is valid
func (ci *ClassIntegration) ValidateClassForRace(classID, raceID int8) (bool, string) {
	if !ci.classes.IsValidClassID(classID) {
		return false, "Invalid class"
	}

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

	className := ci.classes.GetClassNameCase(classID)
	return false, fmt.Sprintf("Class %s cannot be race %d", className, raceID)
}

// GetClassStartingStats returns the starting stats for a class
func (ci *ClassIntegration) GetClassStartingStats(classID int8) map[string]int16 {
	// Base stats that all classes start with
	baseStats := map[string]int16{
		"strength":     50,
		"stamina":      50,
		"agility":      50,
		"wisdom":       50,
		"intelligence": 50,
	}

	// Apply class modifiers based on class type and role
	switch ci.classes.GetBaseClass(classID) {
	case ClassFighter:
		baseStats["strength"] += 5
		baseStats["stamina"] += 5
		baseStats["intelligence"] -= 3
	case ClassPriest:
		baseStats["wisdom"] += 5
		baseStats["intelligence"] += 3
		baseStats["strength"] -= 2
	case ClassMage:
		baseStats["intelligence"] += 5
		baseStats["wisdom"] += 3
		baseStats["strength"] -= 3
		baseStats["stamina"] -= 2
	case ClassScout:
		baseStats["agility"] += 5
		baseStats["stamina"] += 3
		baseStats["wisdom"] -= 2
	}

	// Fine-tune for specific secondary base classes
	switch ci.classes.GetSecondaryBaseClass(classID) {
	case ClassWarrior:
		baseStats["strength"] += 2
		baseStats["stamina"] += 2
	case ClassBrawler:
		baseStats["agility"] += 2
		baseStats["strength"] += 1
	case ClassCrusader:
		baseStats["wisdom"] += 2
		baseStats["strength"] += 1
	case ClassCleric:
		baseStats["wisdom"] += 3
	case ClassDruid:
		baseStats["wisdom"] += 2
		baseStats["intelligence"] += 1
	case ClassShaman:
		baseStats["wisdom"] += 2
		baseStats["stamina"] += 1
	case ClassSorcerer:
		baseStats["intelligence"] += 3
	case ClassEnchanter:
		baseStats["intelligence"] += 2
		baseStats["agility"] += 1
	case ClassSummoner:
		baseStats["intelligence"] += 2
		baseStats["wisdom"] += 1
	case ClassRogue:
		baseStats["agility"] += 3
	case ClassBard:
		baseStats["agility"] += 2
		baseStats["intelligence"] += 1
	case ClassPredator:
		baseStats["agility"] += 2
		baseStats["stamina"] += 1
	}

	return baseStats
}

// CreateClassSpecificEntity creates entity data with class-specific properties
func (ci *ClassIntegration) CreateClassSpecificEntity(classID int8) map[string]interface{} {
	if !ci.classes.IsValidClassID(classID) {
		return nil
	}

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

	// Basic class info
	entityData["class_id"] = classID
	entityData["class_name"] = ci.classes.GetClassNameCase(classID)
	entityData["class_type"] = ci.classes.GetClassType(classID)

	// Starting stats
	entityData["starting_stats"] = ci.GetClassStartingStats(classID)

	// Class progression
	entityData["progression"] = ci.utils.GetClassProgression(classID)

	// Class description
	entityData["description"] = ci.utils.GetClassDescription(classID)

	// Role information
	entityData["base_class"] = ci.classes.GetBaseClass(classID)
	entityData["secondary_base_class"] = ci.classes.GetSecondaryBaseClass(classID)

	return entityData
}

// GetClassSelectionData returns data for class selection UI
func (ci *ClassIntegration) GetClassSelectionData() map[string]interface{} {
	data := make(map[string]interface{})

	// All available adventure classes (exclude tradeskill for character creation)
	allClasses := ci.classes.GetAllClasses()
	adventureClasses := make([]map[string]interface{}, 0)

	for classID, displayName := range allClasses {
		if ci.classes.IsAdventureClass(classID) {
			classData := map[string]interface{}{
				"id":                   classID,
				"name":                 displayName,
				"type":                 ci.classes.GetClassType(classID),
				"description":          ci.utils.GetClassDescription(classID),
				"base_class":           ci.classes.GetBaseClass(classID),
				"secondary_base_class": ci.classes.GetSecondaryBaseClass(classID),
				"starting_stats":       ci.GetClassStartingStats(classID),
				"progression":          ci.utils.GetClassProgression(classID),
				"is_base_class":        ci.utils.IsBaseClass(classID),
			}
			adventureClasses = append(adventureClasses, classData)
		}
	}

	data["adventure_classes"] = adventureClasses
	data["statistics"] = ci.utils.GetClassStatistics()

	return data
}

// Global class integration instance
var globalClassIntegration *ClassIntegration

// GetGlobalClassIntegration returns the global class integration helper
func GetGlobalClassIntegration() *ClassIntegration {
	if globalClassIntegration == nil {
		globalClassIntegration = NewClassIntegration()
	}
	return globalClassIntegration
}
