#pragma once

#include <SDL3/SDL.h>

#include <deque>   // Para deque (historial)
#include <memory>  // Para shared_ptr
#include <string>  // Para string

class Surface;
class Sprite;
class Text;

class Console {
   public:
    // Singleton
    static void init(const std::string& font_name);
    static void destroy();
    static auto get() -> Console*;

    // Métodos principales
    void update(float delta_time);
    void render();
    void toggle();
    void handleEvent(const SDL_Event& event);

    // Consultas
    auto isActive() -> bool;        // true si RISING, ACTIVE o VANISHING
    auto getVisibleHeight() -> int; // Píxeles visibles actuales (0 = oculta, height_ = totalmente visible)

   private:
    enum class Status {
        HIDDEN,
        RISING,
        ACTIVE,
        VANISHING,
    };

    // Constantes visuales
    static constexpr Uint8 BG_COLOR = 0;      // PaletteColor::BLACK
    static constexpr Uint8 BORDER_COLOR = 9;  // PaletteColor::BRIGHT_GREEN
    static constexpr Uint8 MSG_COLOR = 8;     // PaletteColor::GREEN
    static constexpr float SLIDE_SPEED = 120.0F;

    // Constantes de consola
    static constexpr std::string_view CONSOLE_NAME    = "JDD Console";
    static constexpr std::string_view CONSOLE_VERSION = "v1.0";
    static constexpr int   MAX_LINE_CHARS   = 28;
    static constexpr int   MAX_HISTORY_SIZE = 20;
    static constexpr float CURSOR_ON_TIME   = 0.5F;
    static constexpr float CURSOR_OFF_TIME  = 0.3F;

    // [SINGLETON]
    static Console* console;

    // Constructor y destructor privados [SINGLETON]
    explicit Console(const std::string& font_name);
    ~Console() = default;

    // Métodos privados
    void buildSurface();   // Crea la Surface con el aspecto visual
    void redrawText();     // Redibuja el texto dinámico (msg + input + cursor)
    void processCommand(); // Procesa el comando introducido por el usuario

    // Objetos de renderizado
    std::shared_ptr<Text> text_;
    std::shared_ptr<Surface> surface_;
    std::shared_ptr<Sprite> sprite_;

    // Estado de la animación
    Status status_{Status::HIDDEN};
    float y_{0.0F};       // Posición Y actual (animada)
    float height_{0.0F};  // Altura del panel

    // Estado de la entrada de texto
    std::string msg_line_;  // inicializado en constructor con CONSOLE_NAME + CONSOLE_VERSION
    std::string input_line_;
    float       cursor_timer_{0.0F};
    bool        cursor_visible_{true};

    // Historial de comandos (navegable con flechas arriba/abajo)
    std::deque<std::string> history_;
    int         history_index_{-1};  // -1 = en la entrada actual (presente)
    std::string saved_input_;        // guarda input_line_ al empezar a navegar
};
