//! Kinematic physics & collision layer.
//!
//! See ARCH-7 ("Movement & Collision — No Physics Engine"): there is no
//! rigid-body solver. Collision is distance-based sphere overlap, separation is
//! inverse-mass-weighted position correction, and proximity is a radius query.
//! Geometry primitives live in [`geometry`]; components/events in
//! [`components`]; the per-frame systems in [`systems`].
//!
//! The collision pipeline runs every frame during `AppState::InGame`, ordered
//! after kinematic velocity integration so it resolves the latest positions.

use bevy::prelude::*;

use crate::gameplay::movement;
use crate::state::AppState;

pub mod components;
pub mod geometry;
pub mod systems;

pub use components::{BodyMass, CollisionEvent, ProximityEvent, ProximitySensor};
pub use systems::FrameCollisions;

pub struct PhysicsPlugin;

impl Plugin for PhysicsPlugin {
    fn build(&self, app: &mut App) {
        app.add_event::<CollisionEvent>()
            .add_event::<ProximityEvent>()
            .init_resource::<FrameCollisions>()
            // Collision pipeline: detect (read-only) → resolve (writes
            // Transform + Velocity), ordered after kinematic integration so
            // the positions being resolved are current.
            .add_systems(
                Update,
                (systems::detect_collisions, systems::resolve_collisions)
                    .chain()
                    .run_if(in_state(AppState::InGame))
                    .after(movement::kinematic::integrate_velocity),
            )
            // Spatial queries: proximity sensors emit Enter/Exit events.
            .add_systems(
                Update,
                systems::update_proximity_sensors.run_if(in_state(AppState::InGame)),
            )
            // Debug observer for both event streams (reads the event fields so
            // they stay live until combat/docking systems consume them).
            .add_systems(
                Update,
                systems::log_physics_events.run_if(in_state(AppState::InGame)),
            );
    }
}
