//! In-system gameplay module.
//!
//! Handles the system-scale view where the player is docked at a station
//! within their selected starting system. This is the entry point to actual
//! gameplay after onboarding.

mod actions;
mod docked;
mod flight;
mod flight_ui;
mod operations;
mod scene;
mod target;
mod ui;

use bevy::prelude::*;

use crate::state::AppState;

pub use docked::{DockedState, UndockEvent};
pub use flight::{FlightState, FlightControlsPlugin};
pub use scene::ActiveSystem;
pub use target::{Targetable, TargetKind, SelectedTarget, TargetSelectionPlugin};
pub use actions::{ContextualActionPlugin, ActionType, ActionTriggeredEvent, ActionUi};
pub use operations::{TimedOperationPlugin, OperationKind, ActiveOperation};

pub struct InSystemPlugin;

impl Plugin for InSystemPlugin {
    fn build(&self, app: &mut App) {
        app.init_resource::<DockedState>()
            .init_resource::<ActiveSystem>()
            .add_event::<UndockEvent>()
            .add_plugins(FlightControlsPlugin)
            .add_plugins(TargetSelectionPlugin)
            .add_plugins(ContextualActionPlugin)
            .add_plugins(TimedOperationPlugin)
            .add_systems(
                OnEnter(AppState::InGame),
                (
                    scene::setup_in_system_view,
                    // UI removed - no longer needed
                    // ui::setup_docked_ui,
                    add_targetable_to_pois,
                ).chain(),
            )
            .add_systems(
                OnExit(AppState::InGame),
                (
                    // UI removed - no longer needed
                    // ui::despawn_docked_ui,
                    // flight_ui::despawn_flight_ui,
                    scene::despawn_in_system_scene,
                ).chain(),
            )
            .add_systems(
                Update,
                (
                    // UI removed - no longer needed
                    // ui::refresh_docked_ui,
                    // ui::undock_button_handler,
                    // flight_ui::update_flight_ui,
                    handle_action_triggered,
                )
                    .chain()
                    .run_if(in_state(AppState::InGame)),
            );
    }
}

/// Handle action triggered events from the action buttons.
fn handle_action_triggered(
    mut commands: Commands,
    mut events: EventReader<ActionTriggeredEvent>,
    player_query: Query<Entity, With<scene::PlayerShip>>,
    durations: Res<operations::OperationDurations>,
    mut operation_events: EventWriter<operations::OperationStartedEvent>,
    selected_target_query: Query<&SelectedTarget, With<scene::PlayerShip>>,
) {
    let Ok(player_entity) = player_query.single() else {
        return;
    };

    for event in events.read() {
        bevy::log::info!("Action triggered: {:?}", event.action_type);

        match event.action_type {
            ActionType::Undock => {
                operations::start_undocking(&mut commands, player_entity, &durations, &mut operation_events);
            }
            ActionType::Approach => {
                // Get selected target
                if let Ok(selected) = selected_target_query.single() {
                    operations::start_travel(&mut commands, player_entity, selected.name.clone(), &durations, &mut operation_events);
                }
            }
            ActionType::Dock => {
                // TODO: Implement docking operation
                bevy::log::info!("Dock action triggered");
            }
            ActionType::StartMining => {
                // TODO: Implement mining operation
                bevy::log::info!("Start mining action triggered");
            }
            _ => {
                bevy::log::info!("Other action: {:?}", event.action_type);
            }
        }
    }
}

/// Add Targetable components to spawned POIs (stations and asteroid belts)
/// so they can be selected by the target selection system.
fn add_targetable_to_pois(
    mut commands: Commands,
    station_query: Query<(Entity, &crate::gameplay::galaxy::Identifiable), (With<crate::gameplay::galaxy::Station>, Without<Targetable>)>,
    belt_query: Query<(Entity, &crate::gameplay::galaxy::Identifiable), (With<crate::gameplay::galaxy::AsteroidBelt>, Without<Targetable>)>,
) {
    // Add Targetable to stations
    for (entity, identifiable) in station_query.iter() {
        bevy::log::debug!("Adding Targetable component to station: {}", identifiable.display_name);
        commands.entity(entity).insert(Targetable {
            kind: TargetKind::Station,
            name: identifiable.display_name.clone(),
        });
    }

    // Add Targetable to asteroid belts
    for (entity, identifiable) in belt_query.iter() {
        bevy::log::debug!("Adding Targetable component to asteroid belt: {}", identifiable.display_name);
        commands.entity(entity).insert(Targetable {
            kind: TargetKind::AsteroidBelt,
            name: identifiable.display_name.clone(),
        });
    }
}
