#pragma once

#include <SDL3/SDL.h>

#include <cstdint>

/**
 * @brief Clase base ligera para entidades con AABB dinámico de colisión.
 *
 * Un SolidActor expone un rectángulo (aabb_) al SolidActorManager, que lo
 * usa para los sweeps del Player y otras queries. No es polimórfica: no
 * tiene métodos virtuales (las entidades concretas viven en sus propios
 * managers, que las actualizan y las renderizan). La base solo unifica
 * el "bit de colisión" — AABB, flags y delta del último frame.
 *
 * Hereda de esta clase cualquier entidad que necesite participar en la
 * resolución de colisión del Player: puertas, plataformas móviles,
 * bloques empujables, ascensores, compuertas, etc.
 *
 * Las flags determinan el comportamiento del actor ante el sweep:
 *   - BLOCKS_PLAYER:  el AABB bloquea al Player como un muro en las 4 dirs.
 *   - CARRY_ON_TOP:   si el Player está de pie encima, aplica last_delta_.x.
 *   - ONEWAY_TOP:     solo bloquea desde arriba (jump-through desde abajo).
 *   - KILLS_ON_CRUSH: (futuro) si aplasta al Player contra tile sólido, mata.
 */
class SolidActor {
   public:
    // NOLINTNEXTLINE(performance-enum-size) -- bitmask con margen para crecer
    enum Flags : uint32_t {
        BLOCKS_PLAYER = 1U << 0U,
        CARRY_ON_TOP = 1U << 1U,
        ONEWAY_TOP = 1U << 2U,
        KILLS_ON_CRUSH = 1U << 3U,
    };

    SolidActor() = default;
    SolidActor(const SolidActor&) = delete;
    auto operator=(const SolidActor&) -> SolidActor& = delete;
    SolidActor(SolidActor&&) = delete;
    auto operator=(SolidActor&&) -> SolidActor& = delete;
    ~SolidActor() = default;

    [[nodiscard]] auto getAABB() const -> const SDL_FRect& { return aabb_; }
    [[nodiscard]] auto getFlags() const -> uint32_t { return flags_; }
    [[nodiscard]] auto getLastDelta() const -> SDL_FPoint { return last_delta_; }
    [[nodiscard]] auto isBlocking() const -> bool { return (flags_ & BLOCKS_PLAYER) != 0U; }
    [[nodiscard]] auto carriesOnTop() const -> bool { return (flags_ & CARRY_ON_TOP) != 0U; }
    [[nodiscard]] auto isOneWayTop() const -> bool { return (flags_ & ONEWAY_TOP) != 0U; }

   protected:
    SDL_FRect aabb_{};         // Rectángulo de colisión (room-local pixel space)
    SDL_FPoint last_delta_{};  // (dx, dy) del último frame — para carry horizontal
    uint32_t flags_{0};
};
