const { Player, Inventory } = require("../../models");
const sessionManager = require("../../game/SessionManager");
const DatapackLoader = require("../../game/DatapackLoader");

module.exports = (io, socket) => {
  const userId = socket.user?.id;

  socket.on("dungeon:start", async ({ dungeonId }) => {
    try {
      if (!userId) return;

      const dungeon = DatapackLoader.getDungeon(dungeonId);
      if (!dungeon) {
        return socket.emit("error", { message: "Dungeon coordinates invalid" });
      }

      const player = await Player.findByPk(userId);
      if (player.energy < dungeon.energyCost) {
        return socket.emit("error", {
          message: "Insufficient energy for deployment",
        });
      }

      await player.decrement("energy", { by: dungeon.energyCost });

      const dungeonSession = {
        dungeonId: dungeon.id,
        currentRoomIndex: 0,
        isCompleted: false,
        startTime: Date.now(),
        rewards: [],
      };

      sessionManager.setPlayerScene(socket.id, "dungeon", dungeonSession);

      const firstRoomId = dungeon.rooms[0].id;
      const firstRoomData = DatapackLoader.getRoom(firstRoomId);

      socket.emit("dungeon:started", {
        dungeonId: dungeon.id,
        room: firstRoomData,
        roomIndex: 0,
        totalRooms: dungeon.rooms.length,
        remainingEnergy: player.energy - dungeon.energyCost,
      });

      console.log(`[Dungeon] Player ${userId} started ${dungeonId}`);
    } catch (err) {
      console.error("Dungeon Start Error:", err);
      socket.emit("error", { message: "Failed to initiate deployment" });
    }
  });

  socket.on("dungeon:combat_step", async (data) => {
    try {
      const session = sessionManager.getPlayerSession(socket.id);
      if (!session || session.scene !== "dungeon" || !session.sceneData) return;

      const dungeonSession = session.sceneData;
      const enemyId = sessionManager._cleanId(data.enemyId);
      const enemyTemplate = DatapackLoader.getEnemy(enemyId);

      if (!enemyTemplate) {
        return socket.emit("error", { message: "Target data corrupted" });
      }

      if (dungeonSession.currentEnemyHp === undefined) {
        dungeonSession.currentEnemyHp = enemyTemplate.stats?.hp || 100;
      }

      const damage = Math.floor(Math.random() * 11) + 15;
      dungeonSession.currentEnemyHp -= damage;

      const isDefeated = dungeonSession.currentEnemyHp <= 0;

      socket.emit("dungeon:combat_result", {
        damageDealt: damage,
        enemyHp: Math.max(0, dungeonSession.currentEnemyHp),
        targetDefeated: isDefeated,
        message: `Strike successful. Dealt ${damage} damage to units.`,
      });

      if (isDefeated) {
        console.log(`[Dungeon] Enemy ${enemyId} defeated by ${session.id}`);
      }
    } catch (err) {
      console.error("Combat Error:", err);
    }
  });

  socket.on("dungeon:next_room", async () => {
    try {
      const session = sessionManager.getPlayerSession(socket.id);

      if (!session || session.scene !== "dungeon" || !session.sceneData) {
        console.error(
          `[Dungeon Error] Invalid session for socket ${socket.id}`,
        );
        return;
      }

      const dungeonId = session.sceneData.dungeonId; // ТУТ була помилка (читання з undefined)
      const dungeon = DatapackLoader.getDungeon(dungeonId);

      const nextIndex = session.sceneData.currentRoomIndex + 1;

      if (nextIndex < dungeon.rooms.length) {
        session.sceneData.currentRoomIndex = nextIndex;

        const nextRoomId = dungeon.rooms[nextIndex].id;
        const nextRoomData = DatapackLoader.getRoom(nextRoomId);

        socket.emit("dungeon:room_update", {
          room: nextRoomData,
          roomIndex: nextIndex,
        });
      } else {
        await finalizeDungeon(socket, session.sceneData, dungeon);
      }
    } catch (err) {
      console.error("Dungeon Progress Error:", err);
      socket.emit("error", { message: "Failed to process next room" });
    }
  });
};

async function finalizeDungeon(socket, sessionData, dungeon) {
  const userId = socket.user.id;
  const earnedLoot = [];

  dungeon.lootTable.forEach((entry) => {
    if (Math.random() * 100 <= entry.chance) {
      earnedLoot.push({ itemId: entry.itemId, quantity: 1 });
    }
  });

  for (const item of earnedLoot) {
    const [invItem, created] = await Inventory.findOrCreate({
      where: { playerId: userId, itemId: item.itemId },
      defaults: { quantity: 0 },
    });
    await invItem.increment("quantity", { by: item.quantity });
  }

  sessionManager.setPlayerScene(socket.id, "world", null);

  socket.emit("dungeon:completed", {
    rewards: earnedLoot,
    message: "Mission successful. All objectives secured.",
  });
}
