use bevy::input::mouse::MouseButton;
use bevy::prelude::*;
use bevy::window::PrimaryWindow;

use super::components::{MoveTarget, Player};
use crate::camera::MainCamera;
use crate::gameplay::in_system::DockedState;

/// Y coordinate of the ground plane. Cursor rays are projected onto this plane.
const GROUND_PLANE_Y: f32 = 0.0;

/// Helper function to check if the player is in flight mode (not docked).
/// This can be used as a run condition for systems that should only run during flight.
pub fn when_in_flight(docked: Res<DockedState>) -> bool {
    !docked.is_docked
}

/// On left-click, project the cursor onto the ground plane and update the player's MoveTarget.
/// This works in both docked and flight modes - the ground plane targeting is useful for
/// setting movement targets regardless of camera mode.
pub fn click_to_move(
    mouse_input: Res<ButtonInput<MouseButton>>,
    primary_window: Query<&Window, With<PrimaryWindow>>,
    camera_query: Query<(&Camera, &GlobalTransform), With<MainCamera>>,
    mut player: Query<&mut MoveTarget, With<Player>>,
) {
    if !mouse_input.just_pressed(MouseButton::Left) {
        return;
    }
    let Ok(window) = primary_window.single() else {
        return;
    };
    let Some(cursor_pos) = window.cursor_position() else {
        return;
    };
    let Ok((camera, camera_gt)) = camera_query.single() else {
        return;
    };
    let Ok(ray) = camera.viewport_to_world(camera_gt, cursor_pos) else {
        return;
    };

    // Intersect ray with the ground plane (y = GROUND_PLANE_Y).
    if ray.direction.y.abs() < 1e-6 {
        return; // ray is parallel to ground — no intersection
    }
    let t = (GROUND_PLANE_Y - ray.origin.y) / ray.direction.y;
    if t < 0.0 {
        return; // intersection is behind the camera
    }
    let target = ray.origin + ray.direction * t;

    let Ok(mut move_target) = player.single_mut() else {
        return;
    };
    move_target.0 = target;
}
