#ifndef TACTICAL_SHOOTER_HIT_DETECTION_H
#define TACTICAL_SHOOTER_HIT_DETECTION_H

#include "entity.h"

#include <cstdint>
#include <vector>

namespace tactical_shooter {

/**
 * Hit detection system that operates on the simulation entities directly.
 *
 * Because the simulation core runs in GDExtension (not GDScript), we avoid
 * crossing the script→engine boundary for every raycast during the hot loop.
 * Instead, this component provides simplified geometric checks that can be
 * resolved locally, or queues world-space queries for the Godot PhysicsServer3D
 * if precise scene geometry is needed.
 *
 * Phase 1 uses sphere/box overlap against entity positions — fast, no physics
 * dependency. Phase 2+ may add proper PhysicsServer3D raycasts against the
 * world geometry.
 */

/**
 * Result of a single hit query.
 */
struct HitResult {
    bool hit = false;
    uint16_t entity_id = 0xFFFF;  // 0xFFFF = world geometry / no entity
    float damage = 0.0f;
    float distance = 0.0f;
    godot::Vector3 point;
    godot::Vector3 normal;
    uint8_t hitbox_id = 0;        // 0=body, 1=head, 2=arms, 3=legs
};

/**
 * Weapon damage profile.
 */
struct WeaponDamage {
    float base_damage = 30.0f;
    float head_multiplier = 4.0f;
    float body_multiplier = 1.0f;
    float arm_multiplier = 0.75f;
    float leg_multiplier = 0.6f;
    float max_range = 500.0f;     // units
    float spread_degrees = 0.5f;  // random spread per shot
};

class HitDetection {
public:
    HitDetection();

    /**
     * Set which entities are currently in play (reference list).
     * Must be called before any hit queries each frame.
     */
    void set_entities(const std::vector<Entity *> &entities);

    /**
     * Raycast against entity bounding spheres.
     * No PhysicsServer3D dependency — pure geometric check.
     *
     * @param origin        Ray origin
     * @param direction     Normalized ray direction
     * @param max_distance  Maximum trace distance
     * @param exclude_id    Entity ID to exclude (shooter)
     * @return              First entity hit (if any)
     */
    HitResult raycast_entity(
        const godot::Vector3 &origin,
        const godot::Vector3 &direction,
        float max_distance,
        uint16_t exclude_id = 0xFFFF
    ) const;

    /**
     * Process a weapon fire: apply damage to hit entity.
     * Combines raycast + damage application + amortization.
     *
     * @param origin        Fire origin
     * @param direction     Fire direction (with spread already applied)
     * @param shooter_id    Entity that fired
     * @param weapon        Weapon damage profile
     * @return              Hit result with damage
     */
    HitResult process_shot(
        const godot::Vector3 &origin,
        const godot::Vector3 &direction,
        uint16_t shooter_id,
        const WeaponDamage &weapon
    );

    /**
     * Apply damage to an entity and update its state.
     * Respects armor reduction.
     *
     * @param entity   Target entity
     * @param damage   Raw damage before armor
     * @param mult     Hitbox multiplier
     * @return         Actual health removed
     */
    static float apply_damage(Entity &entity, float damage, float mult);

    /**
     * Sphere overlap detection — find all entities within radius.
     * Useful for explosive damage.
     */
    std::vector<HitResult> sphere_overlap(
        const godot::Vector3 &center,
        float radius,
        uint16_t exclude_id = 0xFFFF
    ) const;

private:
    /**
     * Get the hitbox multiplier for a hit location.
     */
    float get_hitbox_multiplier(uint8_t hitbox_id, const WeaponDamage &weapon) const;

    /**
     * Determine which hitbox a ray hit based on local-space intersection.
     * Simple head/body/leg classification by vertical offset.
     */
    uint8_t classify_hitbox(const Entity &entity, const godot::Vector3 &hit_point) const;

    const std::vector<Entity *> *entities_ = nullptr;

    // Bounding sphere radius for entity hit detection
    static constexpr float kEntityRadius = 0.4f;    // ~arm span / 2
    static constexpr float kHeadRadius = 0.2f;
    static constexpr float kEntityHeight = 1.8f;    // standing height
};

} // namespace tactical_shooter

#endif // TACTICAL_SHOOTER_HIT_DETECTION_H
