#pragma once

#include <SDL3/SDL.h>  // Para Uint32, Uint64

#include <memory>  // Para unique_ptr
#include <vector>  // Para vector

#include "core/rendering/sprite/card_sprite.hpp"  // Para CardSprite
#include "core/rendering/tiled_bg.hpp"            // Para TiledBG
#include "core/rendering/writer.hpp"              // Para Writer
#include "utils/color.hpp"                        // Para Color
#include "utils/param.hpp"                        // Para Param, ParamIntro, param

// --- Clase Intro: secuencia cinemática de introducción del juego ---
//
// Esta clase gestiona la secuencia de introducción narrativa del juego, mostrando
// una serie de escenas con imágenes, texto y efectos visuales sincronizados.
//
// Funcionalidades principales:
// • Sistema de escenas secuencial: 6 escenas con transiciones automáticas
// • Animaciones de tarjetas: efecto de lanzamiento sobre mesa con zoom, rotación y rebote
// • Texto narrativo: velocidades de escritura configurables por escena
// • Efectos visuales: sombras, bordes y transiciones de color
// • Audio sincronizado: música de fondo durante toda la secuencia
// • Estado POST: transición suave hacia el menú principal

class Intro {
   public:
    // --- Constructor y destructor ---
    Intro();
    ~Intro() = default;

    // --- Callbacks para el bucle SDL_MAIN_USE_CALLBACKS ---
    void iterate();                            // Ejecuta un frame
    void handleEvent(const SDL_Event& event);  // Procesa un evento

    // --- Bucle principal legacy (fallback) ---
    void run();

   private:
    // --- Constantes de tiempo (en segundos) ---
    static constexpr float TEXT_DISPLAY_DURATION_S = 3.0F;  // Duración de visualización de texto
    static constexpr float POST_BG_STOP_DELAY_S = 1.0F;     // Retraso antes de detener el fondo
    static constexpr float POST_END_DELAY_S = 1.0F;         // Retraso antes de finalizar intro
    static constexpr float INITIAL_DELAY_S = 2.0F;          // Pausa antes de empezar las escenas

    // --- Constantes de sonido ---
    static constexpr const char* SFX_CARD_THROW = "service_menu_select.wav";  // Sonido al lanzar una tarjeta
    static constexpr const char* SFX_CARD_IMPACT = "player_collision.wav";    // Sonido al impactar en la mesa

    // --- Constantes de layout ---
    static constexpr float CARD_BORDER_SIZE = 2.0F;  // Tamaño del borde de tarjetas
    static constexpr float SHADOW_OFFSET = 8.0F;     // Desplazamiento de sombra
    static constexpr float TILED_BG_SPEED = 18.0F;   // Velocidad del fondo mosaico (pixels/segundo)
    static constexpr int TEXT_KERNING = -2;          // Espaciado entre caracteres

    // --- Constantes de velocidades de texto (segundos entre caracteres, menor = más rápido) ---
    static constexpr float TEXT_SPEED_ULTRA_FAST = 0.0167F;  // Ultra rápida (1 frame a 60fps)
    static constexpr float TEXT_SPEED_VERY_FAST = 0.033F;    // Muy rápida (2 frames a 60fps)
    static constexpr float TEXT_SPEED_FAST = 0.05F;          // Rápida (3 frames a 60fps)
    static constexpr float TEXT_SPEED_NORMAL = 0.133F;       // Normal (8 frames a 60fps)
    static constexpr float TEXT_SPEED_SLOW = 0.2F;           // Lenta (12 frames a 60fps)
    static constexpr float TEXT_SPEED_VERY_SLOW = 0.267F;    // Muy lenta (16 frames a 60fps)
    static constexpr float TEXT_SPEED_ULTRA_SLOW = 0.333F;   // Ultra lenta (20 frames a 60fps)

    // --- Constantes de animaciones de tarjetas ---
    static constexpr float CARD_ENTRY_DURATION_S = 1.5F;  // Duración de la animación de entrada
    static constexpr float CARD_START_ZOOM = 1.8F;        // Zoom inicial (como si estuviera cerca)
    static constexpr float CARD_EXIT_SPEED = 400.0F;      // Velocidad base de salida (pixels/s)
    static constexpr float CARD_EXIT_ACCEL = 200.0F;      // Aceleración de salida (pixels/s²)
    static constexpr double CARD_EXIT_ROTATION = 450.0;   // Velocidad de rotación en salida (grados/s)

    // --- Ángulos iniciales de entrada por tarjeta (grados) ---
    static constexpr double CARD_ANGLE_0 = 12.0;
    static constexpr double CARD_ANGLE_1 = -15.0;
    static constexpr double CARD_ANGLE_2 = 8.0;
    static constexpr double CARD_ANGLE_3 = -10.0;
    static constexpr double CARD_ANGLE_4 = 18.0;
    static constexpr double CARD_ANGLE_5 = -7.0;

    // --- Estados internos ---
    enum class State {
        SCENES,
        POST,
    };

    enum class PostState {
        STOP_BG,
        END,
    };

    // --- Objetos ---
    std::vector<std::unique_ptr<CardSprite>> card_sprites_;  // Tarjetas animadas con sombra integrada
    std::vector<std::unique_ptr<Writer>> texts_;             // Textos de la intro
    std::unique_ptr<TiledBG> tiled_bg_;                      // Fondo en mosaico

    // --- Variables ---
    Uint64 last_time_ = 0;                       // Último timestamp para calcular delta-time
    int scene_ = 0;                              // Indica qué escena está activa
    State state_ = State::SCENES;                // Estado principal de la intro
    PostState post_state_ = PostState::STOP_BG;  // Estado POST
    float state_start_time_ = 0.0F;              // Tiempo de inicio del estado actual (segundos)
    Color bg_color_ = param.intro.bg_color;      // Color de fondo
    bool shake_done_ = false;                    // Evita shake repetido en la misma escena
    float initial_elapsed_ = 0.0F;               // Tiempo acumulado antes de empezar

    // --- Métodos internos ---
    void update(float delta_time);         // Actualiza las variables del objeto
    void render();                         // Dibuja el objeto en pantalla
    static void checkInput();              // Comprueba las entradas
    static void checkEvents();             // Comprueba los eventos
    void updateScenes();                   // Actualiza las escenas de la intro
    void initSprites();                    // Inicializa las tarjetas
    void initTexts();                      // Inicializa los textos
    void updateSprites(float delta_time);  // Actualiza los sprites
    void updateTexts(float delta_time);    // Actualiza los textos
    void renderSprites();                  // Dibuja los sprites
    void renderTexts();                    // Dibuja los textos
    static void renderTextRect();          // Dibuja el rectángulo de fondo del texto
    void updatePostState();                // Actualiza el estado POST
    auto calculateDeltaTime() -> float;    // Calcula el tiempo transcurrido desde el último frame

    // --- Métodos para manejar cada escena individualmente ---
    void updateScene0();
    void updateScene1();
    void updateScene2();
    void updateScene3();
    void updateScene4();
    void updateScene5();

    // --- Métodos auxiliares ---
    void switchText(int from_index, int to_index);
};
