#pragma once

#include <string>  // Para string
#include <vector>  // Para vector

#include "external/fkyaml_node.hpp"  // Para fkyaml::node
#include "game/entities/enemy.hpp"   // Para Enemy::Data
#include "game/entities/item.hpp"    // Para Item::Data
#include "game/gameplay/room.hpp"    // Para Room::Data

/**
 * @brief Cargador de archivos de habitaciones en formato YAML
 *
 * Responsabilidades:
 * - Cargar archivos de room en formato YAML unificado (.yaml)
 * - Parsear datos de room, tilemap, enemies e items
 * - Convertir tipos de datos (tiles, posiciones, colores)
 * - Validar y propagar errores de carga
 *
 * Esta clase contiene solo métodos estáticos y no debe instanciarse.
 */
class RoomLoader {
   public:
    // Constructor eliminado para prevenir instanciación
    RoomLoader() = delete;
    ~RoomLoader() = delete;
    RoomLoader(const RoomLoader&) = delete;
    auto operator=(const RoomLoader&) -> RoomLoader& = delete;
    RoomLoader(RoomLoader&&) = delete;
    auto operator=(RoomLoader&&) -> RoomLoader& = delete;

    /**
     * @brief Carga un archivo de room en formato YAML
     * @param file_path Ruta al archivo YAML de habitación
     * @param verbose Si true, muestra información de debug
     * @return Room::Data con todos los datos de la habitación incluyendo:
     *         - Configuración de la habitación (nombre, colores, etc.)
     * - Tilemap completo (convertido de 2D a 1D)
     *         - Lista de enemigos con todas sus propiedades
     *         - Lista de items con todas sus propiedades
     *
     * El formato YAML esperado incluye:
     * - room: configuración general
     * - tilemap: array 2D de 16x32 tiles (convertido a vector 1D de 512 elementos)
     * - enemies: lista de enemigos (opcional)
     * - items: lista de items (opcional)
     */
    static auto loadYAML(const std::string& file_path, bool verbose = false) -> Room::Data;
#ifdef _DEBUG
    static auto loadFromString(const std::string& yaml_content, const std::string& file_name) -> Room::Data;
#endif

   private:
    /**
     * @brief Convierte room connection de YAML a formato interno
     * @param value Valor del YAML (vacío, "02" o "02.yaml")
     * @return "0" para sin conexión, o nombre del archivo con extensión
     */
    static auto convertRoomConnection(const std::string& value) -> std::string;

    /**
     * @brief Convierte autoSurface de YAML a int
     * @param node Nodo YAML (puede ser int o string "left"/"none"/"right")
     * @return -1 para left, 0 para none, 1 para right
     */
    static auto convertAutoSurface(const fkyaml::node& node) -> int;

    /**
     * @brief Convierte un tilemap 2D a vector 1D flat
     * @param tilemap_2d Array 2D de tiles (16 rows × 32 cols)
     * @return Vector 1D flat con 512 elementos
     */
    static auto flattenTilemap(const std::vector<std::vector<int>>& tilemap_2d) -> std::vector<int>;

    /**
     * @brief Parsea la configuración general de la habitación
     * @param yaml Nodo raíz del YAML
     * @param room Estructura de datos de la habitación a rellenar
     * @param file_name Nombre del archivo para logging
     */
    static void parseRoomConfig(const fkyaml::node& yaml, Room::Data& room, const std::string& file_name);

    /**
     * @brief Parsea las conexiones de la habitación (arriba/abajo/izq/der)
     * @param conn_node Nodo YAML con las conexiones
     * @param room Estructura de datos de la habitación a rellenar
     */
    static void parseRoomConnections(const fkyaml::node& conn_node, Room::Data& room);

    /**
     * @brief Parsea el tilemap de la habitación
     * @param yaml Nodo raíz del YAML
     * @param room Estructura de datos de la habitación a rellenar
     * @param file_name Nombre del archivo para logging
     * @param verbose Si true, muestra información de debug
     */
    static void parseTilemap(const fkyaml::node& yaml, Room::Data& room, const std::string& file_name, bool verbose);

    /**
     * @brief Parsea la lista de enemigos de la habitación
     * @param yaml Nodo raíz del YAML
     * @param room Estructura de datos de la habitación a rellenar
     * @param verbose Si true, muestra información de debug
     */
    static void parseEnemies(const fkyaml::node& yaml, Room::Data& room, bool verbose);

    /**
     * @brief Parsea los datos de un enemigo individual
     * @param enemy_node Nodo YAML del enemigo
     * @return Estructura Enemy::Data con los datos parseados
     */
    static auto parseEnemyData(const fkyaml::node& enemy_node) -> Enemy::Data;

    /**
     * @brief Parsea los límites de movimiento de un enemigo
     * @param bounds_node Nodo YAML con los límites
     * @param enemy Estructura del enemigo a rellenar
     */
    static void parseEnemyBoundaries(const fkyaml::node& bounds_node, Enemy::Data& enemy);

    /**
     * @brief Parsea la lista de items de la habitación
     * @param yaml Nodo raíz del YAML
     * @param room Estructura de datos de la habitación a rellenar
     * @param verbose Si true, muestra información de debug
     */
    static void parseItems(const fkyaml::node& yaml, Room::Data& room, bool verbose);

    /**
     * @brief Parsea los datos de un item individual
     * @param item_node Nodo YAML del item
     * @param room Datos de la habitación (para colores por defecto)
     * @return Estructura Item::Data con los datos parseados
     */
    static auto parseItemData(const fkyaml::node& item_node, const Room::Data& room) -> Item::Data;
};
