#include "BehaviorTargeting.h"

#include "CargoComponent.h"
#include "EntityAdmin.h"
#include "FactionComponent.h"
#include "HealthComponent.h"
#include "HqProxyComponent.h"
#include "PositionComponent.h"
#include "ShipIdentityComponent.h"
#include "StationBodyComponent.h"

std::vector<RepairableInfo> buildRepairables(EntityAdmin& admin)
{
    std::vector<RepairableInfo> repairables;

    admin.forEach<ShipIdentityComponent, PositionComponent, FactionComponent, HealthComponent>(
        [&repairables](entt::entity e, const ShipIdentityComponent& /*si*/,
                       const PositionComponent& pos, const FactionComponent& f,
                       const HealthComponent& h)
        {
            repairables.push_back({e, pos.value, f.isEnemy, true, h.hp, h.maxHp});
        });

    admin.forEach<StationBodyComponent, PositionComponent, FactionComponent, HealthComponent>(
        [&repairables, &admin](entt::entity e, const StationBodyComponent& /*sb*/,
                       const PositionComponent& pos, const FactionComponent& f,
                       const HealthComponent& h)
        {
            // The HQ is not a repair target — only ships and defence stations are
            // (REQ-SHP-REPAIR). In the balancing arena the HQ is spawned as a station,
            // so it is identified by its HqProxyComponent tag.
            if (admin.hasAll<HqProxyComponent>(e)) { return; }
            repairables.push_back({e, pos.value, f.isEnemy, false, h.hp, h.maxHp});
        });

    return repairables;
}

std::vector<CombatantInfo> buildCombatants(EntityAdmin& admin)
{
    std::vector<CombatantInfo> combatants;

    admin.forEach<PositionComponent, FactionComponent, ShipIdentityComponent>(
        [&combatants](entt::entity e, const PositionComponent& pos,
                      const FactionComponent& f, const ShipIdentityComponent& /*si*/)
        {
            combatants.push_back({e, pos.value, f.isEnemy, false});
        });

    admin.forEach<PositionComponent, FactionComponent, StationBodyComponent>(
        [&combatants](entt::entity e, const PositionComponent& pos,
                      const FactionComponent& f, const StationBodyComponent& /*sb*/)
        {
            combatants.push_back({e, pos.value, f.isEnemy, true});
        });

    admin.forEach<PositionComponent, FactionComponent, HqProxyComponent>(
        [&combatants, &admin](entt::entity e, const PositionComponent& pos,
                      const FactionComponent& f, const HqProxyComponent& /*hq*/)
        {
            // An arena HQ carries both StationBodyComponent and HqProxyComponent; it
            // is already listed by the station pass above, so skip it here to avoid
            // counting it twice.
            if (admin.hasAll<StationBodyComponent>(e)) { return; }
            combatants.push_back({e, pos.value, f.isEnemy, true});
        });

    return combatants;
}

std::unordered_map<entt::entity, CargoState> buildCargoByShip(EntityAdmin& admin)
{
    std::unordered_map<entt::entity, CargoState> cargoByShip;
    admin.forEach<CargoComponent>(
        [&cargoByShip](entt::entity ship, const CargoComponent& c)
        {
            cargoByShip[ship] = CargoState{c.current, c.maxCapacity};
        });
    return cargoByShip;
}

bool isCargoFull(const CargoState& cargo)
{
    return cargo.capacity > 0 && cargo.current >= cargo.capacity;
}
