package player

import (
	"eq2emu/internal/entity"
	"eq2emu/internal/quests"
	"eq2emu/internal/spells"
)

// GetQuest returns a quest by ID
func (p *Player) GetQuest(questID int32) *quests.Quest {
	p.playerQuestsMutex.RLock()
	defer p.playerQuestsMutex.RUnlock()

	if quest, exists := p.playerQuests[questID]; exists {
		return quest
	}
	return nil
}

// GetAnyQuest returns a quest from any list (active, completed, pending)
func (p *Player) GetAnyQuest(questID int32) *quests.Quest {
	p.playerQuestsMutex.RLock()
	defer p.playerQuestsMutex.RUnlock()

	// Check active quests
	if quest, exists := p.playerQuests[questID]; exists {
		return quest
	}

	// Check completed quests
	if quest, exists := p.completedQuests[questID]; exists {
		return quest
	}

	// Check pending quests
	if quest, exists := p.pendingQuests[questID]; exists {
		return quest
	}

	return nil
}

// GetCompletedQuest returns a completed quest by ID
func (p *Player) GetCompletedQuest(questID int32) *quests.Quest {
	p.playerQuestsMutex.RLock()
	defer p.playerQuestsMutex.RUnlock()

	if quest, exists := p.completedQuests[questID]; exists {
		return quest
	}
	return nil
}

// HasQuestBeenCompleted checks if a quest has been completed
func (p *Player) HasQuestBeenCompleted(questID int32) bool {
	return p.GetCompletedQuest(questID) != nil
}

// GetQuestCompletedCount returns how many times a quest has been completed
func (p *Player) GetQuestCompletedCount(questID int32) int32 {
	quest := p.GetCompletedQuest(questID)
	if quest != nil {
		return quest.GetCompleteCount()
	}
	return 0
}

// AddCompletedQuest adds a quest to the completed list
func (p *Player) AddCompletedQuest(quest *quests.Quest) {
	if quest == nil {
		return
	}

	p.playerQuestsMutex.Lock()
	defer p.playerQuestsMutex.Unlock()

	p.completedQuests[quest.GetQuestID()] = quest
}

// HasActiveQuest checks if a quest is currently active
func (p *Player) HasActiveQuest(questID int32) bool {
	p.playerQuestsMutex.RLock()
	defer p.playerQuestsMutex.RUnlock()

	_, exists := p.playerQuests[questID]
	return exists
}

// HasAnyQuest checks if player has quest in any state
func (p *Player) HasAnyQuest(questID int32) bool {
	return p.GetAnyQuest(questID) != nil
}

// GetPlayerQuests returns the active quest map
func (p *Player) GetPlayerQuests() map[int32]*quests.Quest {
	return p.playerQuests
}

// GetCompletedPlayerQuests returns the completed quest map
func (p *Player) GetCompletedPlayerQuests() map[int32]*quests.Quest {
	return p.completedQuests
}

// GetQuestIDs returns all active quest IDs
func (p *Player) GetQuestIDs() []int32 {
	p.playerQuestsMutex.RLock()
	defer p.playerQuestsMutex.RUnlock()

	ids := make([]int32, 0, len(p.playerQuests))
	for id := range p.playerQuests {
		ids = append(ids, id)
	}
	return ids
}

// RemoveQuest removes a quest from the player
func (p *Player) RemoveQuest(questID int32, deleteQuest bool) {
	p.playerQuestsMutex.Lock()
	defer p.playerQuestsMutex.Unlock()

	if quest, exists := p.playerQuests[questID]; exists {
		delete(p.playerQuests, questID)

		if deleteQuest {
			// TODO: Delete quest data
			_ = quest
		}
	}

	// TODO: Update quest journal
	// TODO: Remove quest items if needed
}

// AddQuestRequiredSpawn adds a spawn requirement for a quest
func (p *Player) AddQuestRequiredSpawn(spawn *entity.Spawn, questID int32) {
	if spawn == nil {
		return
	}

	p.playerSpawnQuestsRequiredMutex.Lock()
	defer p.playerSpawnQuestsRequiredMutex.Unlock()

	spawnID := spawn.GetDatabaseID()
	if p.playerSpawnQuestsRequired[spawnID] == nil {
		p.playerSpawnQuestsRequired[spawnID] = make([]int32, 0)
	}

	// Check if already added
	for _, id := range p.playerSpawnQuestsRequired[spawnID] {
		if id == questID {
			return
		}
	}

	p.playerSpawnQuestsRequired[spawnID] = append(p.playerSpawnQuestsRequired[spawnID], questID)
}

// AddHistoryRequiredSpawn adds a spawn requirement for history
func (p *Player) AddHistoryRequiredSpawn(spawn *entity.Spawn, eventID int32) {
	if spawn == nil {
		return
	}

	p.playerSpawnHistoryRequiredMutex.Lock()
	defer p.playerSpawnHistoryRequiredMutex.Unlock()

	spawnID := spawn.GetDatabaseID()
	if p.playerSpawnHistoryRequired[spawnID] == nil {
		p.playerSpawnHistoryRequired[spawnID] = make([]int32, 0)
	}

	// Check if already added
	for _, id := range p.playerSpawnHistoryRequired[spawnID] {
		if id == eventID {
			return
		}
	}

	p.playerSpawnHistoryRequired[spawnID] = append(p.playerSpawnHistoryRequired[spawnID], eventID)
}

// CheckQuestRequired checks if a spawn is required for any quest
func (p *Player) CheckQuestRequired(spawn *entity.Spawn) bool {
	if spawn == nil {
		return false
	}

	p.playerSpawnQuestsRequiredMutex.RLock()
	defer p.playerSpawnQuestsRequiredMutex.RUnlock()

	spawnID := spawn.GetDatabaseID()
	quests, exists := p.playerSpawnQuestsRequired[spawnID]
	return exists && len(quests) > 0
}

// GetQuestStepComplete checks if a quest step is complete
func (p *Player) GetQuestStepComplete(questID, stepID int32) bool {
	quest := p.GetQuest(questID)
	if quest != nil {
		return quest.GetQuestStepCompleted(stepID)
	}
	return false
}

// GetQuestStep returns the current quest step
func (p *Player) GetQuestStep(questID int32) int16 {
	quest := p.GetQuest(questID)
	if quest != nil {
		return quest.GetQuestStep()
	}
	return 0
}

// GetTaskGroupStep returns the current task group step
func (p *Player) GetTaskGroupStep(questID int32) int16 {
	quest := p.GetQuest(questID)
	if quest != nil {
		return quest.GetTaskGroup()
	}
	return 0
}

// SetStepComplete completes a quest step
func (p *Player) SetStepComplete(questID, step int32) *quests.Quest {
	quest := p.GetQuest(questID)
	if quest != nil {
		quest.SetStepComplete(step)
		// TODO: Check if quest is now complete
		// TODO: Send quest update
	}
	return quest
}

// AddStepProgress adds progress to a quest step
func (p *Player) AddStepProgress(questID, step, progress int32) *quests.Quest {
	quest := p.GetQuest(questID)
	if quest != nil {
		quest.AddStepProgress(step, progress)
		// TODO: Check if step is now complete
		// TODO: Send quest update
	}
	return quest
}

// GetStepProgress returns progress for a quest step
func (p *Player) GetStepProgress(questID, stepID int32) int32 {
	quest := p.GetQuest(questID)
	if quest != nil {
		return quest.GetStepProgress(stepID)
	}
	return 0
}

// CanReceiveQuest checks if player can receive a quest
func (p *Player) CanReceiveQuest(questID int32, ret *int8) bool {
	// TODO: Get quest from master list
	// quest := master_quest_list.GetQuest(questID)

	// Check if already has quest
	if p.HasAnyQuest(questID) {
		if ret != nil {
			*ret = 1 // Already has quest
		}
		return false
	}

	// TODO: Check prerequisites
	// - Level requirements
	// - Class requirements
	// - Race requirements
	// - Faction requirements
	// - Previous quest requirements

	return true
}

// GetQuestByPositionID returns a quest by its position in the journal
func (p *Player) GetQuestByPositionID(listPositionID int32) *quests.Quest {
	// TODO: Implement quest position tracking
	return nil
}

// SendQuestRequiredSpawns sends spawn updates for quest requirements
func (p *Player) SendQuestRequiredSpawns(questID int32) {
	// TODO: Send spawn visual updates for quest requirements
}

// SendHistoryRequiredSpawns sends spawn updates for history requirements
func (p *Player) SendHistoryRequiredSpawns(eventID int32) {
	// TODO: Send spawn visual updates for history events
}

// SendQuest sends quest data to client
func (p *Player) SendQuest(questID int32) {
	// TODO: Send quest journal packet
}

// UpdateQuestCompleteCount updates quest completion count
func (p *Player) UpdateQuestCompleteCount(questID int32) {
	quest := p.GetCompletedQuest(questID)
	if quest != nil {
		quest.IncrementCompleteCount()
		// TODO: Save to database
	}
}

// PendingQuestAcceptance handles pending quest rewards
func (p *Player) PendingQuestAcceptance(questID, itemID int32, questExists *bool) *quests.Quest {
	// TODO: Handle quest reward acceptance
	return nil
}

// AcceptQuestReward accepts a quest reward
func (p *Player) AcceptQuestReward(itemID, selectableItemID int32) bool {
	// TODO: Give quest rewards to player
	return false
}

// SendQuestStepUpdate sends a quest step update
func (p *Player) SendQuestStepUpdate(questID, questStepID int32, displayQuestHelper bool) bool {
	// TODO: Send quest step update packet
	return false
}

// GetQuestTemporaryRewards gets temporary quest rewards
func (p *Player) GetQuestTemporaryRewards(questID int32, items *[]*Item) {
	// TODO: Get temporary quest rewards
}

// AddQuestTemporaryReward adds a temporary quest reward
func (p *Player) AddQuestTemporaryReward(questID, itemID int32, itemCount int16) {
	// TODO: Add temporary quest reward
}

// UpdateQuestReward updates quest reward data
func (p *Player) UpdateQuestReward(questID int32, qrd *quests.QuestRewardData) bool {
	// TODO: Update quest reward
	return false
}

// CheckQuestsChatUpdate checks quests for chat updates
func (p *Player) CheckQuestsChatUpdate(spawn *entity.Spawn) []*quests.Quest {
	// TODO: Check if spawn chat updates any quests
	return nil
}

// CheckQuestsItemUpdate checks quests for item updates
func (p *Player) CheckQuestsItemUpdate(item *Item) []*quests.Quest {
	// TODO: Check if item updates any quests
	return nil
}

// CheckQuestsLocationUpdate checks quests for location updates
func (p *Player) CheckQuestsLocationUpdate() []*quests.Quest {
	// TODO: Check if current location updates any quests
	return nil
}

// CheckQuestsKillUpdate checks quests for kill updates
func (p *Player) CheckQuestsKillUpdate(spawn *entity.Spawn, update bool) []*quests.Quest {
	// TODO: Check if killing spawn updates any quests
	return nil
}

// HasQuestUpdateRequirement checks if spawn has quest update requirements
func (p *Player) HasQuestUpdateRequirement(spawn *entity.Spawn) bool {
	// TODO: Check if spawn updates any active quests
	return false
}

// CheckQuestsSpellUpdate checks quests for spell updates
func (p *Player) CheckQuestsSpellUpdate(spell *spells.Spell) []*quests.Quest {
	// TODO: Check if spell updates any quests
	return nil
}

// CheckQuestsCraftUpdate checks quests for crafting updates
func (p *Player) CheckQuestsCraftUpdate(item *Item, qty int32) {
	// TODO: Check if crafting updates any quests
}

// CheckQuestsHarvestUpdate checks quests for harvest updates
func (p *Player) CheckQuestsHarvestUpdate(item *Item, qty int32) {
	// TODO: Check if harvesting updates any quests
}

// CheckQuestsFailures checks for quest failures
func (p *Player) CheckQuestsFailures() []*quests.Quest {
	// TODO: Check if any quests have failed
	return nil
}

// CheckQuestRemoveFlag checks if spawn should have quest flag removed
func (p *Player) CheckQuestRemoveFlag(spawn *entity.Spawn) bool {
	// TODO: Check if quest flag should be removed from spawn
	return false
}

// CheckQuestFlag returns the quest flag for a spawn
func (p *Player) CheckQuestFlag(spawn *entity.Spawn) int8 {
	// TODO: Determine quest flag for spawn
	// 0 = no flag
	// 1 = quest giver
	// 2 = quest update
	// etc.
	return 0
}
