#pragma once

#include <cstddef>     // Para size_t
#include <functional>  // Para function
#include <optional>    // Para optional
#include <string>      // Para basic_string, string
#include <vector>      // Para vector

#include "core/system/stage_interface.hpp"  // for IStageInfo

// --- Enums ---
enum class PowerCollectionState {
    ENABLED,  // Recolección habilitada
    DISABLED  // Recolección deshabilitada
};

enum class StageStatus {
    LOCKED,       // Fase bloqueada
    IN_PROGRESS,  // Fase en progreso
    COMPLETED     // Fase completada
};

// --- Clase StageData: representa los datos de una fase del juego ---
class StageData {
   public:
    // --- Constructor ---
    StageData(int power_to_complete, int min_menace, int max_menace, std::string name = "");  // Constructor de una fase

    // --- Getters ---
    [[nodiscard]] auto getPowerToComplete() const -> int { return power_to_complete_; }           // Obtiene el poder necesario para completar
    [[nodiscard]] auto getMinMenace() const -> int { return min_menace_; }                        // Obtiene el nivel mínimo de amenaza
    [[nodiscard]] auto getMaxMenace() const -> int { return max_menace_; }                        // Obtiene el nivel máximo de amenaza
    [[nodiscard]] auto getName() const -> const std::string& { return name_; }                    // Obtiene el nombre de la fase
    [[nodiscard]] auto getStatus() const -> StageStatus { return status_; }                       // Obtiene el estado actual
    [[nodiscard]] auto isCompleted() const -> bool { return status_ == StageStatus::COMPLETED; }  // Verifica si está completada

    // --- Setters ---
    void setStatus(StageStatus status) { status_ = status; }  // Establece el estado de la fase

   private:
    // --- Variables de estado ---
    StageStatus status_;     // Estado actual de la fase
    std::string name_;       // Nombre de la fase
    int power_to_complete_;  // Poder necesario para completar la fase
    int min_menace_;         // Nivel mínimo de amenaza
    int max_menace_;         // Nivel máximo de amenaza
};

// --- Clase StageManager: gestor principal del sistema de fases del juego ---
class StageManager : public IStageInfo {
   public:
    // --- Tipos ---
    using PowerChangeCallback = std::function<void(int)>;  // Callback para cambios de poder

    // --- Constructor ---
    StageManager();  // Constructor principal

    // --- Métodos principales del juego ---
    void initialize();                                // Inicializa el gestor de fases
    void initialize(const std::string& stages_file);  // Inicializa con archivo personalizado
    void reset();                                     // Reinicia el progreso del juego
    auto advanceToNextStage() -> bool;                // Avanza a la siguiente fase

    // --- Gestión de poder ---
    auto subtractPower(int amount) -> bool;  // Resta poder de la fase actual
    void enablePowerCollection() override;   // Habilita la recolección de poder
    void disablePowerCollection();           // Deshabilita la recolección de poder

    // --- Navegación ---
    auto jumpToStage(size_t target_stage_index) -> bool;  // Salta a una fase específica
    auto setTotalPower(int target_total_power) -> bool;   // Establece el poder total y ajusta fase/progreso

    // --- Consultas de estado ---
    [[nodiscard]] auto getCurrentStage() const -> std::optional<StageData>;                     // Obtiene la fase actual
    [[nodiscard]] auto getStage(size_t index) const -> std::optional<StageData>;                // Obtiene una fase específica
    [[nodiscard]] auto getCurrentStageIndex() const -> size_t { return current_stage_index_; }  // Obtiene el índice de la fase actual
    [[nodiscard]] auto getCurrentPower() const -> int { return current_power_; }                // Obtiene el poder actual
    [[nodiscard]] auto getTotalPower() const -> int { return total_power_; }                    // Obtiene el poder total acumulado
    [[nodiscard]] auto getTotalPowerNeededToCompleteGame() const -> int;                        // Poder total necesario para completar el juego
    [[nodiscard]] auto getPowerNeededToReachStage(size_t target_stage_index) const -> int;      // Poder necesario para llegar a la fase X
    [[nodiscard]] auto getTotalStages() const -> size_t { return stages_.size(); }              // Obtiene el número total de fases

    // --- Seguimiento de progreso ---
    [[nodiscard]] auto isCurrentStageCompleted() const -> bool;              // Verifica si la fase actual está completada
    [[nodiscard]] auto isGameCompleted() const -> bool;                      // Verifica si el juego está completado
    [[nodiscard]] auto getProgressPercentage() const -> double;              // Progreso total del juego (0-100%)
    [[nodiscard]] auto getCurrentStageProgressPercentage() const -> double;  // Progreso de la fase actual (0-100%)
    [[nodiscard]] auto getCurrentStageProgressFraction() const -> double;    // Progreso de la fase actual (0.0-1.0)
    [[nodiscard]] auto getPowerNeededForCurrentStage() const -> int;         // Poder restante para completar la fase actual

    // --- Gestión de callbacks ---
    void setPowerChangeCallback(PowerChangeCallback callback);  // Establece callback para cambios de poder
    void removePowerChangeCallback();                           // Elimina callback de cambios de poder

    // --- Implementación de la interfaz IStageInfo ---
    [[nodiscard]] auto canCollectPower() const -> bool override;       // Verifica si se puede recolectar poder
    void addPower(int amount) override;                                // Añade poder a la fase actual
    [[nodiscard]] auto getCurrentMenaceLevel() const -> int override;  // Obtiene el nivel de amenaza actual

   private:
    // --- Variables de estado ---
    std::vector<StageData> stages_;                // Lista de todas las fases
    PowerChangeCallback power_change_callback_;    // Callback para notificar cambios de poder
    PowerCollectionState power_collection_state_;  // Estado de recolección de poder
    size_t current_stage_index_;                   // Índice de la fase actual
    int current_power_;                            // Poder actual en la fase activa
    int total_power_;                              // Poder total acumulado en todo el juego

    // --- Métodos internos ---
    void createDefaultStages();                                         // Crea las fases predeterminadas del juego
    auto loadStagesFromFile(const std::string& filename) -> bool;       // Carga fases desde archivo
    [[nodiscard]] auto validateStageIndex(size_t index) const -> bool;  // Valida que un índice de fase sea válido
    void updateStageStatuses();                                         // Actualiza los estados de todas las fases
};