#pragma once

#include <SDL3/SDL.h>  // Para SDL_FRect, Uint16

#include <memory>  // Para shared_ptr, unique_ptr
#include <string>  // Para string
#include <vector>  // Para vector

#include "core/rendering/sprite/animated_sprite.hpp"  // Para AnimatedSprite
#include "utils/utils.hpp"                            // Para Circle

class Texture;

// --- Enums ---
enum class ItemType : int {
    DISK = 1,            // Disco
    GAVINA = 2,          // Gavina
    PACMAR = 3,          // Pacman
    CLOCK = 4,           // Reloj
    COFFEE = 5,          // Café
    DEBIAN = 6,          // Debian
    COFFEE_MACHINE = 7,  // Máquina de café
    NONE = 8,            // Ninguno
};

// --- Clase Item: representa un objeto en el juego ---
class Item {
   public:
    // --- Constantes ---
    static constexpr float WIDTH = 20.0F;                // Anchura del item
    static constexpr float HEIGHT = 20.0F;               // ALtura del item
    static constexpr int COFFEE_MACHINE_WIDTH = 30;      // Anchura de la máquina de café
    static constexpr int COFFEE_MACHINE_HEIGHT = 39;     // Altura de la máquina de café
    static constexpr float LIFETIME_DURATION_S = 10.0F;  // Duración de vida del ítem en segundos

    // Velocidades base (pixels/segundo) - Coffee Machine
    static constexpr float COFFEE_MACHINE_VEL_X_FACTOR = 30.0F;  // Factor para velocidad X de máquina de café (0.5*60fps)
    static constexpr float COFFEE_MACHINE_VEL_Y = -6.0F;         // Velocidad Y inicial de máquina de café (-0.1*60fps)
    static constexpr float COFFEE_MACHINE_ACCEL_Y = 360.0F;      // Aceleración Y de máquina de café (0.1*60²fps = 360 pixels/segundo²)

    // Velocidades base (pixels/segundo) - Items normales
    static constexpr float ITEM_VEL_X_BASE = 60.0F;  // Velocidad X base para items (1.0F*60fps)
    static constexpr float ITEM_VEL_X_STEP = 20.0F;  // Incremento de velocidad X (0.33F*60fps)
    static constexpr float ITEM_VEL_Y = -240.0F;     // Velocidad Y inicial de items (-4.0F*60fps)
    static constexpr float ITEM_ACCEL_Y = 720.0F;    // Aceleración Y de items (0.2*60²fps = 720 pixels/segundo²)

    // Constantes de física de rebote
    static constexpr float BOUNCE_VEL_THRESHOLD = 60.0F;    // Umbral de velocidad para parar (1.0F*60fps)
    static constexpr float COFFEE_BOUNCE_DAMPING = -0.20F;  // Factor de rebote Y para máquina de café
    static constexpr float ITEM_BOUNCE_DAMPING = -0.5F;     // Factor de rebote Y para items normales
    static constexpr float HORIZONTAL_DAMPING = 0.75F;      // Factor de amortiguación horizontal

    // --- Constructor y destructor ---
    Item(ItemType type, float x, float y, SDL_FRect& play_area, const std::shared_ptr<Texture>& texture, const std::vector<std::string>& animation);  // Constructor principal
    ~Item() = default;                                                                                                                                // Destructor

    // --- Métodos principales ---
    void alignTo(int x);            // Centra el objeto en la posición X indicada
    void render();                  // Renderiza el objeto en pantalla
    void disable();                 // Desactiva el objeto
    void update(float delta_time);  // Actualiza la posición, animación y contadores (time-based)

    // --- Getters ---
    [[nodiscard]] auto getPosX() const -> float { return pos_x_; }             // Obtiene la posición X
    [[nodiscard]] auto getPosY() const -> float { return pos_y_; }             // Obtiene la posición Y
    [[nodiscard]] auto getWidth() const -> int { return width_; }              // Obtiene la anchura
    [[nodiscard]] auto getHeight() const -> int { return height_; }            // Obtiene la altura
    [[nodiscard]] auto getType() const -> ItemType { return type_; }           // Obtiene el tipo
    [[nodiscard]] auto isEnabled() const -> bool { return enabled_; }          // Verifica si está habilitado
    [[nodiscard]] auto isOnFloor() const -> bool { return floor_collision_; }  // Verifica si está en el suelo
    auto getCollider() -> Circle& { return collider_; }                        // Obtiene el colisionador

   private:
    // --- Objetos y punteros ---
    std::unique_ptr<AnimatedSprite> sprite_;  // Sprite con los gráficos del objeto

    // --- Variables de estado ---
    SDL_FRect play_area_;           // Rectángulo con la zona de juego
    Circle collider_;               // Círculo de colisión del objeto
    ItemType type_;                 // Tipo de objeto
    float pos_x_ = 0.0F;            // Posición X del objeto
    float pos_y_ = 0.0F;            // Posición Y del objeto
    float vel_x_ = 0.0F;            // Velocidad en el eje X
    float vel_y_ = 0.0F;            // Velocidad en el eje Y
    float accel_x_ = 0.0F;          // Aceleración en el eje X
    float accel_y_ = 0.0F;          // Aceleración en el eje Y
    float width_ = WIDTH;           // Ancho del objeto
    float height_ = HEIGHT;         // Alto del objeto
    float rotate_speed_ = 0.0F;     // Velocidad de rotacion
    float lifetime_timer_ = 0.0F;   // Acumulador de tiempo de vida del ítem (segundos)
    bool floor_collision_ = false;  // Indica si el objeto colisiona con el suelo
    bool enabled_ = true;           // Indica si el objeto está habilitado

    // --- Métodos internos ---
    void shiftColliders();                                                                                   // Alinea el círculo de colisión con la posición del objeto
    void shiftSprite();                                                                                      // Coloca el sprite en la posición del objeto
    void move(float delta_time);                                                                             // Actualiza la posición y estados del objeto (time-based)
    void updateTimeToLive(float delta_time);                                                                 // Actualiza el contador de tiempo de vida (time-based)
    static auto getCoffeeMachineSpawn(int player_x, int item_width, int area_width, int margin = 2) -> int;  // Calcula la zona de aparición de la máquina de café
};
