#pragma once

#include <vector>

#include "game/gameplay/tile_collider.hpp"
#include "utils/defines.hpp"

/**
 * @brief Mapa de colisiones de una habitación
 *
 * Contiene el collision_tile_map original (32×21) y un tilemap extendido (38×27)
 * que incluye tiles de borde de las habitaciones adyacentes.
 * El TileCollider opera sobre el mapa extendido, permitiendo colisiones cross-room
 * sin lógica especial en el Player.
 */
class CollisionMap {
   public:
    // Datos de colisión de las habitaciones adyacentes (punteros a sus collision_tile_map).
    // nullptr = sin habitación en esa dirección (borde queda como EMPTY).
    struct AdjacentData {
        const std::vector<int>* top{nullptr};
        const std::vector<int>* bottom{nullptr};
        const std::vector<int>* left{nullptr};
        const std::vector<int>* right{nullptr};
        const std::vector<int>* top_left{nullptr};
        const std::vector<int>* top_right{nullptr};
        const std::vector<int>* bottom_left{nullptr};
        const std::vector<int>* bottom_right{nullptr};
    };

    explicit CollisionMap(std::vector<int> collision_tile_map);
    ~CollisionMap() = default;

    CollisionMap(const CollisionMap&) = delete;
    auto operator=(const CollisionMap&) -> CollisionMap& = delete;
    CollisionMap(CollisionMap&&) = delete;
    auto operator=(CollisionMap&&) -> CollisionMap& = delete;

    // Rellena los bordes del mapa extendido con tiles de las habitaciones adyacentes.
    void updateBorders(const AdjacentData& adjacent);

    [[nodiscard]] auto getTileCollider() const -> const TileCollider& { return tile_collider_; }
    [[nodiscard]] auto getCollisionTileMap() const -> const std::vector<int>& { return collision_tile_map_; }

    // Modifica un tile del mapa de colisiones (original + extendido) en runtime.
    // Lo usan: el editor de mapas (debug) y el DoorManager para mostrar/ocultar muros de puertas.
    void setCollisionTile(int index, int value);

   private:
    static constexpr int B = CollisionBorder::TILES;  // Tiles de borde
    static constexpr int MW = Map::WIDTH;             // Ancho original (32)
    static constexpr int MH = Map::HEIGHT;            // Alto original (21)
    static constexpr int EW = ExtendedMap::WIDTH;     // Ancho extendido (38)
    static constexpr int EH = ExtendedMap::HEIGHT;    // Alto extendido (27)

    std::vector<int> collision_tile_map_;  // Original (32×21)
    std::vector<int> extended_tile_map_;   // Extendido (38×27) — referenciado por TileCollider
    TileCollider tile_collider_;           // Debe ir después de extended_tile_map_ (usa referencia)

    // Copia el centro (room actual) al mapa extendido. Los bordes quedan como EMPTY (0).
    void buildExtendedCenter();

    // Copia una región rectangular de un tilemap fuente (MW×MH) al mapa extendido.
    void copyRegion(const std::vector<int>& src,
        int src_col,
        int src_row,
        int dst_col,
        int dst_row,
        int cols,
        int rows);
};
