// game_scene.hpp - Lógica principal del juego
// © 1999 Visente i Sergi (versión Pascal)
// © 2025 Port a C++20 con SDL3

#pragma once

#include <array>
#include <cstdint>
#include <memory>
#include <string>

#include "core/graphics/vector_text.hpp"
#include "core/physics/physics_world.hpp"
#include "core/rendering/sdl_manager.hpp"
#include "core/system/scene.hpp"
#include "core/system/scene_context.hpp"
#include "core/system/game_config.hpp"
#include "core/types.hpp"
#include "game/constants.hpp"
#include "game/effects/debris_manager.hpp"
#include "game/effects/floating_score_manager.hpp"
#include "game/entities/bullet.hpp"
#include "game/entities/enemy.hpp"
#include "game/entities/ship.hpp"
#include "game/stage_system/stage_config.hpp"
#include "game/stage_system/stage_manager.hpp"

// Game over state machine
enum class GameOverState : uint8_t {
    NONE,      // Normal gameplay
    CONTINUE,  // Continue countdown screen (9→0)
    GAME_OVER  // Final game over (returning to title)
};

// Clase principal del juego (escena)
class GameScene final : public Scene {
    public:
        explicit GameScene(SDLManager& sdl, SceneManager::SceneContext& context);
        ~GameScene() override = default;

        // Scene interface
        void handleEvent(const SDL_Event& event) override;
        void update(float delta_time) override;
        void draw() override;
        [[nodiscard]] auto isFinished() const -> bool override;

        // Inicialización del estado del juego (llamado por Director tras crear la escena).
        void init();

    private:
        SDLManager& sdl_;
        SceneManager::SceneContext& context_;
        GameConfig::MatchConfig match_config_;  // Configuración de jugadors active

        // Mundo físico (Fase 5) — integración cinemática + colisiones
        Physics::PhysicsWorld physics_world_;

        // Efectes visuals
        Effects::DebrisManager debris_manager_;
        Effects::FloatingScoreManager floating_score_manager_;

        // Estat del juego
        std::array<Ship, 2> ships_;  // [0]=P1, [1]=P2
        std::array<Enemy, Constants::MAX_ORNIS> enemies_;
        std::array<Bullet, Constants::MAX_BALES * 2> bullets_;  // 6 balas: P1=[0,1,2], P2=[3,4,5]
        std::array<float, 2> hit_timer_per_player_;  // Death timers per player (seconds)

        // Lives and game over system
        std::array<int, 2> lives_per_player_;  // [0]=P1, [1]=P2
        GameOverState game_over_state_;         // Game over state machine (NONE, CONTINUE, GAME_OVER)
        int continue_counter_;                  // Continue countdown (9→0)
        float continue_tick_timer_;             // Timer for countdown tick (1.0s)
        int continues_used_;                  // Continues used this game (0-3 max)
        float game_over_timer_;                 // Final GAME OVER timer before title screen
        Vec2 death_position_;                            // Death position (for respawn)
        std::array<int, 2> score_per_player_;  // [0]=P1, [1]=P2

        // Text vectorial
        Graphics::VectorText text_;

        // [NEW] Stage system
        std::unique_ptr<StageSystem::StageSystemConfig> stage_config_;
        std::unique_ptr<StageSystem::StageManager> stage_manager_;

        // Control de sons de animación INIT_HUD
        bool init_hud_rect_sound_played_;  // Flag para evitar repetir sonido del rectángulo

        // Funciones privades
        void tocado(uint8_t player_id);
        void dibuixar_marges() const;                                    // Dibuixar vores de la zona de juego
        void dibuixar_marcador();                                        // Dibuixar marcador de puntuación
        void disparar_bala(uint8_t player_id);                           // Shoot bullet from player
        [[nodiscard]] Vec2 obtenir_punt_spawn(uint8_t player_id) const;  // Get spawn position for player

        // [NEW] Continue & Join system
        void unir_jugador(uint8_t player_id);         // Join inactive player mid-game
        void dibuixar_continue();                     // Draw continue screen

        // [NEW] Stage system helpers
        void dibuixar_missatge_stage(const std::string& message);

        // [NEW] Función helper del marcador
        [[nodiscard]] std::string buildScoreboard() const;

        // Sub-pasos de update() (descompuestos en Fase 9d para reducir
        // complejidad cognitiva; cada uno es responsable de una sección).
        void stepPhysics(float delta_time);
        void stepShootingInput();
        void stepMidGameJoin();
        // Devuelven true si el frame debe salir tras esta sección.
        [[nodiscard]] auto stepContinueScreen(float delta_time) -> bool;
        [[nodiscard]] auto stepGameOver(float delta_time) -> bool;
        // Avanza el death timer / respawn / transition a CONTINUE. Devuelve
        // true si algun jugador está en secuencia de muerte (para que el
        // caller actualice efectos sin gameplay).
        [[nodiscard]] auto stepDeathSequence(float delta_time) -> bool;
        void stepStageStateMachine(float delta_time);
        void runStageInitHud(float delta_time);
        void runStageLevelStart(float delta_time);
        void runStagePlaying(float delta_time);
        void runStageLevelCompleted(float delta_time);
        // Helper: ejecuta colisiones de gameplay con el Context preparado.
        void runCollisionDetections();
};
