const DatapackLoader = require("./DatapackLoader");

class DungeonManager {
  constructor() {
    this.activeSessions = new Map();
  }

  startDungeon(playerId, dungeonId) {
    const dungeon = DatapackLoader.getDungeon(dungeonId);
    if (!dungeon || !dungeon.rooms?.length) return null;

    const session = {
      dungeonId,
      currentRoomIndex: 0,
      isFinished: false,
      currentEnemyHp: undefined,
      rewards: { xp: 0, credits: 0, items: [] },
    };
    this.activeSessions.set(playerId, session);
    return this.getCurrentRoomData(playerId);
  }

  getCurrentRoomData(playerId) {
    const session = this.activeSessions.get(playerId);
    if (!session) return null;

    const dungeon = DatapackLoader.getDungeon(session.dungeonId);
    const roomRef = dungeon.rooms[session.currentRoomIndex];
    const rawRoom = DatapackLoader.getRoom(roomRef.id);

    if (!rawRoom) return null;

    const hostiles = (rawRoom.hostiles || [])
      .map((hId) => DatapackLoader.getEnemy(hId))
      .filter(Boolean);

    return {
      roomIndex: session.currentRoomIndex,
      totalRooms: dungeon.rooms.length,
      config: rawRoom,
      hostiles,
    };
  }

  processCombatStep(playerId, enemyId) {
    const session = this.activeSessions.get(playerId);
    if (!session || session.isFinished) return null;

    const enemy = DatapackLoader.getEnemy(enemyId);
    if (!enemy) return null;

    if (session.currentEnemyHp === undefined) {
      session.currentEnemyHp = enemy.stats?.health || 100;
    }

    const damage = Math.floor(Math.random() * 10) + 20;
    session.currentEnemyHp -= damage;

    const isDefeated = session.currentEnemyHp <= 0;
    let lootDropped = [];

    if (isDefeated) {
      if (enemy.loot) {
        lootDropped = this._generateLoot(enemy.loot);
        session.rewards.items.push(...lootDropped);
      }
      session.currentEnemyHp = undefined;
    }

    return {
      damageDealt: damage,
      enemyHp: Math.max(0, session.currentEnemyHp || 0),
      targetDefeated: isDefeated,
      loot: lootDropped,
    };
  }

  moveToNextRoom(playerId) {
    const session = this.activeSessions.get(playerId);
    if (!session || session.isFinished) return null;

    const dungeon = DatapackLoader.getDungeon(session.dungeonId);
    const roomRef = dungeon.rooms[session.currentRoomIndex];
    const rawRoom = DatapackLoader.getRoom(roomRef.id);

    if (rawRoom) {
      if (rawRoom.hostiles) {
        rawRoom.hostiles.forEach((hId) => {
          const enemy = DatapackLoader.getEnemy(hId);
          if (enemy) {
            session.rewards.xp += enemy.gainXp || 0;
            session.rewards.credits += enemy.credits || 0;
          }
        });
      }
      session.rewards.xp += rawRoom.gainXp || 0;
      session.rewards.credits += rawRoom.credits || 0;
      if (rawRoom.loot) {
        session.rewards.items.push(...this._generateLoot(rawRoom.loot));
      }
    }

    if (session.currentRoomIndex < dungeon.rooms.length - 1) {
      session.currentRoomIndex++;
      return this.getCurrentRoomData(playerId);
    }

    session.isFinished = true;
    return { status: "completed", rewards: session.rewards };
  }

  _generateLoot(lootTable) {
    const dropped = [];
    lootTable.forEach((entry) => {
      if (Math.random() <= (entry.chance || 1.0)) {
        const count =
          typeof entry.count === "object"
            ? Math.floor(
                Math.random() * (entry.count.max - entry.count.min + 1),
              ) + entry.count.min
            : entry.count || 1;
        dropped.push({ id: entry.id, count });
      }
    });
    return dropped;
  }

  leaveDungeon(playerId) {
    this.activeSessions.delete(playerId);
  }
}

module.exports = new DungeonManager();
