package titles

import (
	"fmt"
	"time"
)

// AchievementIntegration handles title granting from achievements
type AchievementIntegration struct {
	titleManager *TitleManager
}

// NewAchievementIntegration creates a new achievement integration handler
func NewAchievementIntegration(titleManager *TitleManager) *AchievementIntegration {
	return &AchievementIntegration{
		titleManager: titleManager,
	}
}

// OnAchievementCompleted is called when a player completes an achievement
func (ai *AchievementIntegration) OnAchievementCompleted(playerID int32, achievementID uint32) error {
	return ai.titleManager.ProcessAchievementCompletion(playerID, achievementID)
}

// QuestIntegration handles title granting from quest completion
type QuestIntegration struct {
	titleManager *TitleManager
	questTitles  map[uint32]int32 // Maps quest ID to title ID
}

// NewQuestIntegration creates a new quest integration handler
func NewQuestIntegration(titleManager *TitleManager) *QuestIntegration {
	qi := &QuestIntegration{
		titleManager: titleManager,
		questTitles:  make(map[uint32]int32),
	}

	// Initialize quest-to-title mappings
	qi.initializeQuestTitles()

	return qi
}

// initializeQuestTitles sets up quest-to-title relationships
func (qi *QuestIntegration) initializeQuestTitles() {
	// TODO: Load quest-title mappings from database or configuration
	// These would be examples of quest rewards that grant titles

	// Example mappings (these would come from quest definitions):
	// qi.questTitles[1001] = heroTitleID     // "Hero of Qeynos" from major storyline
	// qi.questTitles[2001] = explorerTitleID // "Explorer" from exploration quest
	// qi.questTitles[3001] = merchantTitleID // "Master Merchant" from trading quest
}

// OnQuestCompleted is called when a player completes a quest
func (qi *QuestIntegration) OnQuestCompleted(playerID int32, questID uint32) error {
	titleID, exists := qi.questTitles[questID]
	if !exists {
		return nil // Quest doesn't grant a title
	}

	return qi.titleManager.GrantTitle(playerID, titleID, 0, questID)
}

// AddQuestTitleMapping adds a quest-to-title relationship
func (qi *QuestIntegration) AddQuestTitleMapping(questID uint32, titleID int32) {
	qi.questTitles[questID] = titleID
}

// RemoveQuestTitleMapping removes a quest-to-title relationship
func (qi *QuestIntegration) RemoveQuestTitleMapping(questID uint32) {
	delete(qi.questTitles, questID)
}

// LevelIntegration handles title granting based on character level
type LevelIntegration struct {
	titleManager *TitleManager
	levelTitles  map[int32]int32 // Maps level to title ID
}

// NewLevelIntegration creates a new level integration handler
func NewLevelIntegration(titleManager *TitleManager) *LevelIntegration {
	li := &LevelIntegration{
		titleManager: titleManager,
		levelTitles:  make(map[int32]int32),
	}

	// Initialize level-based titles
	li.initializeLevelTitles()

	return li
}

// initializeLevelTitles sets up level milestone titles
func (li *LevelIntegration) initializeLevelTitles() {
	// TODO: Create and register level milestone titles
	// These would be created in the title manager and their IDs stored here

	// Example level titles:
	// li.levelTitles[10] = noviceTitleID    // "Novice" at level 10
	// li.levelTitles[25] = adeptTitleID     // "Adept" at level 25
	// li.levelTitles[50] = veteranTitleID   // "Veteran" at level 50
	// li.levelTitles[80] = masterTitleID    // "Master" at level 80
	// li.levelTitles[90] = championTitleID  // "Champion" at level 90
}

// OnLevelUp is called when a player levels up
func (li *LevelIntegration) OnLevelUp(playerID, newLevel int32) error {
	titleID, exists := li.levelTitles[newLevel]
	if !exists {
		return nil // No title for this level
	}

	return li.titleManager.GrantTitle(playerID, titleID, 0, 0)
}

// GuildIntegration handles title granting from guild activities
type GuildIntegration struct {
	titleManager *TitleManager
}

// NewGuildIntegration creates a new guild integration handler
func NewGuildIntegration(titleManager *TitleManager) *GuildIntegration {
	return &GuildIntegration{
		titleManager: titleManager,
	}
}

// OnGuildRankChanged is called when a player's guild rank changes
func (gi *GuildIntegration) OnGuildRankChanged(playerID int32, guildID, newRank int32) error {
	// TODO: Implement guild rank titles
	// Different guild ranks could grant different titles

	// Example: Guild leaders get "Guild Leader" title
	// if newRank == GUILD_RANK_LEADER {
	//     return gi.titleManager.GrantTitle(playerID, guildLeaderTitleID, 0, 0)
	// }

	return nil
}

// OnGuildAchievement is called when a guild completes an achievement
func (gi *GuildIntegration) OnGuildAchievement(guildID int32, achievementID uint32, memberIDs []int32) error {
	// TODO: Implement guild achievement titles
	// Guild achievements could grant titles to all participating members

	// Example: Grant title to all guild members who participated
	// for _, memberID := range memberIDs {
	//     err := gi.titleManager.GrantTitle(memberID, guildAchievementTitleID, achievementID, 0)
	//     if err != nil {
	//         // Log error but continue processing other members
	//     }
	// }

	return nil
}

// PvPIntegration handles title granting from PvP activities
type PvPIntegration struct {
	titleManager *TitleManager
	pvpStats     map[int32]*PvPStats // Track PvP statistics per player
}

// PvPStats tracks player PvP statistics for title eligibility
type PvPStats struct {
	PlayerKills   int32
	PlayerDeaths  int32
	HonorPoints   int32
	LastKillTime  time.Time
	KillStreak    int32
	MaxKillStreak int32
}

// NewPvPIntegration creates a new PvP integration handler
func NewPvPIntegration(titleManager *TitleManager) *PvPIntegration {
	return &PvPIntegration{
		titleManager: titleManager,
		pvpStats:     make(map[int32]*PvPStats),
	}
}

// OnPlayerKill is called when a player kills another player
func (pi *PvPIntegration) OnPlayerKill(killerID, victimID int32, honorGained int32) error {
	// Update killer stats
	killerStats := pi.getOrCreateStats(killerID)
	killerStats.PlayerKills++
	killerStats.HonorPoints += honorGained
	killerStats.LastKillTime = time.Now()
	killerStats.KillStreak++

	if killerStats.KillStreak > killerStats.MaxKillStreak {
		killerStats.MaxKillStreak = killerStats.KillStreak
	}

	// Update victim stats
	victimStats := pi.getOrCreateStats(victimID)
	victimStats.PlayerDeaths++
	victimStats.KillStreak = 0 // Reset kill streak on death

	// Check for PvP milestone titles
	return pi.checkPvPTitles(killerID, killerStats)
}

// getOrCreateStats gets or creates PvP stats for a player
func (pi *PvPIntegration) getOrCreateStats(playerID int32) *PvPStats {
	stats, exists := pi.pvpStats[playerID]
	if !exists {
		stats = &PvPStats{}
		pi.pvpStats[playerID] = stats
	}
	return stats
}

// checkPvPTitles checks if player qualifies for any PvP titles
func (pi *PvPIntegration) checkPvPTitles(playerID int32, stats *PvPStats) error {
	// TODO: Implement PvP title thresholds and grant appropriate titles

	// Example PvP title thresholds:
	// if stats.PlayerKills >= 100 && stats.PlayerKills < 500 {
	//     pi.titleManager.GrantTitle(playerID, slayerTitleID, 0, 0)
	// } else if stats.PlayerKills >= 500 && stats.PlayerKills < 1000 {
	//     pi.titleManager.GrantTitle(playerID, killerTitleID, 0, 0)
	// } else if stats.PlayerKills >= 1000 {
	//     pi.titleManager.GrantTitle(playerID, warlordTitleID, 0, 0)
	// }

	// if stats.MaxKillStreak >= 10 {
	//     pi.titleManager.GrantTitle(playerID, unstoppableTitleID, 0, 0)
	// }

	return nil
}

// EventIntegration handles title granting from special events
type EventIntegration struct {
	titleManager *TitleManager
	activeEvents map[string]*Event // Active events by name
	eventTitles  map[string]int32  // Maps event name to title ID
}

// Event represents a time-limited server event
type Event struct {
	Name        string
	StartTime   time.Time
	EndTime     time.Time
	IsActive    bool
	Description string
	TitleID     int32 // Title granted for participation
}

// NewEventIntegration creates a new event integration handler
func NewEventIntegration(titleManager *TitleManager) *EventIntegration {
	return &EventIntegration{
		titleManager: titleManager,
		activeEvents: make(map[string]*Event),
		eventTitles:  make(map[string]int32),
	}
}

// StartEvent activates a special event
func (ei *EventIntegration) StartEvent(name, description string, duration time.Duration, titleID int32) error {
	event := &Event{
		Name:        name,
		StartTime:   time.Now(),
		EndTime:     time.Now().Add(duration),
		IsActive:    true,
		Description: description,
		TitleID:     titleID,
	}

	ei.activeEvents[name] = event
	ei.eventTitles[name] = titleID

	return nil
}

// EndEvent deactivates a special event
func (ei *EventIntegration) EndEvent(name string) error {
	event, exists := ei.activeEvents[name]
	if !exists {
		return fmt.Errorf("event %s does not exist", name)
	}

	event.IsActive = false
	delete(ei.activeEvents, name)

	return nil
}

// OnEventParticipation is called when a player participates in an event
func (ei *EventIntegration) OnEventParticipation(playerID int32, eventName string) error {
	event, exists := ei.activeEvents[eventName]
	if !exists || !event.IsActive {
		return fmt.Errorf("event %s is not active", eventName)
	}

	// Check if event is still within time bounds
	now := time.Now()
	if now.Before(event.StartTime) || now.After(event.EndTime) {
		event.IsActive = false
		delete(ei.activeEvents, eventName)
		return fmt.Errorf("event %s has expired", eventName)
	}

	// Grant event participation title
	if event.TitleID > 0 {
		return ei.titleManager.GrantTitle(playerID, event.TitleID, 0, 0)
	}

	return nil
}

// GetActiveEvents returns all currently active events
func (ei *EventIntegration) GetActiveEvents() []*Event {
	result := make([]*Event, 0, len(ei.activeEvents))

	for _, event := range ei.activeEvents {
		// Check if event is still valid
		now := time.Now()
		if now.After(event.EndTime) {
			event.IsActive = false
			continue
		}

		if event.IsActive {
			result = append(result, event)
		}
	}

	return result
}

// TitleEarnedCallback represents a callback function called when a title is earned
type TitleEarnedCallback func(playerID, titleID int32, source string)

// IntegrationManager coordinates all title integration systems
type IntegrationManager struct {
	titleManager           *TitleManager
	achievementIntegration *AchievementIntegration
	questIntegration       *QuestIntegration
	levelIntegration       *LevelIntegration
	guildIntegration       *GuildIntegration
	pvpIntegration         *PvPIntegration
	eventIntegration       *EventIntegration

	callbacks []TitleEarnedCallback
}

// NewIntegrationManager creates a comprehensive integration manager
func NewIntegrationManager(titleManager *TitleManager) *IntegrationManager {
	return &IntegrationManager{
		titleManager:           titleManager,
		achievementIntegration: NewAchievementIntegration(titleManager),
		questIntegration:       NewQuestIntegration(titleManager),
		levelIntegration:       NewLevelIntegration(titleManager),
		guildIntegration:       NewGuildIntegration(titleManager),
		pvpIntegration:         NewPvPIntegration(titleManager),
		eventIntegration:       NewEventIntegration(titleManager),
		callbacks:              make([]TitleEarnedCallback, 0),
	}
}

// AddTitleEarnedCallback adds a callback to be notified when titles are earned
func (im *IntegrationManager) AddTitleEarnedCallback(callback TitleEarnedCallback) {
	im.callbacks = append(im.callbacks, callback)
}

// NotifyTitleEarned calls all registered callbacks when a title is earned
func (im *IntegrationManager) NotifyTitleEarned(playerID, titleID int32, source string) {
	for _, callback := range im.callbacks {
		callback(playerID, titleID, source)
	}
}

// GetAchievementIntegration returns the achievement integration handler
func (im *IntegrationManager) GetAchievementIntegration() *AchievementIntegration {
	return im.achievementIntegration
}

// GetQuestIntegration returns the quest integration handler
func (im *IntegrationManager) GetQuestIntegration() *QuestIntegration {
	return im.questIntegration
}

// GetLevelIntegration returns the level integration handler
func (im *IntegrationManager) GetLevelIntegration() *LevelIntegration {
	return im.levelIntegration
}

// GetGuildIntegration returns the guild integration handler
func (im *IntegrationManager) GetGuildIntegration() *GuildIntegration {
	return im.guildIntegration
}

// GetPvPIntegration returns the PvP integration handler
func (im *IntegrationManager) GetPvPIntegration() *PvPIntegration {
	return im.pvpIntegration
}

// GetEventIntegration returns the event integration handler
func (im *IntegrationManager) GetEventIntegration() *EventIntegration {
	return im.eventIntegration
}
