// demo_pilot.hpp - IA de piloto para el attract mode (demo jugándose sola)
// © 2026 JailDesigner
//
// Calcula, cada frame, los controles de la nave (rotar/empujar/disparar) leyendo
// el estado de juego en solo-lectura. No lee Input ni muta entidades: GameScene
// aplica el Control resultante via Ship::applyMovement + fireBullet.
//
// El comportamiento busca parecer "humano", no óptimo: apuntado con lead y un
// pequeño error, cadencia de disparo con cooldown, esquiva por radio de peligro
// y sesgo hacia el centro para no pegarse a las paredes.

#pragma once

#include <SDL3/SDL.h>

#include <array>
#include <cstddef>
#include <cstdint>

#include "core/defaults/entities.hpp"
#include "core/system/scene_context.hpp"
#include "game/constants.hpp"
#include "game/entities/bullet.hpp"
#include "game/entities/enemy.hpp"
#include "game/entities/ship.hpp"

namespace Systems::Demo {

    // Escenari curat del attract mode: stage de arranque + nombre de naus IA.
    // Tots inclouen estrelles (que disparen) per donar feina al pilot.
    struct Scenario {
        std::uint8_t stage;    // stage_id de stages.yaml on arrenca la demo
        std::uint8_t players;  // 1 o 2 naus controlades per la IA
    };

    inline constexpr std::array<Scenario, SceneManager::SceneContext::DEMO_SCENARIO_COUNT>
        SCENARIOS = {{
            {.stage = 5, .players = 1},   // estrelles + mix, 1 jugador
            {.stage = 8, .players = 1},   // pressió alta, 1 jugador
            {.stage = 6, .players = 2},   // densitat alta, 2 jugadors (foc amic ON)
            {.stage = 10, .players = 2},  // repte final, 2 jugadors (foc amic ON)
        }};

    // Escenari per a l'índex donat (cíclic).
    [[nodiscard]] inline auto scenario(std::uint8_t index) -> Scenario {
        return SCENARIOS.at(index % SCENARIOS.size());
    }

    // Control de la nave para un frame.
    struct Control {
        bool left{false};
        bool right{false};
        bool thrust{false};
        bool shoot{false};
    };

    class DemoPilot {
       public:
        [[nodiscard]] auto compute(const Ship& ship,
            const std::array<Enemy, Constants::MAX_ORNIS>& enemies,
            const std::array<Bullet, static_cast<std::size_t>(Defaults::Entities::MAX_BULLETS_TOTAL)>& bullets,
            const SDL_FRect& play_area,
            float delta_time) -> Control;

       private:
        float retarget_timer_{0.0F};  // re-evalúa objetivo cada RETARGET_INTERVAL
        float fire_cooldown_{0.0F};   // tiempo restante hasta poder disparar
        float aim_jitter_{0.0F};      // error de apuntado, refrescado al retargetar
        int target_idx_{-1};          // índice del enemigo objetivo (o -1)
    };

}  // namespace Systems::Demo
