#pragma once

#include "IGenerationLayer.h"
#include "GMap.h"
#include <vector>
#include <memory>
#include <chrono>
#include <nlohmann/json.hpp>

using json = nlohmann::json;

namespace warfactory {

// Forward declarations
struct PlanetaryCore;

/**
 * @brief World generation orchestrator with step-by-step execution
 *
 * Manages multiple generation layers and provides cycle-by-cycle execution
 * with progress tracking, debugging, and configuration management.
 */
class WorldGenerationModule {
private:
    // ========================================
    // GENERATION STATE
    // ========================================
    std::unique_ptr<GMap> world_map;
    std::unique_ptr<PlanetaryCore> planetary_core;

    // Layer management
    std::vector<std::unique_ptr<IGenerationLayer>> layers;
    int current_layer_index = 0;

    // Configuration
    json global_config;
    uint64_t world_seed = 0;

    // Execution state
    bool generation_active = false;
    bool generation_complete = false;
    bool generation_paused = false;

    // Performance tracking
    std::chrono::steady_clock::time_point start_time;
    std::chrono::steady_clock::time_point last_step_time;
    float total_execution_time = 0.0f;
    int total_steps_executed = 0;

public:
    /**
     * @brief Constructor
     * @param width World map width
     * @param height World map height
     * @param seed World generation seed
     */
    WorldGenerationModule(int width, int height, uint64_t seed = 0);

    /**
     * @brief Destructor
     */
    ~WorldGenerationModule();

    // ========================================
    // LAYER MANAGEMENT
    // ========================================

    /**
     * @brief Add generation layer to pipeline
     * @param layer Layer to add (ownership transferred)
     */
    void addLayer(std::unique_ptr<IGenerationLayer> layer);

    /**
     * @brief Remove all layers
     */
    void clearLayers();

    /**
     * @brief Get number of registered layers
     * @return Layer count
     */
    size_t getLayerCount() const { return layers.size(); }

    /**
     * @brief Get current active layer
     * @return Current layer pointer or nullptr
     */
    IGenerationLayer* getCurrentLayer() const;

    /**
     * @brief Get layer by index
     * @param index Layer index
     * @return Layer pointer or nullptr if invalid index
     */
    IGenerationLayer* getLayer(size_t index) const;

    // ========================================
    // STEP-BY-STEP EXECUTION
    // ========================================

    /**
     * @brief Execute next generation step
     * @return true if more steps available
     */
    bool executeNextStep();

    /**
     * @brief Execute multiple steps
     * @param step_count Number of steps to execute
     * @return Number of steps actually executed
     */
    int executeSteps(int step_count);

    /**
     * @brief Execute current layer completely
     * @return true if layer completed successfully
     */
    bool executeCurrentLayer();

    /**
     * @brief Execute all remaining layers
     * @return true if generation completed successfully
     */
    bool executeAll();

    // ========================================
    // EXECUTION CONTROL
    // ========================================

    /**
     * @brief Start generation from beginning
     */
    void startGeneration();

    /**
     * @brief Pause generation
     */
    void pauseGeneration();

    /**
     * @brief Resume generation
     */
    void resumeGeneration();

    /**
     * @brief Stop and reset generation
     */
    void stopGeneration();

    /**
     * @brief Reset to initial state
     */
    void reset();

    // ========================================
    // PROGRESS TRACKING
    // ========================================

    /**
     * @brief Get overall generation progress
     * @return Progress percentage (0.0-1.0)
     */
    float getOverallProgress() const;

    /**
     * @brief Get current layer progress
     * @return Progress percentage (0.0-1.0)
     */
    float getCurrentLayerProgress() const;

    /**
     * @brief Get current step description
     * @return Human-readable step description
     */
    std::string getCurrentStepDescription() const;

    /**
     * @brief Get estimated remaining time
     * @return Estimated seconds remaining
     */
    float getEstimatedRemainingTime() const;

    /**
     * @brief Get total estimated duration
     * @return Estimated total seconds
     */
    float getTotalEstimatedDuration() const;

    // ========================================
    // STATE QUERIES
    // ========================================

    bool isGenerationActive() const { return generation_active; }
    bool isGenerationComplete() const { return generation_complete; }
    bool isGenerationPaused() const { return generation_paused; }
    bool hasMoreSteps() const;

    int getCurrentLayerIndex() const { return current_layer_index; }
    int getTotalStepsExecuted() const { return total_steps_executed; }
    float getTotalExecutionTime() const { return total_execution_time; }

    // ========================================
    // CONFIGURATION
    // ========================================

    /**
     * @brief Set global configuration
     * @param config JSON configuration
     */
    void setConfiguration(const json& config);

    /**
     * @brief Get current configuration
     * @return Current JSON configuration
     */
    const json& getConfiguration() const { return global_config; }

    /**
     * @brief Set world generation seed
     * @param seed New seed value
     */
    void setWorldSeed(uint64_t seed);

    /**
     * @brief Get world generation seed
     * @return Current seed
     */
    uint64_t getWorldSeed() const { return world_seed; }

    /**
     * @brief Validate all layer configurations
     * @return true if all configurations valid
     */
    bool validateConfigurations() const;

    // ========================================
    // WORLD ACCESS
    // ========================================

    /**
     * @brief Get generated world map
     * @return World map reference
     */
    const GMap& getWorldMap() const;

    /**
     * @brief Get mutable world map (for testing/debugging)
     * @return Mutable world map reference
     */
    GMap& getWorldMapMutable();

    /**
     * @brief Get planetary core state
     * @return Planetary core reference
     */
    const PlanetaryCore& getPlanetaryCore() const;

    // ========================================
    // DEBUGGING AND MONITORING
    // ========================================

    /**
     * @brief Get detailed generation status
     * @return JSON with complete status information
     */
    json getDetailedStatus() const;

    /**
     * @brief Get performance metrics
     * @return JSON with performance data
     */
    json getPerformanceMetrics() const;

    /**
     * @brief Enable verbose logging for all layers
     * @param enabled Whether to enable verbose output
     */
    void setVerboseLogging(bool enabled);

    /**
     * @brief Export current state for debugging
     * @return JSON with complete world state
     */
    json exportDebugState() const;

    /**
     * @brief Import state for debugging/testing
     * @param state Debug state to import
     */
    void importDebugState(const json& state);

    // ========================================
    // CONVENIENCE METHODS
    // ========================================

    /**
     * @brief Generate world with standard layers
     * @param config Optional configuration override
     * @return true if generation successful
     */
    bool generateStandardWorld(const json& config = json{});

    /**
     * @brief Generate world step-by-step with callback
     * @param callback Function called after each step
     * @return true if generation successful
     */
    bool generateWithCallback(std::function<bool(const WorldGenerationModule&)> callback);

private:
    // ========================================
    // INTERNAL HELPERS
    // ========================================

    /**
     * @brief Initialize planetary core
     */
    void initializePlanetaryCore();

    /**
     * @brief Setup standard generation layers
     */
    void setupStandardLayers();

    /**
     * @brief Update execution timing
     */
    void updateTiming();

    /**
     * @brief Advance to next layer
     * @return true if more layers available
     */
    bool advanceToNextLayer();

    /**
     * @brief Calculate overall progress across all layers
     * @return Combined progress (0.0-1.0)
     */
    float calculateOverallProgress() const;
};

/**
 * @brief Factory for creating standard layer configurations
 */
namespace StandardLayers {
    /**
     * @brief Create geological generation layer
     * @return Geological layer with default configuration
     */
    std::unique_ptr<IGenerationLayer> createGeologicalLayer();

    /**
     * @brief Create climate simulation layer
     * @return Climate layer with default configuration
     */
    std::unique_ptr<IGenerationLayer> createClimateLayer();

    /**
     * @brief Create biome classification layer
     * @return Biome layer with default configuration
     */
    std::unique_ptr<IGenerationLayer> createBiomeLayer();

    /**
     * @brief Create budget assignment layer
     * @return Budget layer with default configuration
     */
    std::unique_ptr<IGenerationLayer> createBudgetLayer();

    /**
     * @brief Create resource generation layer
     * @return Resource layer with default configuration
     */
    std::unique_ptr<IGenerationLayer> createResourceLayer();

    /**
     * @brief Create complete standard pipeline
     * @return Vector of all standard layers
     */
    std::vector<std::unique_ptr<IGenerationLayer>> createStandardPipeline();
}

} // namespace warfactory