//! Timed operation system for tactical navigation.
//!
//! Handles operations with durations like undocking, travel, docking, and mining.
//! Operations have progress tracking and fire completion events when done.

use bevy::prelude::*;

/// Active operation with timing information.
#[derive(Component, Debug, Clone)]
pub struct ActiveOperation {
    pub kind: OperationKind,
    pub started_at: f64,
    pub duration_ms: f64,
    pub target_name: String,
}

/// Kinds of operations that can be active.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum OperationKind {
    Undocking,
    Travel,
    Docking,
    Mining,
    Refining,
    Fitting,
    Combat,
}

/// Event fired when an operation completes.
#[derive(Event, Debug, Clone)]
pub struct OperationCompletedEvent {
    pub kind: OperationKind,
    pub entity: Entity,
}

/// Event fired when an operation is started.
#[derive(Event, Debug)]
pub struct OperationStartedEvent {
    pub kind: OperationKind,
    pub duration_ms: f64,
    pub target_name: String,
}

/// Resource for operation duration constants.
#[derive(Resource, Debug, Clone)]
pub struct OperationDurations {
    pub undock: f64,
    pub local_travel: f64,
    pub docking: f64,
    pub mining: f64,
}

impl Default for OperationDurations {
    fn default() -> Self {
        Self {
            undock: 3000.0,      // 3 seconds
            local_travel: 5000.0, // 5 seconds
            docking: 4000.0,      // 4 seconds
            mining: 8000.0,       // 8 seconds
        }
    }
}

/// Plugin for timed operation system.
pub struct TimedOperationPlugin;

impl Plugin for TimedOperationPlugin {
    fn build(&self, app: &mut App) {
        app.init_resource::<OperationDurations>()
            .add_event::<OperationCompletedEvent>()
            .add_event::<OperationStartedEvent>()
            .add_systems(
                Update,
                (
                    monitor_operations,
                    update_operation_progress,
                ).run_if(in_state(crate::state::AppState::InGame)),
            );
    }
}

/// Monitor active operations and fire completion events when done.
fn monitor_operations(
    time: Res<Time>,
    mut commands: Commands,
    query: Query<(Entity, &ActiveOperation)>,
    mut completed_events: EventWriter<OperationCompletedEvent>,
) {
    let now = time.elapsed_secs_f64() * 1000.0;

    for (entity, operation) in &query {
        let elapsed = now - operation.started_at;

        if elapsed >= operation.duration_ms {
            bevy::log::info!("Operation completed: {:?}", operation.kind);

            // Fire completion event
            completed_events.write(OperationCompletedEvent {
                kind: operation.kind,
                entity,
            });

            // Remove the operation component
            commands.entity(entity).remove::<ActiveOperation>();
        }
    }
}

/// Update operation progress for UI display.
/// This updates any Progress components attached to operation entities.
fn update_operation_progress(
    time: Res<Time>,
    mut query: Query<(&ActiveOperation, &mut Progress)>,
) {
    let now = time.elapsed_secs_f64() * 1000.0;

    for (operation, mut progress) in query.iter_mut() {
        let elapsed = now - operation.started_at;
        let progress_value = (elapsed / operation.duration_ms).clamp(0.0, 1.0);
        progress.value = progress_value as f32;
    }
}

/// Start an undocking operation on the player ship.
pub fn start_undocking(
    commands: &mut Commands,
    player_entity: Entity,
    durations: &OperationDurations,
    events: &mut EventWriter<OperationStartedEvent>,
    now_ms: f64,
) {
    commands.entity(player_entity).insert(ActiveOperation {
        kind: OperationKind::Undocking,
        started_at: now_ms,
        duration_ms: durations.undock,
        target_name: "Undocking".to_string(),
    });

    events.write(OperationStartedEvent {
        kind: OperationKind::Undocking,
        duration_ms: durations.undock,
        target_name: "Undocking".to_string(),
    });
}

/// Start a travel operation.
pub fn start_travel(
    commands: &mut Commands,
    player_entity: Entity,
    target_name: String,
    durations: &OperationDurations,
    events: &mut EventWriter<OperationStartedEvent>,
    now_ms: f64,
) {
    commands.entity(player_entity).insert(ActiveOperation {
        kind: OperationKind::Travel,
        started_at: now_ms,
        duration_ms: durations.local_travel,
        target_name: target_name.clone(),
    });

    events.write(OperationStartedEvent {
        kind: OperationKind::Travel,
        duration_ms: durations.local_travel,
        target_name,
    });
}

/// Progress bar component for showing operation progress.
#[derive(Component, Debug, Clone)]
pub struct Progress {
    pub value: f32,
}

/// Marker for operation progress UI entities.
#[derive(Component)]
pub struct OperationProgressUi;
