#pragma once

#include <SDL3/SDL.h>  // Para SDL_FRect, SDL_FPoint, SDL_Texture, SDL_Renderer

#include <array>       // Para array
#include <cstddef>     // Para size_t
#include <functional>  // Para function
#include <memory>      // Para unique_ptr, shared_ptr
#include <vector>      // Para vector

#include "utils/color.hpp"  // Para Color

class MovingSprite;
class Sprite;
class Texture;
class AnimatedSprite;

// --- Clase Background: gestiona el fondo de la sección jugable ---
class Background {
   public:
    // --- Enums ---
    enum class State {
        NORMAL,    // Progresión normal del día
        COMPLETED  // Reducción gradual de la actividad
    };

    // --- Tipos ---
    using ProgressCallback = std::function<void(float)>;  // Callback para sincronización

    // --- Constructor y destructor ---
    Background(float total_progress_to_complete = 6100.0F);  // Constructor principal
    ~Background();                                           // Destructor

    // --- Métodos principales ---
    void update(float delta_time);  // Actualiza la lógica del objeto
    void render();                  // Dibuja el objeto
    void reset();                   // Reinicia la progresión

    // --- Configuración ---
    void setPos(SDL_FRect pos);                           // Establece la posición del objeto
    void setState(State new_state);                       // Cambia el estado del fondo
    void setProgressCallback(ProgressCallback callback);  // Establece callback para sincronización
    void removeProgressCallback();                        // Elimina el callback
    void setManualMode(bool manual);                      // Activa/desactiva el modo manual
    void setCloudsSpeed(float value);                     // Ajusta la velocidad de las nubes
    void setGradientNumber(int value);                    // Establece el degradado de fondo
    void setTransition(float value);                      // Ajusta la transición entre texturas
    void setSunProgression(float progress);               // Establece la posición del sol
    void setMoonProgression(float progress);              // Establece la posición de la luna
    void setColor(Color color);                           // Establece el color de atenuación
    void setAlpha(int alpha);                             // Ajusta la transparencia del fondo

    // --- Control de progresión ---
    void incrementProgress(float amount = 1.0F);  // Incrementa la progresión interna
    void setProgress(float absolute_progress);    // Establece la progresión absoluta

    // --- Getters ---
    [[nodiscard]] auto getProgress() const -> float { return progress_; }                                // Obtiene el progreso actual
    [[nodiscard]] auto getState() const -> State { return state_; }                                      // Obtiene el estado actual
    [[nodiscard]] auto getCurrentGradient() const -> int { return static_cast<int>(gradient_number_); }  // Obtiene el gradiente actual

   private:
    // --- Constantes ---
    static constexpr size_t STAGES = 4;                                    // Número de etapas
    static constexpr float MINIMUM_COMPLETED_PROGRESS_PERCENTAGE = 0.05F;  // Porcentaje mínimo completado (10%)
    static constexpr float SUN_COMPLETION_FACTOR = 0.5F;                   // Factor de completado del sol
    static constexpr float COMPLETION_TRANSITION_DURATION_S = 3.0F;        // Duración de la transición de completado en segundos

    // --- Objetos y punteros ---
    SDL_Renderer* renderer_;                                // Renderizador de la ventana
    SDL_Texture* canvas_;                                   // Textura para componer el fondo
    SDL_Texture* color_texture_;                            // Textura para atenuar el fondo
    std::shared_ptr<Texture> buildings_texture_;            // Textura de edificios
    std::shared_ptr<Texture> top_clouds_texture_;           // Textura de nubes superiores
    std::shared_ptr<Texture> bottom_clouds_texture_;        // Textura de nubes inferiores
    std::shared_ptr<Texture> gradients_texture_;            // Textura de gradientes
    std::shared_ptr<Texture> sun_texture_;                  // Textura del sol
    std::shared_ptr<Texture> moon_texture_;                 // Textura de la luna
    std::unique_ptr<MovingSprite> top_clouds_sprite_a_;     // Sprite de nubes superiores A
    std::unique_ptr<MovingSprite> top_clouds_sprite_b_;     // Sprite de nubes superiores B
    std::unique_ptr<MovingSprite> bottom_clouds_sprite_a_;  // Sprite de nubes inferiores A
    std::unique_ptr<MovingSprite> bottom_clouds_sprite_b_;  // Sprite de nubes inferiores B
    std::unique_ptr<Sprite> buildings_sprite_;              // Sprite de edificios
    std::unique_ptr<Sprite> gradient_sprite_;               // Sprite de gradiente
    std::unique_ptr<Sprite> sun_sprite_;                    // Sprite del sol
    std::unique_ptr<Sprite> moon_sprite_;                   // Sprite de la luna
    std::unique_ptr<AnimatedSprite> grass_sprite_;          // Sprite con la hierba

    // --- Variables de configuración ---
    const float total_progress_to_complete_;  // Progreso total para completar
    const float progress_per_stage_;          // Progreso por etapa
    const float sun_completion_progress_;     // Progreso de completado del sol
    const float minimum_completed_progress_;  // Progreso mínimo calculado dinámicamente
    ProgressCallback progress_callback_;      // Callback para notificar cambios de progreso

    // --- Variables de estado ---
    std::vector<SDL_FPoint> sun_path_;             // Recorrido del sol
    std::vector<SDL_FPoint> moon_path_;            // Recorrido de la luna
    std::array<SDL_FRect, STAGES> gradient_rect_;  // Fondos degradados
    std::array<SDL_FRect, 4> top_clouds_rect_;     // Nubes superiores
    std::array<SDL_FRect, 4> bottom_clouds_rect_;  // Nubes inferiores
    SDL_FRect rect_;                               // Tamaño del objeto
    SDL_FRect src_rect_;                           // Parte del objeto para copiar en pantalla
    SDL_FRect dst_rect_;                           // Posición en pantalla donde se copia el objeto
    Color attenuate_color_;                        // Color de atenuación
    State state_ = State::NORMAL;                  // Estado actual
    float progress_ = 0.0F;                        // Progresión interna
    float clouds_speed_ = 0;                       // Velocidad de las nubes
    float transition_ = 0;                         // Porcentaje de transición
    float current_alpha_float_ = 0.0F;             // Acumulador para el valor alfa preciso
    size_t gradient_number_ = 0;                   // Índice de fondo degradado
    size_t alpha_color_texture_ = 0;               // Transparencia de atenuación
    size_t previous_alpha_color_texture_ = 0;      // Transparencia anterior
    size_t sun_index_ = 0;                         // Índice del recorrido del sol
    size_t moon_index_ = 0;                        // Índice del recorrido de la luna
    int base_ = 0;                                 // Posición base del fondo
    Uint8 alpha_ = 0;                              // Transparencia entre fases
    bool manual_mode_ = false;                     // Si está en modo manual

    // --- Variables para transición suave de completado ---
    float completion_transition_timer_ = 0.0F;  // Timer para la transición de completado
    float completion_initial_progress_ = 0.0F;  // Progreso inicial al entrar en estado completado

    // --- Métodos internos ---
    void initializePaths();                          // Inicializa las rutas del sol y la luna
    void initializeRects();                          // Inicializa los rectángulos de gradientes y nubes
    void initializeSprites();                        // Crea los sprites
    void initializeSpriteProperties();               // Configura las propiedades iniciales de los sprites
    void initializeTextures();                       // Inicializa las texturas de renderizado
    void updateProgression(float delta_time);        // Actualiza la progresión y calcula transiciones
    void updateCloudsSpeed();                        // Actualiza la velocidad de las nubes según el estado
    void renderGradient();                           // Dibuja el gradiente de fondo
    void renderTopClouds();                          // Dibuja las nubes superiores
    void renderBottomClouds();                       // Dibuja las nubes inferiores
    void fillCanvas();                               // Compone todos los elementos en la textura
    void updateAlphaColorTexture(float delta_time);  // Actualiza el alpha de la textura de atenuación
    void updateClouds(float delta_time);             // Actualiza el movimiento de las nubes (time-based)
    void createSunPath();                            // Precalcula el recorrido del sol
    void createMoonPath();                           // Precalcula el recorrido de la luna
};