#pragma once

#include <SDL3/SDL.h>  // Para SDL_FPoint, SDL_FRect

#include <algorithm>  // Para min
#include <cstdint>    // Para std::uint8_t
#include <memory>     // Para allocator, shared_ptr
#include <string>     // Para string
#include <vector>     // Para vector

#include "core/rendering/text.hpp"  // Para Text
#include "utils/color.hpp"          // Para Color
#include "utils/param.hpp"          // Para param

class WindowMessage {
   public:
    enum class PositionMode : std::uint8_t {
        CENTERED,  // La ventana se centra en el punto especificado
        FIXED      // La esquina superior izquierda coincide con el punto
    };

    struct Config {
        // Colores
        Color bg_color;
        Color border_color;
        Color title_color;
        Color text_color;

        // Espaciado y dimensiones
        float padding{15.0F};
        float line_spacing{5.0F};
        float title_separator_spacing{10.0F};  // Espacio extra para separador del título

        // Límites de tamaño
        float min_width{200.0F};
        float min_height{100.0F};
        float max_width_ratio{0.8F};   // % máximo de ancho de pantalla
        float max_height_ratio{0.8F};  // % máximo de alto de pantalla

        // Margen de seguridad para texto
        float text_safety_margin{20.0F};  // Margen extra para evitar texto cortado

        // Animaciones
        float animation_duration{0.3F};  // Duración en segundos para todas las animaciones

        // Constructor con valores por defecto
        Config()
            : bg_color{40, 40, 60, 220},
              border_color{100, 100, 120, 255},
              title_color{255, 255, 255, 255},
              text_color{200, 200, 200, 255} {}

        // Constructor que convierte desde ParamServiceMenu::WindowMessage
        Config(const ParamServiceMenu::WindowMessage& param_config)
            : bg_color(param_config.bg_color),
              border_color(param_config.border_color),
              title_color(param_config.title_color),
              text_color(param_config.text_color),
              padding(param_config.padding),
              line_spacing(param_config.line_spacing),
              title_separator_spacing(param_config.title_separator_spacing),
              min_width(param_config.min_width),
              min_height(param_config.min_height),
              max_width_ratio(param_config.max_width_ratio),
              max_height_ratio(param_config.max_height_ratio),
              text_safety_margin(param_config.text_safety_margin),
              animation_duration(param_config.animation_duration) {}
    };

    WindowMessage(
        std::shared_ptr<Text> text_renderer,
        std::string title = "",
        const Config& config = Config{});

    // Métodos principales
    void render();
    void update(float delta_time);

    // Control de visibilidad
    void show();
    void hide();
    [[nodiscard]] auto isVisible() const -> bool { return visible_; }
    [[nodiscard]] auto isFullyVisible() const -> bool { return visible_ && !show_hide_animation_.active; }
    [[nodiscard]] auto isAnimating() const -> bool { return resize_animation_.active || show_hide_animation_.active; }

    // Configuración de contenido
    void setTitle(const std::string& title);
    void setText(const std::string& text);
    void setTexts(const std::vector<std::string>& texts);
    void addText(const std::string& text);
    void clearTexts();

    // Control de redimensionado automático
    void enableAutoResize(bool enabled) { auto_resize_enabled_ = enabled; }
    [[nodiscard]] auto isAutoResizeEnabled() const -> bool { return auto_resize_enabled_; }

    // Configuración de posición y tamaño
    void setPosition(float x, float y, PositionMode mode = PositionMode::CENTERED);
    void setSize(float width, float height);
    void centerOnScreen();
    void autoSize();  // Ajusta automáticamente al contenido y reposiciona si es necesario

    // Configuración de colores
    void setBackgroundColor(const Color& color) { config_.bg_color = color; }
    void setBorderColor(const Color& color) { config_.border_color = color; }
    void setTitleColor(const Color& color) {
        config_.title_color = color;
        updateStyles();
    }
    void setTextColor(const Color& color) {
        config_.text_color = color;
        updateStyles();
    }

    // Configuración de espaciado
    void setPadding(float padding) { config_.padding = padding; }
    void setLineSpacing(float spacing) { config_.line_spacing = spacing; }

    // Configuración avanzada
    void setConfig(const Config& config) {
        config_ = config;
        updateStyles();
    }
    [[nodiscard]] auto getConfig() const -> const Config& { return config_; }

    // Getters
    [[nodiscard]] auto getRect() const -> const SDL_FRect& { return rect_; }
    [[nodiscard]] auto getPositionMode() const -> PositionMode { return position_mode_; }
    [[nodiscard]] auto getAnchorPoint() const -> SDL_FPoint { return anchor_; }

   private:
    std::shared_ptr<Text> text_renderer_;
    Config config_;

    // Estado de visibilidad y redimensionado
    bool visible_ = false;
    bool auto_resize_enabled_ = true;  // Por defecto habilitado

    // Contenido
    std::string title_;
    std::vector<std::string> texts_;

    // Posición y tamaño
    SDL_FRect rect_{.x = 0, .y = 0, .w = 300, .h = 200};
    PositionMode position_mode_ = PositionMode::CENTERED;
    SDL_FPoint anchor_{.x = 0.0F, .y = 0.0F};

    // Animación de redimensionado
    struct ResizeAnimation {
        bool active = false;
        float start_width, start_height;
        float target_width, target_height;
        float elapsed = 0.0F;

        void start(float from_w, float from_h, float to_w, float to_h) {
            start_width = from_w;
            start_height = from_h;
            target_width = to_w;
            target_height = to_h;
            elapsed = 0.0F;
            active = true;
        }

        void stop() {
            active = false;
            elapsed = 0.0F;
        }

        [[nodiscard]] auto isFinished(float duration) const -> bool {
            return elapsed >= duration;
        }

        [[nodiscard]] auto getProgress(float duration) const -> float {
            return std::min(elapsed / duration, 1.0F);
        }
    } resize_animation_;

    // Animación de mostrar/ocultar
    struct ShowHideAnimation {
        enum class Type : std::uint8_t { NONE,
            SHOWING,
            HIDING };

        Type type = Type::NONE;
        bool active = false;
        float target_width, target_height;  // Tamaño final al mostrar
        float elapsed = 0.0F;

        void startShow(float to_w, float to_h) {
            type = Type::SHOWING;
            target_width = to_w;
            target_height = to_h;
            elapsed = 0.0F;
            active = true;
        }

        void startHide() {
            type = Type::HIDING;
            elapsed = 0.0F;
            active = true;
        }

        void stop() {
            type = Type::NONE;
            active = false;
            elapsed = 0.0F;
        }

        [[nodiscard]] auto isFinished(float duration) const -> bool {
            return elapsed >= duration;
        }

        [[nodiscard]] auto getProgress(float duration) const -> float {
            return std::min(elapsed / duration, 1.0F);
        }
    } show_hide_animation_;

    // Estilos
    Text::Style title_style_;
    Text::Style text_style_;

    // Métodos privados
    void calculateAutoSize();
    void updatePosition();                           // Actualiza la posición según el modo y punto de anclaje
    void updateStyles();                             // Actualiza los estilos de texto cuando cambian los colores
    void ensureTextFits();                           // Verifica y ajusta para que todo el texto sea visible
    void triggerAutoResize();                        // Inicia redimensionado automático si está habilitado
    void updateAnimation(float delta_time);          // Actualiza la animación de redimensionado
    void updateShowHideAnimation(float delta_time);  // Actualiza la animación de mostrar/ocultar
    void updateResizeAnimation(float delta_time);    // Actualiza la animación de redimensionado

    // Función de suavizado (ease-out)
    [[nodiscard]] static auto easeOut(float t) -> float;

    // Métodos para manejo de texto durante animación
    [[nodiscard]] auto getTruncatedText(const std::string& text, float available_width) const -> std::string;
    [[nodiscard]] auto getAvailableTextWidth() const -> float;
    [[nodiscard]] auto shouldShowContent() const -> bool;  // Si mostrar el contenido (texto, líneas, etc.)

    [[nodiscard]] auto calculateContentHeight() const -> float;
    [[nodiscard]] auto calculateContentWidth() const -> float;
    [[nodiscard]] static auto getScreenWidth() -> float;
    [[nodiscard]] static auto getScreenHeight() -> float;
};