/**
 * Galaxy Strike Online - Server Skill System
 * Manages skill progression, experience, and abilities
 */

class SkillSystem {
    constructor() {
        this.skills = new Map();
        this.playerSkills = new Map(); // userId -> skill data
        this.initializeSkills();
    }
    
    initializeSkills() {
        // Combat skills
        this.addSkill('weapons_mastery', {
            name: 'Weapons Mastery',
            description: 'Increases damage and accuracy with all weapons',
            category: 'combat',
            maxLevel: 100,
            experiencePerLevel: 1000,
            bonuses: {
                damage: 2, // +2% per level
                accuracy: 1, // +1% per level
                criticalChance: 0.5 // +0.5% per level
            }
        });
        
        this.addSkill('defense_training', {
            name: 'Defense Training',
            description: 'Improves damage reduction and resistance',
            category: 'combat',
            maxLevel: 100,
            experiencePerLevel: 1000,
            bonuses: {
                damageReduction: 1.5, // +1.5% per level
                resistance: 1, // +1% per level
                health: 5 // +5 HP per level
            }
        });
        
        this.addSkill('speed_reflexes', {
            name: 'Speed & Reflexes',
            description: 'Enhances movement speed and reaction time',
            category: 'combat',
            maxLevel: 100,
            experiencePerLevel: 1000,
            bonuses: {
                speed: 2, // +2% per level
                dodgeChance: 0.8, // +0.8% per level
                initiative: 1 // +1 per level
            }
        });
        
        // Crafting skills
        this.addSkill('weapons_crafting', {
            name: 'Weapons Crafting',
            description: 'Ability to craft and improve weapons',
            category: 'crafting',
            maxLevel: 100,
            experiencePerLevel: 800,
            bonuses: {
                craftingSpeed: 2, // +2% per level
                craftingSuccess: 1, // +1% per level
                rareChance: 0.5 // +0.5% per level
            }
        });
        
        this.addSkill('armor_crafting', {
            name: 'Armor Crafting',
            description: 'Ability to craft and improve armor',
            category: 'crafting',
            maxLevel: 100,
            experiencePerLevel: 800,
            bonuses: {
                craftingSpeed: 2, // +2% per level
                durabilityBonus: 3, // +3% per level
                rareChance: 0.5 // +0.5% per level
            }
        });
        
        // Social skills
        this.addSkill('leadership', {
            name: 'Leadership',
            description: 'Improves team performance and guild bonuses',
            category: 'social',
            maxLevel: 100,
            experiencePerLevel: 1200,
            bonuses: {
                teamDamage: 1, // +1% per level
                guildBonus: 2, // +2% per level
                maxPartySize: 0.1 // +0.1 per level (rounded)
            }
        });
        
        this.addSkill('negotiation', {
            name: 'Negotiation',
            description: 'Better prices from shops and traders',
            category: 'social',
            maxLevel: 100,
            experiencePerLevel: 1000,
            bonuses: {
                shopDiscount: 0.5, // -0.5% per level
                tradeBonus: 1, // +1% per level
                reputationGain: 2 // +2% per level
            }
        });
        
        // Exploration skills
        this.addSkill('navigation', {
            name: 'Navigation',
            description: 'Faster travel and better map awareness',
            category: 'exploration',
            maxLevel: 100,
            experiencePerLevel: 900,
            bonuses: {
                travelSpeed: 3, // +3% per level
                discoveryRange: 2, // +2% per level
                mapAccuracy: 1 // +1% per level
            }
        });
        
        this.addSkill('scavenging', {
            name: 'Scavenging',
            description: 'Find more materials and rare items',
            category: 'exploration',
            maxLevel: 100,
            experiencePerLevel: 900,
            bonuses: {
                materialFind: 2, // +2% per level
                rareFind: 1, // +1% per level
                salvageBonus: 3 // +3% per level
            }
        });
    }
    
    addSkill(id, skill) {
        this.skills.set(id, {
            id,
            ...skill,
            createdAt: new Date().toISOString()
        });
    }
    
    getSkill(id) {
        return this.skills.get(id);
    }
    
    getAllSkills() {
        return Array.from(this.skills.values());
    }
    
    getSkillsByCategory(category) {
        return Array.from(this.skills.values()).filter(skill => skill.category === category);
    }
    
    initializePlayerData(userId) {
        if (!this.playerSkills.has(userId)) {
            this.playerSkills.set(userId, {
                skillPoints: 0,
                totalExperience: 0,
                skills: new Map(),
                unlockedSkills: new Set(['weapons_mastery', 'defense_training']), // Start with basic skills
                skillHistory: []
            });
            
            // Initialize unlocked skills at level 1
            const playerData = this.playerSkills.get(userId);
            for (const skillId of playerData.unlockedSkills) {
                playerData.skills.set(skillId, {
                    level: 1,
                    experience: 0,
                    totalExperience: 0,
                    unlockedAt: new Date().toISOString()
                });
            }
        }
        return this.playerSkills.get(userId);
    }
    
    getPlayerData(userId) {
        return this.playerSkills.get(userId) || this.initializePlayerData(userId);
    }
    
    addExperience(userId, skillId, amount) {
        const skill = this.getSkill(skillId);
        if (!skill) {
            throw new Error('Skill not found');
        }
        
        const playerData = this.getPlayerData(userId);
        
        // Check if skill is unlocked
        if (!playerData.unlockedSkills.has(skillId)) {
            throw new Error('Skill not unlocked');
        }
        
        const playerSkill = playerData.skills.get(skillId);
        if (!playerSkill) {
            throw new Error('Skill data not found');
        }
        
        // Add experience
        playerSkill.experience += amount;
        playerSkill.totalExperience += amount;
        playerData.totalExperience += amount;
        
        let levelsGained = 0;
        let oldLevel = playerSkill.level;
        
        // Check for level up
        while (playerSkill.experience >= skill.experiencePerLevel && playerSkill.level < skill.maxLevel) {
            playerSkill.experience -= skill.experiencePerLevel;
            playerSkill.level += 1;
            levelsGained++;
        }
        
        // Record in history
        playerData.skillHistory.push({
            skillId,
            experienceGained: amount,
            levelsGained,
            newLevel: playerSkill.level,
            timestamp: new Date().toISOString()
        });
        
        // Keep only last 100 skill records
        if (playerData.skillHistory.length > 100) {
            playerData.skillHistory = playerData.skillHistory.slice(-100);
        }
        
        return {
            success: true,
            experienceGained: amount,
            levelsGained,
            newLevel: playerSkill.level,
            oldLevel,
            experienceToNext: playerSkill.level < skill.maxLevel ? skill.experiencePerLevel - playerSkill.experience : 0
        };
    }
    
    unlockSkill(userId, skillId) {
        const skill = this.getSkill(skillId);
        if (!skill) {
            throw new Error('Skill not found');
        }
        
        const playerData = this.getPlayerData(userId);
        
        if (playerData.unlockedSkills.has(skillId)) {
            throw new Error('Skill already unlocked');
        }
        
        // Add to unlocked skills
        playerData.unlockedSkills.add(skillId);
        
        // Initialize at level 1
        playerData.skills.set(skillId, {
            level: 1,
            experience: 0,
            totalExperience: 0,
            unlockedAt: new Date().toISOString()
        });
        
        return {
            success: true,
            skillId,
            skillName: skill.name,
            category: skill.category
        };
    }
    
    getPlayerSkills(userId) {
        const playerData = this.getPlayerData(userId);
        const skills = [];
        
        for (const skillId of playerData.unlockedSkills) {
            const skill = this.getSkill(skillId);
            const playerSkill = playerData.skills.get(skillId);
            
            skills.push({
                ...skill,
                level: playerSkill.level,
                experience: playerSkill.experience,
                totalExperience: playerSkill.totalExperience,
                experienceToNext: playerSkill.level < skill.maxLevel ? skill.experiencePerLevel - playerSkill.experience : 0,
                isMaxLevel: playerSkill.level >= skill.maxLevel,
                unlockedAt: playerSkill.unlockedAt
            });
        }
        
        return skills;
    }
    
    getSkillBonuses(userId) {
        const playerData = this.getPlayerData(userId);
        const totalBonuses = {
            damage: 0,
            accuracy: 0,
            criticalChance: 0,
            damageReduction: 0,
            resistance: 0,
            health: 0,
            speed: 0,
            dodgeChance: 0,
            initiative: 0,
            craftingSpeed: 0,
            craftingSuccess: 0,
            rareChance: 0,
            durabilityBonus: 0,
            teamDamage: 0,
            guildBonus: 0,
            maxPartySize: 0,
            shopDiscount: 0,
            tradeBonus: 0,
            reputationGain: 0,
            travelSpeed: 0,
            discoveryRange: 0,
            mapAccuracy: 0,
            materialFind: 0,
            rareFind: 0,
            salvageBonus: 0
        };
        
        for (const skillId of playerData.unlockedSkills) {
            const skill = this.getSkill(skillId);
            const playerSkill = playerData.skills.get(skillId);
            
            if (skill && playerSkill) {
                for (const [bonus, value] of Object.entries(skill.bonuses)) {
                    totalBonuses[bonus] += value * playerSkill.level;
                }
            }
        }
        
        return totalBonuses;
    }
    
    awardSkillPoints(userId, amount) {
        const playerData = this.getPlayerData(userId);
        playerData.skillPoints += amount;
        
        return {
            success: true,
            pointsAwarded: amount,
            totalPoints: playerData.skillPoints
        };
    }
    
    allocateSkillPoint(userId, skillId) {
        const playerData = this.getPlayerData(userId);
        
        if (playerData.skillPoints <= 0) {
            throw new Error('No skill points available');
        }
        
        const skill = this.getSkill(skillId);
        if (!skill) {
            throw new Error('Skill not found');
        }
        
        const playerSkill = playerData.skills.get(skillId);
        if (!playerSkill) {
            throw new Error('Skill not unlocked');
        }
        
        if (playerSkill.level >= skill.maxLevel) {
            throw new Error('Skill already at max level');
        }
        
        // Allocate point
        playerSkill.level += 1;
        playerData.skillPoints -= 1;
        
        return {
            success: true,
            skillId,
            newLevel: playerSkill.level,
            remainingPoints: playerData.skillPoints
        };
    }
    
    getSkillStatistics(userId) {
        const playerData = this.getPlayerData(userId);
        const skills = this.getPlayerSkills(userId);
        
        return {
            skillPoints: playerData.skillPoints,
            totalExperience: playerData.totalExperience,
            unlockedSkills: playerData.unlockedSkills.size,
            maxLevelSkills: skills.filter(skill => skill.isMaxLevel).length,
            averageLevel: skills.length > 0 ? Math.floor(skills.reduce((sum, skill) => sum + skill.level, 0) / skills.length) : 0,
            recentHistory: playerData.skillHistory.slice(-10)
        };
    }
}

module.exports = SkillSystem;
