#pragma once

#include <SDL3/SDL.h>

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

#include "utils/defines.hpp"

class Surface;
class Sprite;
class CollisionMap;

/**
 * @brief Renderizador de tilemap de una habitación
 *
 * Responsabilidades:
 * - Renderizar el mapa de tiles estático
 * - Gestionar tiles animados (conveyor belts)
 * - Actualizar animaciones basadas en tiempo
 * - Renderizar debug visualization (en modo DEBUG)
 */
class TilemapRenderer {
   public:
    /**
     * @brief Constructor
     * @param tile_map Vector con índices de tiles de la habitación
     * @param tile_set_width Ancho del tileset en tiles
     * @param tileset_surface Surface con los gráficos del tileset
     * @param bg_color Color de fondo de la habitación (como string)
     * @param conveyor_belt_direction Dirección de las cintas transportadoras (-1, 0, +1)
     */
    TilemapRenderer(std::vector<int> tile_map, int tile_set_width, std::shared_ptr<Surface> tileset_surface, std::string bg_color, int conveyor_belt_direction);
    ~TilemapRenderer() = default;

    // Prohibir copia y movimiento
    TilemapRenderer(const TilemapRenderer&) = delete;
    auto operator=(const TilemapRenderer&) -> TilemapRenderer& = delete;
    TilemapRenderer(TilemapRenderer&&) = delete;
    auto operator=(TilemapRenderer&&) -> TilemapRenderer& = delete;

    /**
     * @brief Inicializa el renderizador
     * @param collision_map Mapa de colisiones para determinar tiles animados
     *
     * Crea la textura del mapa, pinta los tiles estáticos, y localiza tiles animados
     */
    void initialize(const CollisionMap* collision_map);

    /**
     * @brief Actualiza las animaciones de tiles
     * @param delta_time Tiempo transcurrido desde el último frame (segundos)
     */
    void update(float delta_time);

    /**
     * @brief Renderiza el mapa completo en pantalla
     *
     * Dibuja la textura del mapa y los tiles animados
     */
    void render();

#ifdef _DEBUG
    /**
     * @brief Redibuja el tilemap (para actualizar modo debug)
     * @param collision_map Mapa de colisiones para dibujar líneas de debug
     *
     * Llamado cuando se activa/desactiva el modo debug para actualizar la visualización
     */
    void redrawMap(const CollisionMap* collision_map);
    void setBgColor(const std::string& color) { bg_color_ = color; }
    void setTile(int index, int tile_value);  // Cambia un tile y repinta esa celda
#endif

    /**
     * @brief Activa/desactiva modo pausa
     * @param paused true para pausar, false para reanudar
     *
     * Nota: Actualmente no afecta al renderizado, pero mantiene consistencia con Room
     */
    void setPaused(bool paused) { is_paused_ = paused; }

    // Getter para la surface del mapa (usado por Room para acceso directo si es necesario)
    [[nodiscard]] auto getMapSurface() const -> std::shared_ptr<Surface> { return map_surface_; }

   private:
    // Estructura para tiles animados (conveyor belts)
    struct AnimatedTile {
        std::shared_ptr<Sprite> sprite{nullptr};  // SurfaceSprite para dibujar el tile
        int x_orig{0};                            // Posición X del primer tile de la animación en tilesheet
    };

    // === Constantes ===
    static constexpr int TILE_SIZE = Tile::SIZE;                      // Ancho del tile en pixels
    static constexpr int MAP_WIDTH = PlayArea::WIDTH / Tile::SIZE;    // Ancho del mapa en tiles
    static constexpr int MAP_HEIGHT = PlayArea::HEIGHT / Tile::SIZE;  // Alto del mapa en tiles
    static constexpr int PLAY_AREA_WIDTH = PlayArea::WIDTH;           // Ancho del área de juego en pixels
    static constexpr int PLAY_AREA_HEIGHT = PlayArea::HEIGHT;         // Alto del área de juego en pixels
    static constexpr float CONVEYOR_FRAME_DURATION = 0.05F;           // Duración de cada frame (3 frames @ 60fps)

    // === Datos de la habitación ===
    std::vector<int> tile_map_;                 // Índices de tiles de la habitación
    int tile_set_width_;                        // Ancho del tileset en tiles
    std::shared_ptr<Surface> tileset_surface_;  // Gráficos del tileset
    std::string bg_color_;                      // Color de fondo
    int conveyor_belt_direction_;               // Dirección de conveyor belts

    // === Renderizado ===
    std::shared_ptr<Surface> map_surface_;      // Textura para el mapa de la habitación
    std::vector<AnimatedTile> animated_tiles_;  // Tiles animados (conveyor belts)
    float time_accumulator_{0.0F};              // Acumulador de tiempo para animaciones
    bool is_paused_{false};                     // Indica si está en modo pausa

    // === Métodos privados ===
    void fillMapTexture(const CollisionMap* collision_map);    // Pinta el mapa estático y debug lines
    void setAnimatedTiles(const CollisionMap* collision_map);  // Localiza todos los tiles animados
    void updateAnimatedTiles();                                // Actualiza tiles animados
    void renderAnimatedTiles();                                // Renderiza tiles animados
};
