package alt_advancement

import (
	"sync"
	"time"
)

// AltAdvanceData represents an Alternate Advancement node
type AltAdvanceData struct {
	// Core identification
	SpellID  int32 `json:"spell_id" db:"spell_id"`
	NodeID   int32 `json:"node_id" db:"node_id"`
	SpellCRC int32 `json:"spell_crc" db:"spell_crc"`

	// Display information
	Name        string `json:"name" db:"name"`
	Description string `json:"description" db:"description"`

	// Tree organization
	Group int8 `json:"group" db:"group"` // AA tab (AA_CLASS, AA_SUBCLASS, etc.)
	Col   int8 `json:"col" db:"col"`     // Column position in tree
	Row   int8 `json:"row" db:"row"`     // Row position in tree

	// Visual representation
	Icon  int16 `json:"icon" db:"icon"`   // Primary icon ID
	Icon2 int16 `json:"icon2" db:"icon2"` // Secondary icon ID

	// Ranking system
	RankCost int8 `json:"rank_cost" db:"rank_cost"` // Cost per rank
	MaxRank  int8 `json:"max_rank" db:"max_rank"`   // Maximum achievable rank

	// Prerequisites
	MinLevel      int8  `json:"min_level" db:"min_level"`             // Minimum character level
	RankPrereqID  int32 `json:"rank_prereq_id" db:"rank_prereq_id"`   // Prerequisite AA node ID
	RankPrereq    int8  `json:"rank_prereq" db:"rank_prereq"`         // Required rank in prerequisite
	ClassReq      int8  `json:"class_req" db:"class_req"`             // Required class
	Tier          int8  `json:"tier" db:"tier"`                       // AA tier
	ReqPoints     int8  `json:"req_points" db:"req_points"`           // Required points in classification
	ReqTreePoints int16 `json:"req_tree_points" db:"req_tree_points"` // Required points in entire tree

	// Display classification
	ClassName    string `json:"class_name" db:"class_name"`       // Class name for display
	SubclassName string `json:"subclass_name" db:"subclass_name"` // Subclass name for display
	LineTitle    string `json:"line_title" db:"line_title"`       // AA line title
	TitleLevel   int8   `json:"title_level" db:"title_level"`     // Title level requirement

	// Metadata
	CreatedAt time.Time `json:"created_at" db:"created_at"`
	UpdatedAt time.Time `json:"updated_at" db:"updated_at"`
}

// TreeNodeData represents class-specific AA tree node configuration
type TreeNodeData struct {
	ClassID  int32 `json:"class_id" db:"class_id"`     // Character class ID
	TreeID   int32 `json:"tree_id" db:"tree_id"`       // Tree node identifier
	AATreeID int32 `json:"aa_tree_id" db:"aa_tree_id"` // AA tree classification ID
}

// AAEntry represents a player's AA entry in a template
type AAEntry struct {
	TemplateID int8  `json:"template_id" db:"template_id"` // Template identifier (1-8)
	TabID      int8  `json:"tab_id" db:"tab_id"`           // Tab identifier
	AAID       int32 `json:"aa_id" db:"aa_id"`             // AA node ID
	Order      int16 `json:"order" db:"order"`             // Display order
	TreeID     int8  `json:"tree_id" db:"tree_id"`         // Tree identifier
}

// PlayerAAData represents a player's AA progression
type PlayerAAData struct {
	// Player identification
	CharacterID int32 `json:"character_id" db:"character_id"`

	// AA progression
	NodeID      int32 `json:"node_id" db:"node_id"`           // AA node ID
	CurrentRank int8  `json:"current_rank" db:"current_rank"` // Current rank in this AA
	PointsSpent int32 `json:"points_spent" db:"points_spent"` // Total points spent on this AA

	// Template assignment
	TemplateID int8  `json:"template_id" db:"template_id"` // Template this AA belongs to
	TabID      int8  `json:"tab_id" db:"tab_id"`           // Tab this AA belongs to
	Order      int16 `json:"order" db:"order"`             // Display order

	// Timestamps
	PurchasedAt time.Time `json:"purchased_at" db:"purchased_at"`
	UpdatedAt   time.Time `json:"updated_at" db:"updated_at"`
}

// AATemplate represents an AA template configuration
type AATemplate struct {
	// Template identification
	TemplateID  int8   `json:"template_id"`
	Name        string `json:"name"`
	Description string `json:"description"`
	IsPersonal  bool   `json:"is_personal"` // True for personal templates (1-3)
	IsServer    bool   `json:"is_server"`   // True for server templates (4-6)
	IsCurrent   bool   `json:"is_current"`  // True for current active template

	// Template data
	Entries []*AAEntry `json:"entries"` // AA entries in this template

	// Metadata
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

// AATab represents an AA tab with its associated data
type AATab struct {
	// Tab identification
	TabID int8   `json:"tab_id"`
	Group int8   `json:"group"`
	Name  string `json:"name"`

	// Tab configuration
	MaxAA        int32 `json:"max_aa"`        // Maximum AA points for this tab
	ClassID      int32 `json:"class_id"`      // Associated class ID
	ExpansionReq int8  `json:"expansion_req"` // Required expansion flags

	// Current state
	PointsSpent     int32 `json:"points_spent"`     // Points spent in this tab
	PointsAvailable int32 `json:"points_available"` // Available points for spending

	// AA nodes in this tab
	Nodes []*AltAdvanceData `json:"nodes"`

	// Metadata
	LastUpdate time.Time `json:"last_update"`
}

// AAPlayerState represents a player's complete AA state
type AAPlayerState struct {
	// Player identification
	CharacterID int32 `json:"character_id"`

	// AA points
	TotalPoints     int32 `json:"total_points"`     // Total AA points earned
	SpentPoints     int32 `json:"spent_points"`     // Total AA points spent
	AvailablePoints int32 `json:"available_points"` // Available AA points
	BankedPoints    int32 `json:"banked_points"`    // Banked AA points

	// Templates
	ActiveTemplate int8                 `json:"active_template"` // Currently active template
	Templates      map[int8]*AATemplate `json:"templates"`       // All templates

	// Tab states
	Tabs map[int8]*AATab `json:"tabs"` // Tab states

	// Player AA progression
	AAProgress map[int32]*PlayerAAData `json:"aa_progress"` // AA node progress by node ID

	// Caching and synchronization
	mutex      sync.RWMutex `json:"-"`
	lastUpdate time.Time    `json:"last_update"`
	needsSync  bool         `json:"-"`
}

// MasterAAList manages all AA definitions
type MasterAAList struct {
	// AA storage
	aaList      []*AltAdvanceData          `json:"aa_list"`
	aaBySpellID map[int32]*AltAdvanceData  `json:"-"` // Fast lookup by spell ID
	aaByNodeID  map[int32]*AltAdvanceData  `json:"-"` // Fast lookup by node ID
	aaByGroup   map[int8][]*AltAdvanceData `json:"-"` // Fast lookup by group/tab

	// Synchronization
	mutex sync.RWMutex `json:"-"`

	// Statistics
	totalLoaded  int64     `json:"total_loaded"`
	lastLoadTime time.Time `json:"last_load_time"`
}

// MasterAANodeList manages tree node configurations
type MasterAANodeList struct {
	// Node storage
	nodeList     []*TreeNodeData           `json:"node_list"`
	nodesByClass map[int32][]*TreeNodeData `json:"-"` // Fast lookup by class ID
	nodesByTree  map[int32]*TreeNodeData   `json:"-"` // Fast lookup by tree ID

	// Synchronization
	mutex sync.RWMutex `json:"-"`

	// Statistics
	totalLoaded  int64     `json:"total_loaded"`
	lastLoadTime time.Time `json:"last_load_time"`
}

// AAManager manages the entire AA system
type AAManager struct {
	// Core lists
	masterAAList   *MasterAAList     `json:"master_aa_list"`
	masterNodeList *MasterAANodeList `json:"master_node_list"`

	// Player states
	playerStates map[int32]*AAPlayerState `json:"-"` // Player AA states by character ID
	statesMutex  sync.RWMutex             `json:"-"`

	// Configuration
	config AAManagerConfig `json:"config"`

	// Database interface
	database AADatabase `json:"-"`

	// Packet handler
	packetHandler AAPacketHandler `json:"-"`

	// Event handlers
	eventHandlers []AAEventHandler `json:"-"`
	eventMutex    sync.RWMutex     `json:"-"`

	// Validation and notification interfaces
	validator  AAValidator  `json:"-"`
	notifier   AANotifier   `json:"-"`
	statistics AAStatistics `json:"-"`
	cache      AACache      `json:"-"`

	// Statistics
	stats      AAManagerStats `json:"stats"`
	statsMutex sync.RWMutex   `json:"-"`

	// Background processing
	stopChan chan struct{}  `json:"-"`
	wg       sync.WaitGroup `json:"-"`
}

// AAManagerConfig holds configuration for the AA manager
type AAManagerConfig struct {
	// System settings
	EnableAASystem   bool `json:"enable_aa_system"`
	EnableCaching    bool `json:"enable_caching"`
	EnableValidation bool `json:"enable_validation"`
	EnableLogging    bool `json:"enable_logging"`

	// Player settings
	AAPointsPerLevel int32 `json:"aa_points_per_level"`
	MaxBankedPoints  int32 `json:"max_banked_points"`
	EnableAABanking  bool  `json:"enable_aa_banking"`

	// Performance settings
	CacheSize      int32         `json:"cache_size"`
	UpdateInterval time.Duration `json:"update_interval"`
	BatchSize      int32         `json:"batch_size"`

	// Database settings
	DatabaseEnabled bool          `json:"database_enabled"`
	AutoSave        bool          `json:"auto_save"`
	SaveInterval    time.Duration `json:"save_interval"`
}

// AAManagerStats holds statistics about the AA system
type AAManagerStats struct {
	// Loading statistics
	TotalAAsLoaded   int64         `json:"total_aas_loaded"`
	TotalNodesLoaded int64         `json:"total_nodes_loaded"`
	LastLoadTime     time.Time     `json:"last_load_time"`
	LoadDuration     time.Duration `json:"load_duration"`

	// Player statistics
	ActivePlayers      int64   `json:"active_players"`
	TotalAAPurchases   int64   `json:"total_aa_purchases"`
	TotalPointsSpent   int64   `json:"total_points_spent"`
	AveragePointsSpent float64 `json:"average_points_spent"`

	// Performance statistics
	CacheHits       int64 `json:"cache_hits"`
	CacheMisses     int64 `json:"cache_misses"`
	DatabaseQueries int64 `json:"database_queries"`
	PacketsSent     int64 `json:"packets_sent"`

	// Tab usage statistics
	TabUsage   map[int8]int64  `json:"tab_usage"`
	PopularAAs map[int32]int64 `json:"popular_aas"`

	// Error statistics
	ValidationErrors int64 `json:"validation_errors"`
	DatabaseErrors   int64 `json:"database_errors"`
	PacketErrors     int64 `json:"packet_errors"`

	// Timing statistics
	LastStatsUpdate time.Time `json:"last_stats_update"`
}

// DefaultAAManagerConfig returns a default configuration
func DefaultAAManagerConfig() AAManagerConfig {
	return AAManagerConfig{
		EnableAASystem:   DEFAULT_ENABLE_AA_SYSTEM,
		EnableCaching:    DEFAULT_ENABLE_AA_CACHING,
		EnableValidation: DEFAULT_ENABLE_AA_VALIDATION,
		EnableLogging:    DEFAULT_ENABLE_AA_LOGGING,
		AAPointsPerLevel: DEFAULT_AA_POINTS_PER_LEVEL,
		MaxBankedPoints:  DEFAULT_AA_MAX_BANKED_POINTS,
		EnableAABanking:  true,
		CacheSize:        AA_CACHE_SIZE,
		UpdateInterval:   time.Duration(AA_UPDATE_INTERVAL) * time.Millisecond,
		BatchSize:        AA_PROCESSING_BATCH_SIZE,
		DatabaseEnabled:  true,
		AutoSave:         true,
		SaveInterval:     5 * time.Minute,
	}
}

// NewAAPlayerState creates a new player AA state
func NewAAPlayerState(characterID int32) *AAPlayerState {
	return &AAPlayerState{
		CharacterID:     characterID,
		TotalPoints:     0,
		SpentPoints:     0,
		AvailablePoints: 0,
		BankedPoints:    0,
		ActiveTemplate:  AA_TEMPLATE_CURRENT,
		Templates:       make(map[int8]*AATemplate),
		Tabs:            make(map[int8]*AATab),
		AAProgress:      make(map[int32]*PlayerAAData),
		lastUpdate:      time.Now(),
		needsSync:       false,
	}
}

// NewAATemplate creates a new AA template
func NewAATemplate(templateID int8, name string) *AATemplate {
	return &AATemplate{
		TemplateID:  templateID,
		Name:        name,
		Description: "",
		IsPersonal:  templateID >= 1 && templateID <= 3,
		IsServer:    templateID >= 4 && templateID <= 6,
		IsCurrent:   templateID == AA_TEMPLATE_CURRENT,
		Entries:     make([]*AAEntry, 0),
		CreatedAt:   time.Now(),
		UpdatedAt:   time.Now(),
	}
}

// NewAATab creates a new AA tab
func NewAATab(tabID, group int8, name string) *AATab {
	return &AATab{
		TabID:           tabID,
		Group:           group,
		Name:            name,
		MaxAA:           0,
		ClassID:         0,
		ExpansionReq:    EXPANSION_NONE,
		PointsSpent:     0,
		PointsAvailable: 0,
		Nodes:           make([]*AltAdvanceData, 0),
		LastUpdate:      time.Now(),
	}
}

// Copy creates a deep copy of AltAdvanceData
func (aad *AltAdvanceData) Copy() *AltAdvanceData {
	copy := *aad
	return &copy
}

// IsValid validates the AltAdvanceData
func (aad *AltAdvanceData) IsValid() bool {
	return aad.SpellID > 0 &&
		aad.NodeID > 0 &&
		len(aad.Name) > 0 &&
		aad.MaxRank > 0 &&
		aad.RankCost > 0
}

// GetMaxAAForTab returns the maximum AA points for a given tab
func GetMaxAAForTab(group int8) int32 {
	switch group {
	case AA_CLASS:
		return MAX_CLASS_AA
	case AA_SUBCLASS:
		return MAX_SUBCLASS_AA
	case AA_SHADOW:
		return MAX_SHADOWS_AA
	case AA_HEROIC:
		return MAX_HEROIC_AA
	case AA_TRADESKILL:
		return MAX_TRADESKILL_AA
	case AA_PRESTIGE:
		return MAX_PRESTIGE_AA
	case AA_TRADESKILL_PRESTIGE:
		return MAX_TRADESKILL_PRESTIGE_AA
	case AA_DRAGON:
		return MAX_DRAGON_AA
	case AA_DRAGONCLASS:
		return MAX_DRAGONCLASS_AA
	case AA_FARSEAS:
		return MAX_FARSEAS_AA
	default:
		return 100 // Default maximum
	}
}

// GetTabName returns the display name for an AA tab
func GetTabName(group int8) string {
	if name, exists := AATabNames[group]; exists {
		return name
	}
	return "Unknown"
}

// GetTemplateName returns the display name for an AA template
func GetTemplateName(templateID int8) string {
	if name, exists := AATemplateNames[templateID]; exists {
		return name
	}
	return "Unknown"
}

// IsExpansionRequired checks if a specific expansion is required
func IsExpansionRequired(flags int8, expansion int8) bool {
	return (flags & expansion) != 0
}
