#pragma once

#include <SDL3/SDL.h>

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

#include "core/rendering/sprite/dissolve_sprite.hpp"  // Para SurfaceDissolveSprite
#include "game/scenes/scene.hpp"                      // Para Scene
#include "utils/defines.hpp"                          // Para GameCanvas::WIDTH, GameCanvas::FIRST_QUAR...

class MovingSprite;
class DeltaTimer;

class Ending2 : public Scene {
   public:
    // --- Constructor y Destructor ---
    Ending2();
    ~Ending2() override;

    // --- Bucle principal (SDL3 Callback API) ---
    void iterate() override;
    void handleEvent(const SDL_Event& event) override;

   private:
    // --- Enumeraciones ---
    enum class EndingState : std::uint8_t {
        PRE_CREDITS,   // Estado previo a los créditos
        CREDITS,       // Estado de los créditos
        POST_CREDITS,  // Estado posterior a los créditos
        FADING,        // Estado de fundido de los textos a negro
    };

    // --- Estructuras ---
    struct State {
        EndingState state{EndingState::PRE_CREDITS};  // Estado actual
        float duration{0.0F};                         // Duración en segundos para el estado actual
    };

    // --- Constantes ---
    static constexpr int FIRST_COL = GameCanvas::FIRST_QUARTER_X + (GameCanvas::WIDTH / 16);   // Primera columna por donde desfilan los sprites
    static constexpr int SECOND_COL = GameCanvas::THIRD_QUARTER_X - (GameCanvas::WIDTH / 16);  // Segunda columna por donde desfilan los sprites
    static constexpr int DIST_SPRITE_TEXT = 8;                                                 // Distancia entre el sprite y el texto que lo acompaña
    static constexpr int DIST_SPRITE_SPRITE = 0;                                               // Distancia entre dos sprites de la misma columna
    static constexpr int INITIAL_Y_OFFSET = 40;                                                // Offset inicial en Y para posicionar sprites
    static constexpr int SCREEN_MESH_HEIGHT = 8;                                               // Altura de la malla superior/inferior de la pantalla
    static constexpr int FADE_H = 24;                                                          // Alçada de la zona de dissolució als cantons (files)
    static constexpr float TRANSITION_DURATION_MS = 500.0F;                                    // ms per canviar d'estat (generar o dissoldre)
    static constexpr int ENTRY_EXIT_PADDING = 2;                                               // px de padding als bordes per activar dissolució/generació
    static constexpr int TEXT_SPACING_MULTIPLIER = 2;                                          // Multiplicador para espaciado entre líneas de texto

    // Constantes de tiempo (basadas en tiempo real, no en frames)
    static constexpr float SPRITE_DESP_SPEED = -12.0F;          // Velocidad de desplazamiento en pixels/segundo (era -0.2 px/frame @ 60fps)
    static constexpr float STATE_PRE_CREDITS_DURATION = 3.0F;   // Duración del estado previo a créditos en segundos
    static constexpr float STATE_POST_CREDITS_DURATION = 5.0F;  // Duración del estado posterior a créditos en segundos
    static constexpr float STATE_FADE_DURATION = 5.0F;          // Duración del fade final en segundos
    static constexpr int MUSIC_FADE_DURATION = 3000;            // Duración del fade de música en milisegundos (para Audio API)

    // --- Métodos ---
    void update();                                  // Actualiza el objeto
    void render();                                  // Dibuja el final en pantalla
    static void handleInput();                      // Comprueba las entradas
    void updateState(float delta_time);             // Actualiza el estado
    void transitionToState(EndingState new_state);  // Transición entre estados
    void iniSpriteList();                           // Inicializa la lista de sprites
    void loadSprites();                             // Carga todos los sprites desde una lista
    void updateSprites(float delta);                // Actualiza los sprites
    void updateTextSprites(float delta);            // Actualiza los sprites de texto
    void updateTexts(float delta);                  // Actualiza los sprites de texto del final
    void renderSprites();                           // Dibuja los sprites
    void renderSpriteTexts();                       // Dibuja los sprites con el texto
    void renderTexts();                             // Dibuja los sprites con el texto del final
    void placeSprites() const;                      // Coloca los sprites en su sitio
    void createSpriteTexts();                       // Crea los sprites con las texturas con los textos
    void createTexts();                             // Crea los sprites con las texturas con los textos del final
    void updateFinalFade();                         // Actualiza el fade final

    // --- Variables miembro ---
    // Objetos y punteros a recursos
    std::vector<std::shared_ptr<DissolveSprite>> sprites_;       // Vector con todos los sprites a dibujar
    std::vector<std::shared_ptr<DissolveSprite>> sprite_texts_;  // Vector con los sprites de texto de los sprites
    std::vector<std::shared_ptr<DissolveSprite>> texts_;         // Vector con los sprites de texto
    std::unique_ptr<DeltaTimer> delta_timer_;                    // Timer para time-based update

    // Variables de estado
    State state_;             // Controla el estado de la clase
    float state_time_{0.0F};  // Tiempo acumulado en el estado actual

    // Variables auxiliares
    std::vector<std::string> sprite_list_;  // Lista con todos los sprites a dibujar
    std::vector<Uint8> colors_;             // Vector con los colores para el fade
    float sprite_max_width_{0.0F};          // El valor de ancho del sprite más ancho
    float sprite_max_height_{0.0F};         // El valor de alto del sprite más alto
};
