#pragma once

#ifdef _DEBUG

#include <SDL3/SDL.h>

#include <functional>     // Para function
#include <memory>         // Para shared_ptr
#include <string>         // Para string
#include <unordered_map>  // Para unordered_map
#include <vector>         // Para vector

#include "utils/defines.hpp"  // Para Map::WIDTH, Map::HEIGHT

class Surface;

/**
 * @brief Minimapa global del juego para el editor
 *
 * Genera una vista en miniatura de todas las habitaciones del juego,
 * posicionadas según sus conexiones.
 * Cada tile del mapa se representa como 1 pixel del color predominante de ese tile.
 * Resultado: cada room = Map::WIDTH x Map::HEIGHT pixels.
 */
class MiniMap {
   public:
    explicit MiniMap(Uint8 bg_color = 2, Uint8 conn_color = 14);
    ~MiniMap() = default;

    void render(const std::string& current_room);
    void handleEvent(const SDL_Event& event, const std::string& current_room);
    void rebuild(Uint8 bg_color, Uint8 conn_color);
    void centerOnRoom(const std::string& room_name);
    [[nodiscard]] auto isReady() const -> bool { return !room_positions_.empty(); }

    // Callback al hacer click en una minihabitación (nombre del room)
    std::function<void(const std::string&)> on_navigate;

   private:
    // Posición de una room en el grid del minimapa
    struct GridPos {
        int x{0};
        int y{0};
    };

    // Una room renderizada
    struct RoomMini {
        std::shared_ptr<Surface> surface;  // ROOM_W x ROOM_H pixels
        GridPos pos;                       // Posición en el grid
    };

    // Tabla de color predominante para un tileset concreto
    struct TileColorTable {
        std::vector<Uint8> colors;  // tile_index → palette color
        int tileset_width{0};       // Ancho del tileset en tiles
        Uint8 transparent{16};      // Color transparente del tileset
    };

    auto getOrBuildTileColorTable(const std::string& tileset_name) -> const TileColorTable&;
    void buildRoomSurfaces();
    void layoutRooms();
    void composeFinalSurface();
    auto getRoomMiniSurface(const std::string& room_name) -> std::shared_ptr<Surface>;
    void drawConnections();
    void renderRoomNumbers(float offset_x, float offset_y);
    auto roomAtScreen(float screen_x, float screen_y) -> std::string;
    auto cellPixelX(int grid_x) const -> int { return PADDING + ((grid_x - min_grid_x_) * (CELL_W + GAP)); }
    auto cellPixelY(int grid_y) const -> int { return PADDING + ((grid_y - min_grid_y_) * (CELL_H + GAP)); }

    // Caché de tablas de color por tileset (clave: nombre del fichero del tileset)
    std::unordered_map<std::string, TileColorTable> tileset_tables_;

    // Rooms renderizadas y posicionadas
    std::unordered_map<std::string, RoomMini> room_positions_;

    // Surface final compuesta
    std::shared_ptr<Surface> map_surface_;
    int map_width_{0};   // Ancho en pixels
    int map_height_{0};  // Alto en pixels

    // Offset para normalizar coordenadas
    int min_grid_x_{0};
    int min_grid_y_{0};

    // Viewport: offset de la surface del minimapa respecto al play area
    float view_x_{0.0F};  // Offset X actual
    float view_y_{0.0F};  // Offset Y actual
    bool dragging_{false};
    float drag_start_x_{0.0F};  // Posición del ratón al inicio del drag
    float drag_start_y_{0.0F};
    float view_start_x_{0.0F};  // Viewport al inicio del drag
    float view_start_y_{0.0F};
    bool show_numbers_{false};  // Toggle para mostrar números de room

    // Constantes
    static constexpr int ROOM_W = Map::WIDTH;             // Ancho de una room en pixels del minimapa (1 pixel por tile)
    static constexpr int ROOM_H = Map::HEIGHT;            // Alto de una room en pixels del minimapa (1 pixel por tile)
    static constexpr int BORDER = 1;                      // Borde alrededor de cada room
    static constexpr int CELL_W = ROOM_W + (BORDER * 2);  // Room + borde
    static constexpr int CELL_H = ROOM_H + (BORDER * 2);
    static constexpr int GAP = 4;            // Separación entre celdas
    static constexpr int SHADOW_OFFSET = 1;  // Desplazamiento de la sombra
    static constexpr int PADDING = 4;        // Padding alrededor del minimapa

    // Colores del minimapa (índices de paleta)
    Uint8 bg_color_{2};                              // Fondo general (configurable)
    Uint8 conn_color_{14};                           // Líneas de conexión (configurable)
    static constexpr Uint8 COLOR_ROOM_BORDER = 0;    // Borde de cada miniroom
    static constexpr Uint8 COLOR_SHADOW = 1;         // Sombra de cada miniroom
    static constexpr Uint8 COLOR_NUMBER_TEXT = 15;   // Texto de números (blanco)
    static constexpr Uint8 COLOR_NUMBER_SHADOW = 1;  // Sombra de números (oscuro)
};

#endif  // _DEBUG
