#pragma once

#include <string>
#include <map>
#include <memory>
#include <nlohmann/json.hpp>
#include "warfactory/IDataNode.h"
#include "warfactory/RandomGenerator.h"

// Forward declarations
namespace warfactory {
    class Meteorite;
}

using json = nlohmann::json;

namespace warfactory {

/**
 * @brief Factory for procedural meteorite generation with feed/pull system
 *
 * Feed Phase: Configure global settings, load meteorite types, set weights
 * Pull Phase: Generate procedural meteorites based on configuration
 */
class MeteoriteFactory {
private:
    std::map<std::string, Meteorite> meteorite_templates;  // Pre-generated templates
    std::map<std::string, float> type_weights;             // From Regular_world.json
    std::string default_size_bias = "medium";

public:
    MeteoriteFactory();

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

    /**
     * @brief Set global configuration parameters
     * @param size_bias Default size bias ("small", "medium", "large", "massive")
     */
    void setDefaultSizeBias(const std::string& size_bias);

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

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

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

    // ========================================
    // PULL PHASE - Generation
    // ========================================

    /**
     * @brief Generate a procedural meteorite based on current configuration
     * @return Unique pointer to generated meteorite (copied from template + modified)
     */
    std::unique_ptr<Meteorite> getProceduralMeteorite();

    /**
     * @brief Generate a procedural meteorite with size override
     * @param size_override Size bias override ("small", "medium", "large", "massive")
     * @return Unique pointer to generated meteorite (copied from template + modified)
     */
    std::unique_ptr<Meteorite> getProceduralMeteorite(const std::string& size_override);

    /**
     * @brief Generate a specific meteorite type
     * @param meteorite_type Specific type to generate
     * @return Unique pointer to generated meteorite (copied from template + modified)
     */
    std::unique_ptr<Meteorite> createSpecificMeteorite(const std::string& meteorite_type);

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

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

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

    /**
     * @brief Get total weight sum for normalization
     */
    float getTotalWeight() const;

private:
    /**
     * @brief Generate templates from loaded meteorite types
     */
    void generateTemplates();

    /**
     * @brief Select random meteorite type based on weights
     */
    std::string selectRandomType() const;

    /**
     * @brief Apply size modifications to a copied meteorite
     */
    void applySizeModifications(Meteorite& meteorite, const std::string& size_bias) const;

    /**
     * @brief Apply size bias to mass calculation
     */
    float applySizeBias(float min_mass, float max_mass, const std::string& size_bias) const;
};

} // namespace warfactory