use bevy::prelude::*;

use crate::{
    GameState, global_observer, heads::ActiveHeads, heads_database::HeadsDatabase,
    hitpoints::Hitpoints, loading_assets::AudioAssets,
};

#[derive(Component)]
pub struct Healing(pub Entity);

#[derive(Event, Debug)]
pub enum HealingStateChanged {
    Started,
    Stopped,
}

pub fn plugin(app: &mut App) {
    app.add_systems(Update, update.run_if(in_state(GameState::Playing)));

    global_observer!(app, on_heal_start_stop);
}

fn on_heal_start_stop(
    trigger: Trigger<HealingStateChanged>,
    mut cmds: Commands,
    assets: Res<AudioAssets>,
    query: Query<&Healing>,
) {
    if matches!(trigger.event(), HealingStateChanged::Started) {
        let e = cmds
            .spawn((
                Name::new("sfx-heal"),
                AudioPlayer::new(assets.healing.clone()),
                PlaybackSettings {
                    mode: bevy::audio::PlaybackMode::Loop,
                    ..Default::default()
                },
            ))
            .id();
        cmds.entity(trigger.target())
            .add_child(e)
            .insert(Healing(e));
    } else {
        if let Ok(healing) = query.single() {
            cmds.entity(healing.0).despawn();
        }
        cmds.entity(trigger.target()).remove::<Healing>();
    }
}

fn update(
    mut query: Query<(&mut ActiveHeads, &mut Hitpoints), With<Healing>>,
    time: Res<Time>,
    heads_db: Res<HeadsDatabase>,
) {
    for (mut heads, mut hitpoints) in query.iter_mut() {
        let Some(current) = heads.current() else {
            continue;
        };

        let head = heads_db.head_stats(current.head);

        if current.last_use + (1. / head.aps) > time.elapsed_secs() {
            continue;
        }

        let medic_hp = hitpoints.get().0;
        if medic_hp > 0 {
            if let Some(health) = heads.medic_heal(2, time.elapsed_secs()) {
                hitpoints.set_health(health);
            } else {
                continue;
            }
        }
    }
}
