#pragma once

#include <cstddef>  // Para size_t
#include <memory>   // Para unique_ptr
#include <string>   // Para basic_string, string
#include <utility>  // Para pair
#include <vector>   // Para vector

#include "ui_message.h"  // Para UIMessage

class MenuOption;
class MenuRenderer;  // <-- Nuevo

class ServiceMenu {
    public:
        enum class SettingsGroup {
            VIDEO,
            AUDIO,
            SETTINGS,
            SYSTEM,
            MAIN
        };

        enum class GroupAlignment {
            CENTERED,
            LEFT
        };

        // --- Constantes públicas que el Renderer podría necesitar ---
        static constexpr size_t OPTIONS_HORIZONTAL_PADDING = 20;
        static constexpr size_t MIN_WIDTH = 240;
        static constexpr size_t MIN_GAP_OPTION_VALUE = 30;

        // --- Métodos de singleton ---
        static void init();
        static void destroy();
        static auto get() -> ServiceMenu *;
        ServiceMenu(const ServiceMenu &) = delete;
        auto operator=(const ServiceMenu &) -> ServiceMenu & = delete;

        // --- Métodos principales ---
        void toggle();
        void render();
        void update();
        void reset();

        // --- Lógica de navegación ---
        void setSelectorUp();
        void setSelectorDown();
        void adjustOption(bool adjust_up);
        void selectOption();
        void moveBack();

        // --- Getters para que el Renderer pueda leer el estado ---
        [[nodiscard]] auto isEnabled() const -> bool { return enabled_; }
        [[nodiscard]] auto getTitle() const -> const std::string & { return title_; }
        [[nodiscard]] auto getCurrentGroup() const -> SettingsGroup { return current_settings_group_; }
        [[nodiscard]] auto getCurrentGroupAlignment() const -> GroupAlignment;
        [[nodiscard]] auto getDisplayOptions() const -> const std::vector<MenuOption *> & { return display_options_; }
        [[nodiscard]] auto getAllOptions() const -> const std::vector<std::unique_ptr<MenuOption>> & { return options_; }
        [[nodiscard]] auto getSelectedIndex() const -> size_t { return selected_; }
        [[nodiscard]] auto getOptionPairs() const -> const std::vector<std::pair<std::string, std::string>> & { return option_pairs_; }
        [[nodiscard]] auto countOptionsInGroup(SettingsGroup group) const -> size_t;

    private:
        // --- Lógica de estado del menú (Modelo) ---
        bool enabled_ = false;
        std::vector<std::unique_ptr<MenuOption>> options_;
        std::vector<MenuOption *> display_options_;
        std::vector<std::pair<std::string, std::string>> option_pairs_;

        SettingsGroup current_settings_group_;
        SettingsGroup previous_settings_group_;
        std::string title_;
        size_t selected_ = 0;
        size_t main_menu_selected_ = 0;

        // --- Mensaje de reinicio ---
        std::unique_ptr<UIMessage> restart_message_ui_;
        bool last_pending_changes_ = false;

        // --- La Vista ---
        std::unique_ptr<MenuRenderer> renderer_;

        // --- Métodos de lógica interna ---
        void updateDisplayOptions();
        void updateOptionPairs();
        void initializeOptions();
        void updateMenu();
        void applySettings();
        void applyVideoSettings();
        static void applyAudioSettings();
        void applySettingsSettings();
        [[nodiscard]] auto getOptionByCaption(const std::string &caption) const -> MenuOption *;
        void adjustListValues();
        static void playMoveSound();
        static void playAdjustSound();
        static void playSelectSound();
        static void playBackSound();
        [[nodiscard]] static auto settingsGroupToString(SettingsGroup group) -> std::string;
        void setHiddenOptions();

        // --- Constructores y destructor privados (singleton) ---
        ServiceMenu();
        ~ServiceMenu() = default;

        // --- Instancia singleton ---
        static ServiceMenu *instance;
};
