package quests

import "fmt"

// Prerequisite management methods for Quest

// SetPrereqLevel sets the minimum level requirement
func (q *Quest) SetPrereqLevel(level int8) {
	q.PrereqLevel = level
	q.SetSaveNeeded(true)
}

// SetPrereqTSLevel sets the minimum tradeskill level requirement
func (q *Quest) SetPrereqTSLevel(level int8) {
	q.PrereqTSLevel = level
	q.SetSaveNeeded(true)
}

// SetPrereqMaxLevel sets the maximum level requirement
func (q *Quest) SetPrereqMaxLevel(level int8) {
	q.PrereqMaxLevel = level
	q.SetSaveNeeded(true)
}

// SetPrereqMaxTSLevel sets the maximum tradeskill level requirement
func (q *Quest) SetPrereqMaxTSLevel(level int8) {
	q.PrereqMaxTSLevel = level
	q.SetSaveNeeded(true)
}

// AddPrereqClass adds a class prerequisite
func (q *Quest) AddPrereqClass(classID int8) {
	q.PrereqClasses = append(q.PrereqClasses, classID)
	q.SetSaveNeeded(true)
}

// AddPrereqTradeskillClass adds a tradeskill class prerequisite
func (q *Quest) AddPrereqTradeskillClass(classID int8) {
	q.PrereqTSClasses = append(q.PrereqTSClasses, classID)
	q.SetSaveNeeded(true)
}

// AddPrereqModelType adds a model type prerequisite
func (q *Quest) AddPrereqModelType(modelType int16) {
	q.PrereqModelTypes = append(q.PrereqModelTypes, modelType)
	q.SetSaveNeeded(true)
}

// AddPrereqRace adds a race prerequisite
func (q *Quest) AddPrereqRace(race int8) {
	q.PrereqRaces = append(q.PrereqRaces, race)
	q.SetSaveNeeded(true)
}

// AddPrereqQuest adds a quest prerequisite
func (q *Quest) AddPrereqQuest(questID int32) {
	q.PrereqQuests = append(q.PrereqQuests, questID)
	q.SetSaveNeeded(true)
}

// AddPrereqFaction adds a faction prerequisite
func (q *Quest) AddPrereqFaction(factionID int32, min, max int32) {
	faction := NewQuestFactionPrereq(factionID, min, max)
	q.PrereqFactions = append(q.PrereqFactions, faction)
	q.SetSaveNeeded(true)
}

// RemovePrereqClass removes a class prerequisite
func (q *Quest) RemovePrereqClass(classID int8) bool {
	for i, class := range q.PrereqClasses {
		if class == classID {
			q.PrereqClasses = append(q.PrereqClasses[:i], q.PrereqClasses[i+1:]...)
			q.SetSaveNeeded(true)
			return true
		}
	}
	return false
}

// RemovePrereqTradeskillClass removes a tradeskill class prerequisite
func (q *Quest) RemovePrereqTradeskillClass(classID int8) bool {
	for i, class := range q.PrereqTSClasses {
		if class == classID {
			q.PrereqTSClasses = append(q.PrereqTSClasses[:i], q.PrereqTSClasses[i+1:]...)
			q.SetSaveNeeded(true)
			return true
		}
	}
	return false
}

// RemovePrereqModelType removes a model type prerequisite
func (q *Quest) RemovePrereqModelType(modelType int16) bool {
	for i, model := range q.PrereqModelTypes {
		if model == modelType {
			q.PrereqModelTypes = append(q.PrereqModelTypes[:i], q.PrereqModelTypes[i+1:]...)
			q.SetSaveNeeded(true)
			return true
		}
	}
	return false
}

// RemovePrereqRace removes a race prerequisite
func (q *Quest) RemovePrereqRace(race int8) bool {
	for i, r := range q.PrereqRaces {
		if r == race {
			q.PrereqRaces = append(q.PrereqRaces[:i], q.PrereqRaces[i+1:]...)
			q.SetSaveNeeded(true)
			return true
		}
	}
	return false
}

// RemovePrereqQuest removes a quest prerequisite
func (q *Quest) RemovePrereqQuest(questID int32) bool {
	for i, quest := range q.PrereqQuests {
		if quest == questID {
			q.PrereqQuests = append(q.PrereqQuests[:i], q.PrereqQuests[i+1:]...)
			q.SetSaveNeeded(true)
			return true
		}
	}
	return false
}

// RemovePrereqFaction removes a faction prerequisite
func (q *Quest) RemovePrereqFaction(factionID int32) bool {
	for i, faction := range q.PrereqFactions {
		if faction.FactionID == factionID {
			q.PrereqFactions = append(q.PrereqFactions[:i], q.PrereqFactions[i+1:]...)
			q.SetSaveNeeded(true)
			return true
		}
	}
	return false
}

// HasPrereqClass checks if a class is a prerequisite
func (q *Quest) HasPrereqClass(classID int8) bool {
	for _, class := range q.PrereqClasses {
		if class == classID {
			return true
		}
	}
	return false
}

// HasPrereqTradeskillClass checks if a tradeskill class is a prerequisite
func (q *Quest) HasPrereqTradeskillClass(classID int8) bool {
	for _, class := range q.PrereqTSClasses {
		if class == classID {
			return true
		}
	}
	return false
}

// HasPrereqModelType checks if a model type is a prerequisite
func (q *Quest) HasPrereqModelType(modelType int16) bool {
	for _, model := range q.PrereqModelTypes {
		if model == modelType {
			return true
		}
	}
	return false
}

// HasPrereqRace checks if a race is a prerequisite
func (q *Quest) HasPrereqRace(race int8) bool {
	for _, r := range q.PrereqRaces {
		if r == race {
			return true
		}
	}
	return false
}

// HasPrereqQuest checks if a quest is a prerequisite
func (q *Quest) HasPrereqQuest(questID int32) bool {
	for _, quest := range q.PrereqQuests {
		if quest == questID {
			return true
		}
	}
	return false
}

// HasPrereqFaction checks if a faction is a prerequisite
func (q *Quest) HasPrereqFaction(factionID int32) bool {
	for _, faction := range q.PrereqFactions {
		if faction.FactionID == factionID {
			return true
		}
	}
	return false
}

// GetPrereqFaction returns the faction prerequisite for a given faction ID
func (q *Quest) GetPrereqFaction(factionID int32) *QuestFactionPrereq {
	for _, faction := range q.PrereqFactions {
		if faction.FactionID == factionID {
			return faction
		}
	}
	return nil
}

// ClearAllPrerequisites removes all prerequisites
func (q *Quest) ClearAllPrerequisites() {
	q.PrereqLevel = DefaultPrereqLevel
	q.PrereqTSLevel = 0
	q.PrereqMaxLevel = 0
	q.PrereqMaxTSLevel = 0
	q.PrereqFactions = q.PrereqFactions[:0]
	q.PrereqRaces = q.PrereqRaces[:0]
	q.PrereqModelTypes = q.PrereqModelTypes[:0]
	q.PrereqClasses = q.PrereqClasses[:0]
	q.PrereqTSClasses = q.PrereqTSClasses[:0]
	q.PrereqQuests = q.PrereqQuests[:0]
	q.SetSaveNeeded(true)
}

// Prerequisite validation methods

// ValidatePrerequisites validates all quest prerequisites
func (q *Quest) ValidatePrerequisites() error {
	// Validate level requirements
	if q.PrereqLevel < 1 || q.PrereqLevel > 100 {
		return fmt.Errorf("prerequisite level must be between 1 and 100")
	}

	if q.PrereqTSLevel < 0 || q.PrereqTSLevel > 100 {
		return fmt.Errorf("prerequisite tradeskill level must be between 0 and 100")
	}

	if q.PrereqMaxLevel > 0 && q.PrereqMaxLevel < q.PrereqLevel {
		return fmt.Errorf("prerequisite max level cannot be less than min level")
	}

	if q.PrereqMaxTSLevel > 0 && q.PrereqMaxTSLevel < q.PrereqTSLevel {
		return fmt.Errorf("prerequisite max tradeskill level cannot be less than min tradeskill level")
	}

	// Validate class prerequisites
	if err := q.validateClassPrerequisites(); err != nil {
		return err
	}

	// Validate race prerequisites
	if err := q.validateRacePrerequisites(); err != nil {
		return err
	}

	// Validate faction prerequisites
	if err := q.validateFactionPrerequisites(); err != nil {
		return err
	}

	return nil
}

// validateClassPrerequisites validates class prerequisites
func (q *Quest) validateClassPrerequisites() error {
	// Check for duplicate classes
	classMap := make(map[int8]bool)
	for _, classID := range q.PrereqClasses {
		if classMap[classID] {
			return fmt.Errorf("duplicate class prerequisite: %d", classID)
		}
		classMap[classID] = true

		// Validate class ID range (basic validation)
		if classID < 1 || classID > 100 {
			return fmt.Errorf("invalid class ID in prerequisites: %d", classID)
		}
	}

	// Check for duplicate tradeskill classes
	tsClassMap := make(map[int8]bool)
	for _, classID := range q.PrereqTSClasses {
		if tsClassMap[classID] {
			return fmt.Errorf("duplicate tradeskill class prerequisite: %d", classID)
		}
		tsClassMap[classID] = true

		// Validate tradeskill class ID range
		if classID < 1 || classID > 100 {
			return fmt.Errorf("invalid tradeskill class ID in prerequisites: %d", classID)
		}
	}

	return nil
}

// validateRacePrerequisites validates race prerequisites
func (q *Quest) validateRacePrerequisites() error {
	// Check for duplicate races
	raceMap := make(map[int8]bool)
	for _, race := range q.PrereqRaces {
		if raceMap[race] {
			return fmt.Errorf("duplicate race prerequisite: %d", race)
		}
		raceMap[race] = true

		// Validate race ID range
		if race < 1 || race > 50 {
			return fmt.Errorf("invalid race ID in prerequisites: %d", race)
		}
	}

	// Check for duplicate model types
	modelMap := make(map[int16]bool)
	for _, modelType := range q.PrereqModelTypes {
		if modelMap[modelType] {
			return fmt.Errorf("duplicate model type prerequisite: %d", modelType)
		}
		modelMap[modelType] = true

		// Validate model type range
		if modelType < 1 {
			return fmt.Errorf("invalid model type in prerequisites: %d", modelType)
		}
	}

	return nil
}

// validateFactionPrerequisites validates faction prerequisites
func (q *Quest) validateFactionPrerequisites() error {
	// Check for duplicate factions and validate ranges
	factionMap := make(map[int32]bool)
	for _, faction := range q.PrereqFactions {
		if factionMap[faction.FactionID] {
			return fmt.Errorf("duplicate faction prerequisite: %d", faction.FactionID)
		}
		factionMap[faction.FactionID] = true

		// Validate faction ID
		if faction.FactionID <= 0 {
			return fmt.Errorf("invalid faction ID in prerequisites: %d", faction.FactionID)
		}

		// Validate faction value ranges
		if faction.Min < -50000 || faction.Min > 50000 {
			return fmt.Errorf("faction %d min value out of range: %d", faction.FactionID, faction.Min)
		}

		if faction.Max < -50000 || faction.Max > 50000 {
			return fmt.Errorf("faction %d max value out of range: %d", faction.FactionID, faction.Max)
		}

		// Check min/max relationship
		if faction.Max != 0 && faction.Max < faction.Min {
			return fmt.Errorf("faction %d max value cannot be less than min value", faction.FactionID)
		}
	}

	// Check for duplicate quest prerequisites
	questMap := make(map[int32]bool)
	for _, questID := range q.PrereqQuests {
		if questMap[questID] {
			return fmt.Errorf("duplicate quest prerequisite: %d", questID)
		}
		questMap[questID] = true

		// Don't allow self-reference
		if questID == q.ID {
			return fmt.Errorf("quest cannot be a prerequisite of itself")
		}

		// Validate quest ID
		if questID <= 0 {
			return fmt.Errorf("invalid quest ID in prerequisites: %d", questID)
		}
	}

	return nil
}
