#pragma once

#include "Volcano.h"
#include "VolcanoImpact.h"
#include "PlanetaryCore.h"
#include "warfactory/IDataNode.h"
#include "warfactory/ResourceRegistry.h"
#include "warfactory/RandomGenerator.h"
#include <map>
#include <memory>
#include <vector>
#include <string>

namespace warfactory {

// Forward declaration for heightmap
class GTile;

/**
 * @brief Factory for procedural volcano generation with create→apply→destroy cycle
 *
 * Generates volcanos for 100M year cycles, applies their effects via VolcanoImpact,
 * then destroys them. Directly modifies PlanetaryCore by deducting used resources.
 * Places volcanos on lowest elevation zones from heightmap data.
 */
class VolcanoFactory {
private:
    std::map<std::string, Volcano> volcano_templates;  // Pre-generated volcano templates
    std::map<std::string, float> type_weights;         // Volcano type probabilities
    std::string default_volcano_type = "stratovolcano";

    // Semi-fixed resource extraction values (from JSON config)
    uint64_t base_material_per_volcano = 1000000000000; // 1e12 tonnes base extraction
    int main_pick_count = 3;                           // Number of primary resources per volcano
    int secondary_pick_count = 5;                      // Number of secondary resources per volcano

    // ID generation
    uint32_t next_volcano_id = 1;              // Auto-increment volcano ID counter

public:
    VolcanoFactory();

    // ========================================
    // FEED PHASE - Configuration
    // ========================================

    /**
     * @brief Configure factory from JSON world generation parameters
     * @param config_node JSON configuration containing volcanic_generation settings
     * Expected structure:
     * {
     *   "volcanic_generation": {
     *     "base_material_per_volcano": 1000000000000,
     *     "main_pick_count": 3,
     *     "secondary_pick_count": 5,
     *     "default_volcano_type": "stratovolcano"
     *   }
     * }
     */
    void configure(const IDataNode& config_node);

    /**
     * @brief Set default volcano type for generation
     * @param volcano_type Default type ("shield", "stratovolcano", "caldera", "cinder_cone")
     */
    void setDefaultVolcanoType(const std::string& volcano_type);

    /**
     * @brief Load volcano types from volcanoes.json and generate templates
     * @param json_path Path to volcanoes.json file
     */
    void loadVolcanoTypes(const std::string& json_path);

    /**
     * @brief Set type weights for random volcano type selection
     * @param weights Map of volcano type -> weight
     */
    void setTypeWeights(const std::map<std::string, float>& weights);

    /**
     * @brief Get available volcano types
     */
    std::vector<std::string> getAvailableTypes() const;

    // ========================================
    // PULL PHASE - Generation (Create→Apply→Destroy cycle)
    // ========================================

    /**
     * @brief Generate volcano from core and place on lowest elevation zones
     * @param core Planetary core to extract resources from (MODIFIED - resources deducted)
     * @param heightmap_tiles Array of GTile heightmap data for placement
     * @param map_width Width of heightmap in tiles
     * @param map_height Height of heightmap in tiles
     * @return Unique pointer to generated volcano placed on optimal elevation
     */
    std::unique_ptr<Volcano> generateVolcanoFromCore(PlanetaryCore& core,
                                                    const GTile* heightmap_tiles,
                                                    int map_width, int map_height);

    /**
     * @brief Generate volcano with specific type from core
     * @param core Planetary core to extract resources from (MODIFIED - resources deducted)
     * @param volcano_type Specific volcano type to generate
     * @param heightmap_tiles Array of GTile heightmap data for placement
     * @param map_width Width of heightmap in tiles
     * @param map_height Height of heightmap in tiles
     * @return Unique pointer to generated volcano
     */
    std::unique_ptr<Volcano> generateSpecificVolcanoFromCore(PlanetaryCore& core,
                                                            const std::string& volcano_type,
                                                            const GTile* heightmap_tiles,
                                                            int map_width, int map_height);

    /**
     * @brief Generate VolcanoImpact from existing volcano for terrain modification
     * @param volcano Source volcano to generate impact from
     * @return Unique pointer to VolcanoImpact with calculated effects
     */
    std::unique_ptr<VolcanoImpact> generateVolcanoImpact(const Volcano& volcano);

    // ========================================
    // UTILITY
    // ========================================

    /**
     * @brief Check if factory is properly configured
     */
    bool isConfigured() const;

    /**
     * @brief Reset all configuration and templates
     */
    void reset();

    /**
     * @brief Get total type weights for normalization
     */
    float getTotalTypeWeight() const;

private:
    /**
     * @brief Select random volcano type based on weights
     */
    std::string selectRandomVolcanoType() const;

    /**
     * @brief Calculate semi-fixed material extraction based on core conditions
     * @param core Planetary core to analyze
     * @return Total material to extract for this volcano in tonnes
     * Formula: base_material ± variation based on core temperature/pressure
     */
    uint64_t calculateMaterialExtraction(const PlanetaryCore& core) const;

    /**
     * @brief Pick main and secondary resources from core composition
     * @param core Planetary core to select from
     * @param total_material Total material budget to distribute
     * @return Resource composition for volcano reservoir (main + secondary picks)
     */
    std::unordered_map<uint32_t, uint64_t> pickVolcanicResources(const PlanetaryCore& core,
                                                                uint64_t total_material) const;

    /**
     * @brief Deduct used resources from planetary core
     * @param core Planetary core to modify
     * @param extracted_resources Resources to remove from core
     */
    void deductResourcesFromCore(PlanetaryCore& core,
                                const std::unordered_map<uint32_t, uint64_t>& extracted_resources) const;

    /**
     * @brief Find optimal volcano placement position from heightmap
     * @param heightmap_tiles Array of GTile heightmap data
     * @param map_width Width of heightmap in tiles
     * @param map_height Height of heightmap in tiles
     * @return Position (x, y) in world coordinates for volcano placement
     */
    std::pair<float, float> findOptimalVolcanoPlacement(const GTile* heightmap_tiles,
                                                       int map_width, int map_height) const;

    /**
     * @brief Check if resource can melt at core temperature
     * @param resource_id Resource to check
     * @param core_temperature Current core temperature in Celsius
     * @return True if resource melts at given temperature
     */
    bool isResourceMolten(uint32_t resource_id, float core_temperature) const;

    /**
     * @brief Get resource melting point from ResourceRegistry
     * @param resource_id Resource to check
     * @return Melting point in Celsius
     */
    float getResourceMeltingPoint(uint32_t resource_id) const;

    /**
     * @brief Generate next unique volcano ID
     * @return Unique uint32_t ID for new volcano
     */
    uint32_t generateVolcanoId();
};

} // namespace warfactory