//! Station info panel for the docked state.
//!
//! Shown while the player is [`Docked`](super::scene::Docked) at a station.
//! This panel is info-only — all actions (undock, fitting, market, …) live in
//! the contextual action panel ([`super::actions`]), which adapts its buttons
//! to the current mode. The [`super::hud`] module spawns/despawns this panel
//! reactively based on the player's docking state.

use bevy::prelude::*;

use crate::gameplay::campaign::CampaignDraft;
use crate::gameplay::in_system::DockedState;

const PANEL_BG: Color = Color::srgb(0.05, 0.07, 0.12);
const PANEL_BORDER: Color = Color::srgb(0.25, 0.40, 0.62);
const TEXT_BRIGHT: Color = Color::srgb(0.82, 0.90, 1.0);
const TEXT_DIM: Color = Color::srgb(0.55, 0.65, 0.82);

const TITLE_FONT_SIZE: f32 = 24.0;
const BODY_FONT_SIZE: f32 = 14.0;

const PANEL_WIDTH: f32 = 360.0;
const SIDE_MARGIN: f32 = 20.0;
const TOP_MARGIN: f32 = 20.0;

/// Marker for the station info panel entity (spawned while docked).
#[derive(Component)]
pub struct DockedUi;

/// Marker for the station details text, refreshed each frame from the
/// [`CampaignDraft`] / [`DockedState`].
#[derive(Component)]
pub struct StationDetailsText;

/// Spawn the station info panel as a top-level, corner-anchored overlay.
///
/// No full-screen root: the panel is a small absolute-positioned node so it
/// only blocks camera input when the cursor is directly over it.
pub fn setup_docked_ui(mut commands: Commands) {
    commands
        .spawn((
            Node {
                position_type: PositionType::Absolute,
                left: Val::Px(SIDE_MARGIN),
                top: Val::Px(TOP_MARGIN),
                width: Val::Px(PANEL_WIDTH),
                flex_direction: FlexDirection::Column,
                row_gap: Val::Px(12.0),
                padding: UiRect::all(Val::Px(16.0)),
                border: UiRect::all(Val::Px(1.0)),
                ..default()
            },
            BackgroundColor(PANEL_BG),
            BorderColor(PANEL_BORDER),
            BorderRadius::all(Val::Px(8.0)),
            DockedUi,
        ))
        .with_children(|panel| {
            // Title
            panel.spawn((
                Text::new("Docked"),
                TextFont {
                    font_size: TITLE_FONT_SIZE,
                    ..default()
                },
                TextColor(TEXT_BRIGHT),
            ));

            // Station details (refreshed by `refresh_docked_ui`).
            panel.spawn((
                Text::new("Loading station data..."),
                TextFont {
                    font_size: BODY_FONT_SIZE,
                    ..default()
                },
                TextColor(TEXT_DIM),
                StationDetailsText,
            ));
        });
}

/// Refresh the station details text from the current campaign / docked state.
///
/// Only writes when the underlying data actually changed, so it is cheap to
/// run every frame.
pub fn refresh_docked_ui(
    campaign: Res<CampaignDraft>,
    docked_state: Res<DockedState>,
    mut query: Query<&mut Text, With<StationDetailsText>>,
) {
    // Only update when something changed.
    if !campaign.is_changed() && !docked_state.is_changed() {
        return;
    }

    let Ok(mut text) = query.single_mut() else {
        return;
    };

    let Some(starting_base) = &campaign.starting_base else {
        text.0 = "No station data available.".to_string();
        return;
    };

    let Some(galaxy) = &campaign.galaxy else {
        text.0 = "No galaxy data available.".to_string();
        return;
    };

    // Find the system.
    let Some(system_index) = galaxy
        .systems
        .iter()
        .position(|s| s.id == starting_base.system_id)
    else {
        text.0 = format!("System {} not found.", starting_base.system_id);
        return;
    };

    let system = &galaxy.systems[system_index];
    let contents = &galaxy.contents[system_index];

    // Docking station = highest-population station in the system.
    let station = contents.stations.iter().max_by_key(|s| s.population);

    let station_name = station
        .map(|s| s.name.as_str())
        .unwrap_or("Unknown Station");
    let station_pop = station.map(|s| s.population).unwrap_or(0);

    text.0 = format!(
        "{}\n{}\n\nSystem: {} ({})\nFaction: {}\nSecurity: {:.2}\nStation Pop: {}",
        station_name,
        "─".repeat(24),
        system.name,
        system.id,
        system.faction,
        system.security,
        station_pop,
    );
}
