//  sdl_manager.hpp - Gestor de inicialización de SDL3
// © 2026 JailDesigner
//
// Tras la Fase 7 de la migración, el rendering ya no usa SDL_Renderer:
// SDLManager posee un GpuFrameRenderer (SDL3 GPU) que es el contexto único
// de dibujo del juego. El resto del código accede vía getRenderer() →
// Rendering::Renderer* (alias del GpuFrameRenderer).

#pragma once

#include <SDL3/SDL.h>

#include <cstdint>
#include <functional>

#include "core/config/engine_config.hpp"
#include "core/rendering/render_context.hpp"

class SDLManager {
   public:
    // `cfg` ha de viure tant com el manager (el posseeix el Director).
    // `on_persist` es crida després de mutar la config (per exemple a
    // toggleVSync) per delegar la persistència en una capa externa
    // (game/ConfigYaml::saveToFile), mantenint sdl_manager agnòstic.
    SDLManager(int width, int height, bool fullscreen, Config::EngineConfig& cfg, std::function<void()> on_persist = {});
    ~SDLManager();

    // No permetre còpia ni assignació
    SDLManager(const SDLManager&) = delete;
    auto operator=(const SDLManager&) -> SDLManager& = delete;

    // [NUEVO] Gestió de finestra dinàmica
    void increaseWindowSize();  // F2: +100px
    void decreaseWindowSize();  // F1: -100px
    void toggleFullscreen();    // F3
    void toggleVSync();         // F4
    void toggleAntialias();     // F5
    void togglePostFx();        // F6
    // Canvia la resolució del render target offscreen (recrea la textura).
    // Cal cridar-lo fora d'un frame (event phase, no draw phase). Si el
    // valor no es un preset valid o ja es l'actual, es no-op.
    void setRenderResolution(int w, int h);
    auto handleWindowEvent(const SDL_Event& event) -> bool;  // Per a SDL_EVENT_WINDOW_RESIZED

    // Funciones principals (renderizado).
    // clear() devuelve false si la swapchain no está disponible (p.ej.
    // ventana minimizada). El caller debe saltarse draw+present ese frame.
    [[nodiscard]] auto clear(uint8_t r = 0, uint8_t g = 0, uint8_t b = 0) -> bool;
    void present();

    // Getters
    auto getRenderer() -> Rendering::Renderer* { return &gpu_renderer_; }
    [[nodiscard]] auto getScaleFactor() const -> float { return zoom_factor_; }
    [[nodiscard]] auto isFullscreen() const -> bool { return is_fullscreen_; }
    [[nodiscard]] auto isPostFxEnabled() const -> bool { return gpu_renderer_.isPostFxEnabled(); }

    // [NUEVO] Actualitzar context de renderizado (factor de scale global)
    void updateRenderingContext() const;

   private:
    SDL_Window* finestra_{nullptr};
    Rendering::Renderer gpu_renderer_;  // GpuFrameRenderer (SDL3 GPU)
    Config::EngineConfig* cfg_;         // Propietat del Director, sobreviu al manager
    std::function<void()> on_persist_;  // Opcional: persistència delegada

    // [NUEVO] Estat de la finestra
    int current_width_;  // Mida física actual
    int current_height_;
    bool is_fullscreen_;
    int max_width_{1920};  // Fallback si no es pot llegir del display
    int max_height_{1080};

    // [ZOOM SYSTEM]
    float zoom_factor_;     // Current zoom (0.5x to max_zoom_)
    int windowed_width_;    // Saved size before fullscreen
    int windowed_height_;   // Saved size before fullscreen
    float max_zoom_{1.0F};  // Maximum zoom (calculated from display)

    // [NUEVO] Funciones internes
    void calculateMaxWindowSize();                // Llegir resolució del display
    void calculateMaxZoom();                      // Calculate max zoom from display
    void applyZoom(float new_zoom);               // Apply zoom and resize window
    void applyWindowSize(int width, int height);  // Canviar mida + centrar
    void updateViewport();                        // Configurar viewport con letterbox
};
