/**
 * Galaxy Strike Online - Server Dungeon System
 * Manages dungeon instances, encounters, and rewards
 */

class DungeonSystem {
    constructor() {
        this.dungeons = new Map();
        this.instances = new Map(); // instanceId -> dungeon instance
        this.playerInstances = new Map(); // userId -> instanceId
        this.initializeDungeons();
    }
    
    initializeDungeons() {
        // Tutorial Dungeon
        this.addDungeon('tutorial_caverns', {
            name: 'Tutorial Caverns',
            description: 'Learn the basics of dungeon crawling',
            difficulty: 'easy',
            minLevel: 1,
            maxLevel: 5,
            maxPlayers: 4,
            estimatedTime: 15, // minutes
            encounters: [
                {
                    type: 'combat',
                    name: 'Cave Bats',
                    enemies: ['bat', 'bat', 'bat'],
                    difficulty: 1
                },
                {
                    type: 'combat',
                    name: 'Cave Spider',
                    enemies: ['spider'],
                    difficulty: 2
                },
                {
                    type: 'boss',
                    name: 'Cave Guardian',
                    enemies: ['guardian'],
                    difficulty: 3
                }
            ],
            rewards: {
                experience: { min: 50, max: 100 },
                credits: { min: 100, max: 250 },
                items: ['health_kit', 'basic_weapon']
            },
            requirements: {
                level: 1
            }
        });
        
        // Combat Dungeon
        this.addDungeon('abandoned_mines', {
            name: 'Abandoned Mines',
            description: 'Dangerous mines filled with hostile creatures',
            difficulty: 'medium',
            minLevel: 5,
            maxLevel: 15,
            maxPlayers: 4,
            estimatedTime: 30,
            encounters: [
                {
                    type: 'combat',
                    name: 'Mine Guards',
                    enemies: ['guard', 'guard'],
                    difficulty: 3
                },
                {
                    type: 'trap',
                    name: 'Explosive Trap',
                    difficulty: 4
                },
                {
                    type: 'combat',
                    name: 'Mine Foreman',
                    enemies: ['foreman'],
                    difficulty: 5
                },
                {
                    type: 'treasure',
                    name: 'Hidden Cache',
                    difficulty: 3
                },
                {
                    type: 'boss',
                    name: 'Mine Overlord',
                    enemies: ['overlord'],
                    difficulty: 6
                }
            ],
            rewards: {
                experience: { min: 200, max: 400 },
                credits: { min: 500, max: 1000 },
                items: ['rare_weapon', 'armor_piece']
            },
            requirements: {
                level: 5,
                item: 'torch'
            }
        });
        
        // Puzzle Dungeon
        this.addDungeon('ancient_library', {
            name: 'Ancient Library',
            description: 'Solve puzzles to uncover ancient knowledge',
            difficulty: 'medium',
            minLevel: 8,
            maxLevel: 20,
            maxPlayers: 2,
            estimatedTime: 45,
            encounters: [
                {
                    type: 'puzzle',
                    name: 'Riddle Door',
                    difficulty: 4
                },
                {
                    type: 'combat',
                    name: 'Library Guardians',
                    enemies: ['guardian', 'guardian'],
                    difficulty: 4
                },
                {
                    type: 'puzzle',
                    name: 'Magic Lock',
                    difficulty: 5
                },
                {
                    type: 'treasure',
                    name: 'Forbidden Tome',
                    difficulty: 5
                },
                {
                    type: 'boss',
                    name: 'Librarian Specter',
                    enemies: ['specter'],
                    difficulty: 6
                }
            ],
            rewards: {
                experience: { min: 300, max: 600 },
                credits: { min: 750, max: 1500 },
                items: ['spell_book', 'knowledge_scroll']
            },
            requirements: {
                level: 8,
                skill: 'ancient_knowledge'
            }
        });
        
        // Raid Dungeon
        this.addDungeon('dragon_lair', {
            name: 'Dragon Lair',
            description: 'Face the ultimate dragon challenge',
            difficulty: 'hard',
            minLevel: 15,
            maxLevel: 30,
            maxPlayers: 8,
            estimatedTime: 60,
            encounters: [
                {
                    type: 'combat',
                    name: 'Dragon Whelps',
                    enemies: ['whelp', 'whelp', 'whelp', 'whelp'],
                    difficulty: 7
                },
                {
                    type: 'combat',
                    name: 'Dragon Guard',
                    enemies: ['dragon_guard', 'dragon_guard'],
                    difficulty: 8
                },
                {
                    type: 'trap',
                    name: 'Dragon Breath Trap',
                    difficulty: 9
                },
                {
                    type: 'combat',
                    name: 'Dragon Elite',
                    enemies: ['dragon_elite'],
                    difficulty: 10
                },
                {
                    type: 'boss',
                    name: 'Ancient Dragon',
                    enemies: ['ancient_dragon'],
                    difficulty: 12
                }
            ],
            rewards: {
                experience: { min: 1000, max: 2000 },
                credits: { min: 2500, max: 5000 },
                items: ['dragon_scale', 'legendary_weapon', 'dragon_egg']
            },
            requirements: {
                level: 15,
                guild: true
            }
        });
    }
    
    addDungeon(id, dungeon) {
        this.dungeons.set(id, {
            id,
            ...dungeon,
            createdAt: new Date().toISOString()
        });
    }
    
    getDungeon(id) {
        return this.dungeons.get(id);
    }
    
    getAllDungeons() {
        return Array.from(this.dungeons.values());
    }
    
    getDungeonsByDifficulty(difficulty) {
        return Array.from(this.dungeons.values()).filter(dungeon => dungeon.difficulty === difficulty);
    }
    
    createInstance(dungeonId, creatorId, playerIds = []) {
        const dungeon = this.getDungeon(dungeonId);
        if (!dungeon) {
            throw new Error('Dungeon not found');
        }
        
        // Validate requirements
        if (playerIds.length > dungeon.maxPlayers) {
            throw new Error('Too many players for this dungeon');
        }
        
        const instanceId = `instance_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
        
        const instance = {
            id: instanceId,
            dungeonId,
            creatorId,
            players: new Set([creatorId, ...playerIds]),
            currentEncounter: 0,
            status: 'active',
            startedAt: new Date().toISOString(),
            completedAt: null,
            progress: {},
            rewards: null,
            deaths: new Map() // userId -> death count
        };
        
        // Initialize progress tracking
        dungeon.encounters.forEach((encounter, index) => {
            instance.progress[index] = {
                completed: false,
                attempts: 0,
                deaths: 0
            };
        });
        
        this.instances.set(instanceId, instance);
        
        // Track player instances
        for (const playerId of instance.players) {
            this.playerInstances.set(playerId, instanceId);
        }
        
        return instance;
    }
    
    getInstance(instanceId) {
        return this.instances.get(instanceId);
    }
    
    getPlayerInstance(userId) {
        const instanceId = this.playerInstances.get(userId);
        return instanceId ? this.getInstance(instanceId) : null;
    }
    
    joinInstance(instanceId, userId) {
        const instance = this.getInstance(instanceId);
        if (!instance) {
            throw new Error('Instance not found');
        }
        
        if (instance.status !== 'active') {
            throw new Error('Instance is not active');
        }
        
        const dungeon = this.getDungeon(instance.dungeonId);
        if (instance.players.size >= dungeon.maxPlayers) {
            throw new Error('Instance is full');
        }
        
        // Remove from existing instance if any
        const existingInstanceId = this.playerInstances.get(userId);
        if (existingInstanceId) {
            this.leaveInstance(userId);
        }
        
        // Add to new instance
        instance.players.add(userId);
        this.playerInstances.set(userId, instanceId);
        
        return instance;
    }
    
    leaveInstance(userId) {
        const instanceId = this.playerInstances.get(userId);
        if (!instanceId) {
            return null;
        }
        
        const instance = this.getInstance(instanceId);
        if (instance) {
            instance.players.delete(userId);
            
            // If instance is empty, clean it up
            if (instance.players.size === 0) {
                this.instances.delete(instanceId);
            }
        }
        
        this.playerInstances.delete(userId);
        return instance;
    }
    
    startEncounter(instanceId, userId) {
        const instance = this.getInstance(instanceId);
        if (!instance) {
            throw new Error('Instance not found');
        }
        
        if (!instance.players.has(userId)) {
            throw new Error('Player not in instance');
        }
        
        const dungeon = this.getDungeon(instance.dungeonId);
        const encounter = dungeon.encounters[instance.currentEncounter];
        
        if (!encounter) {
            throw new Error('No more encounters');
        }
        
        return {
            encounter,
            encounterIndex: instance.currentEncounter,
            instance
        };
    }
    
    completeEncounter(instanceId, userId, result) {
        const instance = this.getInstance(instanceId);
        if (!instance) {
            throw new Error('Instance not found');
        }
        
        const dungeon = this.getDungeon(instance.dungeonId);
        const encounter = dungeon.encounters[instance.currentEncounter];
        
        if (!encounter) {
            throw new Error('No encounter to complete');
        }
        
        const progress = instance.progress[instance.currentEncounter];
        progress.completed = true;
        progress.attempts++;
        
        if (result.deaths) {
            progress.deaths += result.deaths;
            instance.deaths.set(userId, (instance.deaths.get(userId) || 0) + result.deaths);
        }
        
        // Move to next encounter
        instance.currentEncounter++;
        
        // Check if dungeon is complete
        if (instance.currentEncounter >= dungeon.encounters.length) {
            return this.completeDungeon(instanceId);
        }
        
        return {
            success: true,
            nextEncounter: instance.currentEncounter < dungeon.encounters.length ? dungeon.encounters[instance.currentEncounter] : null,
            instance
        };
    }
    
    completeDungeon(instanceId) {
        const instance = this.getInstance(instanceId);
        if (!instance) {
            throw new Error('Instance not found');
        }
        
        const dungeon = this.getDungeon(instance.dungeonId);
        
        // Calculate rewards
        const rewards = this.calculateRewards(dungeon, instance);
        
        // Mark as completed
        instance.status = 'completed';
        instance.completedAt = new Date().toISOString();
        instance.rewards = rewards;
        
        // Remove players from instance tracking
        for (const playerId of instance.players) {
            this.playerInstances.delete(playerId);
        }
        
        return {
            success: true,
            dungeon,
            rewards,
            instance
        };
    }
    
    calculateRewards(dungeon, instance) {
        const rewards = {
            experience: 0,
            credits: 0,
            items: []
        };
        
        // Calculate base rewards
        const expRange = dungeon.rewards.experience;
        const creditRange = dungeon.rewards.credits;
        
        rewards.experience = Math.floor(Math.random() * (expRange.max - expRange.min + 1)) + expRange.min;
        rewards.credits = Math.floor(Math.random() * (creditRange.max - creditRange.min + 1)) + creditRange.min;
        
        // Add death penalty
        const totalDeaths = Array.from(instance.deaths.values()).reduce((sum, deaths) => sum + deaths, 0);
        const deathPenalty = Math.floor(totalDeaths * 0.1); // 10% penalty per death
        rewards.experience = Math.max(0, rewards.experience - deathPenalty);
        rewards.credits = Math.max(0, rewards.credits - (deathPenalty * 2));
        
        // Add items (chance based on performance)
        const itemChance = Math.max(0.1, 0.5 - (totalDeaths * 0.1)); // Lower chance with more deaths
        if (Math.random() < itemChance) {
            const itemPool = dungeon.rewards.items;
            if (itemPool.length > 0) {
                rewards.items.push(itemPool[Math.floor(Math.random() * itemPool.length)]);
            }
        }
        
        return rewards;
    }
    
    getAvailableDungeons(playerLevel, playerCount = 1) {
        return Array.from(this.dungeons.values()).filter(dungeon => 
            dungeon.minLevel <= playerLevel && 
            dungeon.maxLevel >= playerLevel &&
            dungeon.maxPlayers >= playerCount
        );
    }
    
    getDungeonStatistics(userId) {
        const instances = Array.from(this.instances.values()).filter(instance => 
            instance.players.has(userId)
        );
        
        const completed = instances.filter(instance => instance.status === 'completed');
        const active = instances.filter(instance => instance.status === 'active');
        
        return {
            totalDungeons: instances.length,
            completedDungeons: completed.length,
            activeDungeons: active.length,
            totalDeaths: Array.from(this.playerInstances.values()).length,
            recentCompletions: completed.slice(-5).map(instance => ({
                dungeonId: instance.dungeonId,
                completedAt: instance.completedAt,
                rewards: instance.rewards
            }))
        };
    }
    
    cleanupExpiredInstances() {
        const now = Date.now();
        const expiredInstances = [];
        
        for (const [instanceId, instance] of this.instances) {
            const age = now - new Date(instance.startedAt).getTime();
            const maxAge = 2 * 60 * 60 * 1000; // 2 hours
            
            if (age > maxAge && instance.status === 'active') {
                expiredInstances.push(instanceId);
            }
        }
        
        // Clean up expired instances
        for (const instanceId of expiredInstances) {
            const instance = this.instances.get(instanceId);
            if (instance) {
                for (const playerId of instance.players) {
                    this.playerInstances.delete(playerId);
                }
                this.instances.delete(instanceId);
            }
        }
        
        return expiredInstances.length;
    }
}

module.exports = DungeonSystem;
