/**
 * DungeonSystem — wraps ContentLoader for dungeon/enemy defs + manages instances.
 */
class DungeonSystem {
    constructor(contentLoader) {
        this.loader          = contentLoader;
        this.io              = null;
        this.instances       = new Map(); // instanceId -> instance
        this.playerInstances = new Map(); // userId -> instanceId

        this.roomTypes = {
            entrance: { name: 'Entrance',     enemies: 0, rewards: false },
            corridor: { name: 'Corridor',     enemies: 1, rewards: false },
            chamber:  { name: 'Chamber',      enemies: 2, rewards: true  },
            treasure: { name: 'Treasure Room',enemies: 0, rewards: true  },
            boss:     { name: 'Boss Room',    enemies: 1, rewards: true, isBoss: true },
            exit:     { name: 'Exit',         enemies: 0, rewards: false }
        };
    }

    setIO(io) { this.io = io; }

    // ── Content queries (delegated to ContentLoader) ──────────────────
    getAllDungeons()                  { return this.loader.getAllDungeons(); }
    getDungeon(id)                   { return this.loader.getDungeon(id); }
    getDungeonsByDifficulty(d)       { return this.loader.getDungeonsByDifficulty(d); }
    getDungeonsGroupedByDifficulty() { return this.loader.getDungeonsGroupedByDifficulty(); }
    getAvailableDungeons(lvl)        { return this.loader.getAvailableDungeons(lvl); }
    getEnemyTemplates()              { return this.loader.getAllEnemies(); }
    getEnemy(id)                     { return this.loader.getEnemy(id); }

    // ── Instance management ───────────────────────────────────────────
    createInstance(dungeonId, userId, _partyIds = []) {
        const def = this.loader.getDungeon(dungeonId);
        if (!def) return null;

        const [minR, maxR] = def.roomCount || [4, 6];
        const roomCount    = Math.floor(Math.random() * (maxR - minR + 1)) + minR;
        const instanceId   = `${userId}_${dungeonId}_${Date.now()}`;

        const instance = {
            instanceId,
            dungeonId,
            userId,
            startTime:   Date.now(),
            currentRoom: 0,
            totalRooms:  roomCount,
            rooms:       this._generateRooms(def, roomCount),
            completed:   false,
            failed:      false
        };

        this.instances.set(instanceId, instance);
        this.playerInstances.set(userId, instanceId);
        return instance;
    }

    getPlayerInstance(userId) {
        const id = this.playerInstances.get(userId);
        return id ? this.instances.get(id) || null : null;
    }

    getPlayerCompletedDungeons(_userId) {
        // Could be persisted to DB; return empty array for now
        return [];
    }

    startEncounter(instanceId, userId) {
        const instance = this.instances.get(instanceId);
        if (!instance) return { success: false, error: 'Instance not found' };
        const room = instance.rooms[instance.currentRoom];
        if (!room)  return { success: false, error: 'No more rooms' };
        return { success: true, room, currentRoom: instance.currentRoom, totalRooms: instance.totalRooms };
    }

    completeEncounter(instanceId, userId, result = {}) {
        const instance = this.instances.get(instanceId);
        if (!instance) return { success: false, error: 'Instance not found' };

        const room = instance.rooms[instance.currentRoom];
        if (room) room.cleared = true;
        instance.currentRoom++;

        const isComplete = instance.currentRoom >= instance.totalRooms;
        const rewards    = isComplete ? this._generateRewards(instance.dungeonId) : [];
        if (isComplete) instance.completed = true;

        return { success: true, room, rewards, completed: isComplete };
    }

    moveToNextRoom(instanceId, userId) {
        const instance = this.instances.get(instanceId);
        if (!instance) return { success: false, error: 'Instance not found' };
        const room = instance.rooms[instance.currentRoom];
        return { success: true, room: room || null, currentRoom: instance.currentRoom, totalRooms: instance.totalRooms };
    }

    completeDungeon(instanceId) {
        const instance = this.instances.get(instanceId);
        if (!instance) return { success: false, error: 'Instance not found' };

        const rewards = this._generateRewards(instance.dungeonId);
        const def     = this.loader.getDungeon(instance.dungeonId);

        this.instances.delete(instanceId);
        this.playerInstances.delete(instance.userId);

        return { success: true, rewards, dungeonName: def?.name, timeMs: Date.now() - instance.startTime };
    }

    // ── Internals ─────────────────────────────────────────────────────
    _generateRooms(def, count) {
        const rooms     = [];
        const enemyPool = def.enemyPool || [];

        for (let i = 0; i < count; i++) {
            const isFirst = i === 0;
            const isLast  = i === count - 1;
            const isBoss  = i === count - 2 && count > 2;

            let type = 'corridor', enemies = [];

            if (isFirst)     type = 'entrance';
            else if (isLast) type = 'exit';
            else if (isBoss) {
                type = 'boss';
                const bossId = enemyPool[enemyPool.length - 1] || enemyPool[0];
                const tmpl   = this.loader.getEnemy(bossId);
                if (tmpl) enemies.push({ ...tmpl, health: Math.round(tmpl.health * 2), attack: Math.round(tmpl.attack * 1.5) });
            } else {
                const roll = Math.random();
                if (roll < 0.2)      type = 'treasure';
                else if (roll < 0.5) type = 'chamber';
                else                 type = 'corridor';

                const ec = this.roomTypes[type]?.enemies || 0;
                for (let e = 0; e < ec; e++) {
                    const eid  = enemyPool[Math.floor(Math.random() * enemyPool.length)];
                    const tmpl = this.loader.getEnemy(eid);
                    if (tmpl) enemies.push({ ...tmpl });
                }
            }

            rooms.push({ index: i, type, enemies, cleared: false, rewards: [] });
        }
        return rooms;
    }

    _generateRewards(dungeonId) {
        const def = this.loader.getDungeon(dungeonId);
        if (!def?.lootTable) return [];

        const rewards     = [];
        const totalWeight = def.lootTable.reduce((s, e) => s + (e.weight || 0), 0);
        const picks       = Math.floor(Math.random() * 3) + 1;

        for (let i = 0; i < picks; i++) {
            let roll = Math.random() * totalWeight;
            for (const entry of def.lootTable) {
                roll -= entry.weight;
                if (roll <= 0) {
                    const qty = Math.floor(Math.random() * (entry.qtyMax - entry.qtyMin + 1)) + entry.qtyMin;
                    rewards.push({ itemId: entry.itemId, quantity: qty });
                    break;
                }
            }
        }
        return rewards;
    }
}
module.exports = DungeonSystem;
