#pragma once

#include <SDL3/SDL.h>

#include <memory>  // Para shared_ptr
#include <string>  // Para string

class AnimatedSprite;

class Enemy {
   public:
    struct Data {
        std::string type{"path"};    // Tipo de enemigo (path, etc.)
        std::string animation_path;  // Ruta al fichero con la animación
        float x{0.0F};               // Posición inicial en el eje X
        float y{0.0F};               // Posición inicial en el eje Y
        float vx{0.0F};              // Velocidad en el eje X
        float vy{0.0F};              // Velocidad en el eje Y
        int x1{0};                   // Límite izquierdo de la ruta en el eje X
        int x2{0};                   // Límite derecho de la ruta en el eje X
        int y1{0};                   // Límite superior de la ruta en el eje Y
        int y2{0};                   // Límite inferior de la ruta en el eje Y
        bool flip{false};            // Indica si el enemigo hace flip al terminar su ruta
        bool mirror{false};          // Indica si el enemigo está volteado verticalmente
        int frame{0};                // Frame inicial para la animación del enemigo
    };

    explicit Enemy(const Data& enemy);  // Constructor
    virtual ~Enemy() = default;         // Destructor virtual

    virtual void render();                      // Pinta el enemigo en pantalla
    virtual void update(float delta_time) = 0;  // Actualiza las variables del objeto (pura virtual)
#ifdef _DEBUG
    virtual void updateAnimation(float delta_time);             // Solo actualiza la animación sin mover al enemigo
    virtual void resetToInitialPosition(const Data& data) = 0;  // Resetea a posición inicial (pura virtual)
#endif

    auto getRect() -> SDL_FRect;       // Devuelve el rectangulo que contiene al enemigo
    auto getCollider() -> SDL_FRect&;  // Obtiene el rectangulo de colision del enemigo

    // Factory: crea el subtipo de enemigo correcto según data.type
    static auto create(const Data& data) -> std::shared_ptr<Enemy>;

   protected:
    void applyFlipMirror(float vx);  // Aplica flip horizontal y/o mirror vertical al sprite

    std::shared_ptr<AnimatedSprite> sprite_;  // Sprite del enemigo
    SDL_FRect collider_{};                    // Caja de colisión
    bool should_flip_{false};                 // Indica si el enemigo hace flip al terminar su ruta
    bool should_mirror_{false};               // Indica si el enemigo se dibuja volteado verticalmente
};
