use crate::{
    abilities::TriggerCashHeal, cash::CashResource, global_observer, hitpoints::Hitpoints,
    player::Player, sounds::PlaySound,
};
use bevy::prelude::*;

pub fn plugin(app: &mut App) {
    global_observer!(app, on_heal_trigger);
}

#[derive(Debug, PartialEq, Eq)]
struct HealAction {
    cost: i32,
    damage_healed: u32,
}

fn on_heal_trigger(
    _trigger: Trigger<TriggerCashHeal>,
    mut cmds: Commands,
    mut cash: ResMut<CashResource>,
    mut query: Query<&mut Hitpoints, With<Player>>,
) {
    let Ok(mut hp) = query.single_mut() else {
        return;
    };

    if hp.max() || cash.cash == 0 {
        return;
    }

    let action = heal(cash.cash, hp.get().1 - hp.get().0);

    hp.heal(action.damage_healed);

    cash.cash = cash.cash.saturating_sub(action.cost);

    //TODO: trigger ui cost animation
    cmds.trigger(PlaySound::CashHeal);
}

fn heal(cash: i32, damage: u32) -> HealAction {
    let cost = (damage as f32 / 10. * 25.) as i32;

    if cash >= cost {
        HealAction {
            cost,
            damage_healed: damage,
        }
    } else {
        let damage_healed = (cash as f32 * 10. / 25.) as u32;

        HealAction {
            cost: cash,
            damage_healed,
        }
    }
}

#[cfg(test)]
mod test {
    use super::*;

    #[test]
    fn test_heal() {
        assert_eq!(
            heal(100, 10),
            HealAction {
                cost: 25,
                damage_healed: 10
            }
        );

        assert_eq!(
            heal(100, 90),
            HealAction {
                cost: 100,
                damage_healed: 40
            }
        );
    }
}
