#pragma once

#include <nlohmann/json.hpp>

using json = nlohmann::json;

namespace warfactory {

/**
 * @brief Planetary core system for mass conservation
 *
 * Manages planetary mass conservation by accumulating eroded material
 * and releasing it through volcanic activity when core reaches saturation.
 */
struct PlanetaryCore {
    // ========================================
    // MASS TRACKING
    // ========================================
    float core_mass;                    // Accumulated eroded material (kg)
    float surface_mass;                 // Current surface terrain mass (kg)
    float total_planetary_mass;         // Constant after Phase 1 (kg)

    // ========================================
    // VOLCANIC SYSTEM
    // ========================================
    float max_core_capacity;            // Core saturation threshold (kg)
    float volcanic_overflow_rate;       // Rate of material expulsion (0.1-0.3)
    float pending_volcanic_material;    // Material queued for volcanic release (kg)
    int pending_volcanic_events;        // Number of queued eruptions

    // ========================================
    // CONFIGURATION PARAMETERS
    // ========================================
    float volcanic_event_mass_threshold;    // Minimum mass per volcanic event (kg)
    float volcanic_density_factor;           // Material density for eruption radius calculation
    float core_pressure_buildup_rate;       // Rate of pressure increase

    // ========================================
    // DERIVED VALUES
    // ========================================

    /**
     * @brief Get core pressure ratio (0.0-1.0+)
     * @return core_mass / max_core_capacity
     */
    float getCorePressureRatio() const {
        return core_mass / max_core_capacity;
    }

    /**
     * @brief Check if core is approaching saturation
     * @return true if pressure ratio > 0.8
     */
    bool isNearSaturation() const {
        return getCorePressureRatio() > 0.8f;
    }

    /**
     * @brief Check if core overflow is occurring
     * @return true if core_mass > max_core_capacity
     */
    bool isOverflowing() const {
        return core_mass > max_core_capacity;
    }

    /**
     * @brief Get overflow amount
     * @return Amount of mass above capacity (0 if no overflow)
     */
    float getOverflowAmount() const {
        return std::max(0.0f, core_mass - max_core_capacity);
    }

    /**
     * @brief Validate mass conservation
     * @return true if total mass is conserved
     */
    bool validateMassConservation() const {
        float total_current = core_mass + surface_mass + pending_volcanic_material;
        float tolerance = total_planetary_mass * 0.001f; // 0.1% tolerance
        return std::abs(total_current - total_planetary_mass) < tolerance;
    }

    // ========================================
    // CONSTRUCTION AND INITIALIZATION
    // ========================================

    /**
     * @brief Default constructor
     */
    PlanetaryCore() :
        core_mass(0.0f),
        surface_mass(0.0f),
        total_planetary_mass(0.0f),
        max_core_capacity(0.0f),
        volcanic_overflow_rate(0.2f),
        pending_volcanic_material(0.0f),
        pending_volcanic_events(0),
        volcanic_event_mass_threshold(1000000.0f),  // 1M kg per event
        volcanic_density_factor(100000.0f),         // 100k kg/m²
        core_pressure_buildup_rate(0.1f)
    {}

    /**
     * @brief Initialize core for world generation
     * @param initial_surface_mass Starting surface mass
     * @param capacity_ratio Core capacity as ratio of total mass (0.3-0.7)
     */
    void initialize(float initial_surface_mass, float capacity_ratio = 0.5f) {
        surface_mass = initial_surface_mass;
        total_planetary_mass = initial_surface_mass;
        core_mass = 0.0f;
        max_core_capacity = total_planetary_mass * capacity_ratio;
        pending_volcanic_material = 0.0f;
        pending_volcanic_events = 0;
    }

    // ========================================
    // MASS TRANSFER OPERATIONS
    // ========================================

    /**
     * @brief Transfer eroded material to core
     * @param erosion_amount Amount of material eroded (kg)
     */
    void addErodedMaterial(float erosion_amount) {
        core_mass += erosion_amount;
        surface_mass -= erosion_amount;
    }

    /**
     * @brief Add meteorite material to system (Phase 1 only)
     * @param meteorite_mass Mass of meteorite impact (kg)
     */
    void addMeteoriteMaterial(float meteorite_mass) {
        surface_mass += meteorite_mass;
        total_planetary_mass += meteorite_mass;

        // Update core capacity proportionally
        max_core_capacity = total_planetary_mass * (max_core_capacity / (total_planetary_mass - meteorite_mass));
    }

    /**
     * @brief Release volcanic material to surface
     * @param volcanic_amount Amount of material to release (kg)
     */
    void releaseVolcanicMaterial(float volcanic_amount) {
        if (volcanic_amount <= pending_volcanic_material) {
            pending_volcanic_material -= volcanic_amount;
            surface_mass += volcanic_amount;
        }
    }

    // ========================================
    // VOLCANIC OVERFLOW PROCESSING
    // ========================================

    /**
     * @brief Process core overflow and generate volcanic events
     */
    void processOverflow() {
        if (!isOverflowing()) return;

        float overflow = getOverflowAmount();
        float volcanic_expulsion = overflow * volcanic_overflow_rate;

        // Transfer mass from core to pending volcanic events
        core_mass -= volcanic_expulsion;
        pending_volcanic_material += volcanic_expulsion;

        // Queue volcanic events proportional to overflow
        int new_events = static_cast<int>(volcanic_expulsion / volcanic_event_mass_threshold);
        pending_volcanic_events += new_events;
    }

    /**
     * @brief Get material amount for next volcanic event
     * @return Material amount per event (kg)
     */
    float getNextVolcanicEventMaterial() const {
        if (pending_volcanic_events <= 0) return 0.0f;
        return pending_volcanic_material / pending_volcanic_events;
    }

    /**
     * @brief Consume one volcanic event
     * @return Material amount released (kg)
     */
    float consumeVolcanicEvent() {
        if (pending_volcanic_events <= 0) return 0.0f;

        float event_material = getNextVolcanicEventMaterial();
        pending_volcanic_events--;

        return event_material;
    }

    // ========================================
    // STATISTICS AND MONITORING
    // ========================================

    /**
     * @brief Get core statistics
     * @return JSON with detailed core information
     */
    json getStatistics() const {
        return json{
            {"core_mass", core_mass},
            {"surface_mass", surface_mass},
            {"total_planetary_mass", total_planetary_mass},
            {"max_core_capacity", max_core_capacity},
            {"pending_volcanic_material", pending_volcanic_material},
            {"pending_volcanic_events", pending_volcanic_events},
            {"core_pressure_ratio", getCorePressureRatio()},
            {"is_near_saturation", isNearSaturation()},
            {"is_overflowing", isOverflowing()},
            {"overflow_amount", getOverflowAmount()},
            {"mass_conservation_valid", validateMassConservation()}
        };
    }

    /**
     * @brief Export core state to JSON
     * @return JSON representation
     */
    json toJson() const {
        return json{
            {"core_mass", core_mass},
            {"surface_mass", surface_mass},
            {"total_planetary_mass", total_planetary_mass},
            {"max_core_capacity", max_core_capacity},
            {"volcanic_overflow_rate", volcanic_overflow_rate},
            {"pending_volcanic_material", pending_volcanic_material},
            {"pending_volcanic_events", pending_volcanic_events},
            {"volcanic_event_mass_threshold", volcanic_event_mass_threshold},
            {"volcanic_density_factor", volcanic_density_factor},
            {"core_pressure_buildup_rate", core_pressure_buildup_rate}
        };
    }

    /**
     * @brief Import core state from JSON
     * @param data JSON data to import
     */
    void fromJson(const json& data) {
        core_mass = data.value("core_mass", 0.0f);
        surface_mass = data.value("surface_mass", 0.0f);
        total_planetary_mass = data.value("total_planetary_mass", 0.0f);
        max_core_capacity = data.value("max_core_capacity", 0.0f);
        volcanic_overflow_rate = data.value("volcanic_overflow_rate", 0.2f);
        pending_volcanic_material = data.value("pending_volcanic_material", 0.0f);
        pending_volcanic_events = data.value("pending_volcanic_events", 0);
        volcanic_event_mass_threshold = data.value("volcanic_event_mass_threshold", 1000000.0f);
        volcanic_density_factor = data.value("volcanic_density_factor", 100000.0f);
        core_pressure_buildup_rate = data.value("core_pressure_buildup_rate", 0.1f);
    }
};

} // namespace warfactory