#pragma once

#include <SDL3/SDL.h>

#include <memory>
#include <string>
#include <vector>

#include "core/config/engine_config.hpp"
#include "scene_context.hpp"

class Scene;
class SDLManager;
namespace System {
    class DebugOverlay;
}

class Director {
   public:
    // El Director és el programa: posseeix la configuració (via ConfigYaml)
    // i orquestra tots els subsistemes. main.cpp és pur tràmit que el
    // construeix i delega cap a SDL.
    Director(int argc, char* argv[]);
    ~Director();

    // Una iteració del bucle: pivot d'escena si cal, delta time, update i
    // render. Retorna SDL_APP_CONTINUE per seguir, SDL_APP_SUCCESS si vol
    // sortir net, SDL_APP_FAILURE si no es pot recuperar.
    auto iterate() -> SDL_AppResult;

    // Enruta un sol esdeveniment cap a la cadena finestra → globals → F11 →
    // escena. Si detecta sortida (ESC doble, QUIT) marca wants_quit_ perquè
    // el següent iterate() retorni SDL_APP_SUCCESS.
    auto handleEvent(const SDL_Event& event) -> SDL_AppResult;

   private:
    std::string executable_path_;
    std::string system_folder_;
    Config::EngineConfig* cfg_{nullptr};

    // Subsistemes que viuen tant com el Director (abans eren locals de run()).
    // Preparació per a la migració a SDL_MAIN_USE_CALLBACKS: amb les 4
    // callbacks de SDL3 no hi ha un scope que englobi tot el bucle, així
    // que cal que aquest estat sigui membre del Director.
    std::unique_ptr<SDLManager> sdl_;
    std::unique_ptr<SceneManager::SceneContext> context_;
    std::unique_ptr<System::DebugOverlay> debug_overlay_;
    std::unique_ptr<Scene> current_scene_;

    Uint64 last_ticks_ms_{0};
    bool wants_quit_{false};

    auto checkProgramArguments(std::vector<std::string> const& args)
        -> std::string;
    void createSystemFolder(const std::string& folder);

    // Construye la escena correspondiente al tipo solicitado. Retorna
    // nullptr para EXIT u otros valores no constructibles.
    static auto buildScene(SceneManager::SceneContext::SceneType type,
        SDLManager& sdl,
        SceneManager::SceneContext& context)
        -> std::unique_ptr<Scene>;

    // Pivota a la següent escena: destrueix l'actual, llegeix context_->nextScene()
    // i construeix la nova. Retorna SDL_APP_SUCCESS si la nova és EXIT o no es pot
    // construir; SDL_APP_CONTINUE si tot OK.
    auto advanceScene() -> SDL_AppResult;
};
