#pragma once

#include <SDL3/SDL.h>

#include <cstdint>
#include <memory>  // Para shared_ptr
#include <string>  // Para string, basic_string
#include <vector>  // Para vector
class Sprite;      // lines 8-8
class Surface;     // lines 10-10
class Text;        // lines 9-9
class DeltaTimer;  // lines 11-11

class Notifier {
   public:
    // Justificado para las notificaciones
    enum class TextAlign : std::uint8_t {
        LEFT,
        CENTER,
    };

    // Forma de las notificaciones
    enum class Shape : std::uint8_t {
        ROUNDED,
        SQUARED,
    };

    // Estilo de notificación
    struct Style {
        Uint8 bg_color;          // Color de fondo
        Uint8 border_color;      // Color del borde
        Uint8 text_color;        // Color del texto
        Shape shape;             // Forma (ROUNDED/SQUARED)
        TextAlign text_align;    // Alineación del texto
        float duration;          // Duración en segundos
        std::string sound_file;  // Archivo de sonido (vacío = sin sonido)
        bool play_sound;         // Si reproduce sonido

        // Estilos predefinidos
        static const Style DEFAULT;
        static const Style CHEEVO;
    };

    // Gestión singleton
    static void init(const std::string& icon_file, const std::string& text);  // Inicialización
    static void destroy();                                                    // Destrucción
    static auto get() -> Notifier*;                                           // Acceso al singleton

    // Métodos principales
    void render();                  // Renderizado
    void update(float delta_time);  // Actualización lógica
    void show(
        std::vector<std::string> texts,
        const Style& style = Style::DEFAULT,
        int icon = -1,
        bool can_be_removed = true,
        const std::string& code = std::string());  // Mostrar notificación

    // Consultas
    auto isActive() -> bool;                             // Indica si hay notificaciones activas
    auto getCodes() -> std::vector<std::string>;         // Obtiene códigos de notificaciones
    [[nodiscard]] auto getVisibleHeight() const -> int;  // Altura ocupada por notificaciones activas

    // Offset vertical (para evitar solapamiento con Console y renderInfo)
    void addYOffset(int px);     // Suma píxeles al offset base
    void removeYOffset(int px);  // Resta píxeles al offset base

   private:
    // Tipos anidados
    enum class Status : std::uint8_t {
        RISING,
        STAY,
        VANISHING,
        FINISHED,
    };

    struct Notification {
        std::shared_ptr<Surface> surface{nullptr};
        std::shared_ptr<Sprite> sprite{nullptr};
        std::vector<std::string> texts;
        Status state{Status::RISING};
        Shape shape{Shape::SQUARED};
        SDL_FRect rect{.x = 0.0F, .y = 0.0F, .w = 0.0F, .h = 0.0F};
        int y{0};
        int travel_dist{0};
        std::string code;
        bool can_be_removed{true};
        int height{0};
        float elapsed_time{0.0F};
        float display_duration{0.0F};
    };

    // Constantes
    static constexpr float ICON_SIZE = 16.0F;
    static constexpr float PADDING_OUT = 0.0F;
    static constexpr float SLIDE_SPEED = 120.0F;  // Pixels per second for slide animations
    static constexpr float LINE_HEIGHT = 6.0F;    // Alto de línea fijo para el layout de notificaciones
    static constexpr int CORNER_RADIUS = 4;       // Radio de las esquinas redondeadas
    static constexpr int BORDER_INSET = 1;        // Inset del borde interior

    // [SINGLETON] Objeto notifier
    static Notifier* notifier;

    // Métodos privados
    void clearFinishedNotifications();  // Elimina las notificaciones finalizadas
    void clearNotifications();          // Finaliza y elimina todas las notificaciones activas

    // Constructor y destructor privados [SINGLETON]
    Notifier(const std::string& icon_file, const std::string& text);
    ~Notifier() = default;

    // Variables miembro
    std::shared_ptr<Surface> icon_surface_;    // Textura para los iconos
    std::shared_ptr<Text> text_;               // Objeto para dibujar texto
    std::unique_ptr<DeltaTimer> delta_timer_;  // Timer for frame-independent animations
    std::vector<Notification> notifications_;  // Lista de notificaciones activas
    bool stack_{false};                        // Indica si las notificaciones se apilan
    bool has_icons_{false};                    // Indica si el notificador tiene textura para iconos
    int y_offset_{0};                          // Offset vertical base (ajustado por Console y renderInfo)
};
