#pragma once

#include "PlanetaryCore.h"
#include "warfactory/IDataNode.h"
#include <vector>

// Forward declaration for GTile
namespace warfactory {
    class GTile;
}

namespace warfactory {

/**
 * @brief Planetary cooling simulation managing heat transfer between surface and core
 *
 * Processes surface cooling by iterating through all tiles, cooling them down,
 * accumulating the released energy, and redistributing it between space evacuation
 * and core heating injection. Models realistic heat transfer during geological cycles.
 *
 * Process: Surface cools → Energy accumulated → Split between space loss and core transfer
 */
class CoolingPhaseFunction {
private:
    float surface_cooling_rate_per_cycle;         // °C reduction per cycle for surface tiles (base rate)
    float energy_to_core_ratio;                   // Fraction of accumulated energy transferred to core
    float energy_to_space_ratio;                  // Fraction of accumulated energy lost to space
    float minimum_surface_temperature;            // Absolute minimum surface temperature (°C)
    float minimum_core_temperature;               // Absolute minimum core temperature (°C)
    float optimal_cooling_core_temperature;       // Core temperature for maximum surface cooling efficiency (°C)
    float reference_surface_temperature;          // Reference surface temperature for cooling rate calculation (°C)

public:
    CoolingPhaseFunction();

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

    /**
     * @brief Configure cooling process from JSON parameters
     * @param config_node JSON configuration containing gradual_cooling parameters
     * Expected structure:
     * {
     *   "surface_cooling_rate_per_cycle": 50,
     *   "energy_to_core_ratio": 0.3,
     *   "energy_to_space_ratio": 0.7,
     *   "minimum_surface_temperature": -273,
     *   "minimum_core_temperature": 1000,
     *   "optimal_cooling_core_temperature": 2000,
     *   "reference_surface_temperature": 1000
     * }
     */
    void configure(const IDataNode& config_node);

    /**
     * @brief Set surface cooling rate per geological cycle
     * @param rate Temperature reduction in °C per cycle
     */
    void setSurfaceCoolingRate(float rate) { surface_cooling_rate_per_cycle = rate; }


    /**
     * @brief Set energy distribution ratios for accumulated heat
     * @param core_ratio Fraction transferred to planetary core (0.0 to 1.0)
     * @param space_ratio Fraction lost to space (0.0 to 1.0)
     * Note: core_ratio + space_ratio should equal 1.0
     */
    void setEnergyDistribution(float core_ratio, float space_ratio);

    /**
     * @brief Set minimum temperature thresholds
     * @param min_surface Minimum surface temperature in °C
     * @param min_core Minimum core temperature in °C
     */
    void setMinimumTemperatures(float min_surface, float min_core);

    // ========================================
    // COOLING PROCESS
    // ========================================

    /**
     * @brief Execute complete cooling phase for one geological cycle
     * @param tiles Array of surface tiles to cool (MODIFIED - temperatures reduced)
     * @param tile_count Number of tiles in the array
     * @param core Planetary core to process (MODIFIED - temperature affected by energy transfer)
     * @param cycle_duration_years Duration of current cycle in years
     * @return Total energy processed during cooling phase (Joules)
     */
    __uint128_t executeCoolingPhase(GTile* tiles, int tile_count, PlanetaryCore& core, double cycle_duration_years);

    /**
     * @brief Cool surface tiles and accumulate released energy
     * @param tiles Array of surface tiles to process
     * @param tile_count Number of tiles in the array
     * @param core_temperature Current core temperature for core influence calculation
     * @return Total energy released from surface cooling (Joules)
     *
     * Applies both influences:
     * - Core influence: Hot core slows surface cooling (heating from below)
     * - Surface temperature influence: Cold surface cools slower (less energy to evacuate)
     */
    __uint128_t coolSurfaceTiles(GTile* tiles, int tile_count, float core_temperature);

    /**
     * @brief Apply core cooling and energy injection
     * @param core Planetary core to process
     * @param accumulated_energy Total energy available for redistribution
     * @return Energy actually transferred to core (Joules)
     */
    __uint128_t processCoreEnergyTransfer(PlanetaryCore& core, __uint128_t accumulated_energy);

    /**
     * @brief Calculate energy evacuation to space
     * @param accumulated_energy Total energy available for loss
     * @return Energy lost to space (Joules)
     */
    __uint128_t calculateSpaceEvacuation(__uint128_t accumulated_energy) const;

    // ========================================
    // ANALYSIS AND UTILITIES
    // ========================================

    /**
     * @brief Calculate average surface temperature across all tiles
     * @param tiles Array of surface tiles to analyze
     * @param tile_count Number of tiles in the array
     * @return Average surface temperature in °C
     */
    float calculateAverageSurfaceTemperature(const GTile* tiles, int tile_count) const;

    /**
     * @brief Get total energy budget for this cooling cycle
     * @param tiles Surface tiles to analyze
     * @param tile_count Number of tiles
     * @param core Planetary core to analyze
     * @return Total available thermal energy (Joules)
     */
    __uint128_t calculateTotalEnergyBudget(const GTile* tiles, int tile_count, const PlanetaryCore& core) const;

    /**
     * @brief Check if cooling process is still active
     * @param average_surface_temp Current average surface temperature
     * @param core_temp Current core temperature
     * @return True if significant cooling is still occurring
     */
    bool isCoolingActive(float average_surface_temp, float core_temp) const;

    /**
     * @brief Calculate cooling efficiency based on temperature gradients
     * @param surface_temp Average surface temperature
     * @param core_temp Core temperature
     * @return Cooling efficiency factor (0.0 to 1.0)
     */
    float calculateCoolingEfficiency(float surface_temp, float core_temp) const;

    /**
     * @brief Calculate core influence factor on surface cooling rate
     * @param core_temperature Current core temperature in °C
     * @return Core influence multiplier (0.0 to 1.0)
     *
     * Logic: Hot core heats surface from below, slowing surface cooling
     * - Very hot core: Strong heating from below → slow surface cooling
     * - Cold core: No heating from below → normal surface cooling
     */
    float calculateCoreInfluence(float core_temperature) const;

    /**
     * @brief Calculate surface temperature influence on its own cooling rate (linear decline)
     * @param surface_temperature Current surface temperature in °C
     * @return Surface temperature multiplier (0.0 to 1.0)
     *
     * Linear physics logic:
     * - Very hot surface: Fast cooling (lots of energy to evacuate) → factor ≈ 1.0
     * - Warm surface: Moderate cooling → factor ≈ 0.5
     * - Cold surface: Slow cooling (little energy left) → factor ≈ 0.1
     * Formula: factor = surface_temp / reference_temp (clamped to 0.0-1.0)
     */
    float calculateSurfaceTemperatureInfluence(float surface_temperature) const;

    /**
     * @brief Get energy distribution summary for this cycle
     * @param total_energy Total energy processed
     * @return Map containing "core_transfer", "space_loss", "total" values
     */
    std::unordered_map<std::string, __uint128_t> getEnergyDistributionSummary(__uint128_t total_energy) const;

private:
    /**
     * @brief Convert temperature difference to thermal energy
     * @param temperature_delta Temperature reduction in °C
     * @param tile_mass Estimated mass of tile material (tonnes)
     * @return Thermal energy released (Joules)
     */
    __uint128_t convertTemperatureToEnergy(float temperature_delta, double tile_mass) const;

    /**
     * @brief Apply temperature reduction with minimum threshold check
     * @param current_temp Current temperature in °C
     * @param cooling_rate Temperature reduction to apply
     * @param minimum_temp Minimum allowed temperature
     * @return New temperature after cooling
     */
    float applyCoolingWithMinimum(float current_temp, float cooling_rate, float minimum_temp) const;

    /**
     * @brief Calculate Stefan-Boltzmann radiation loss to space
     * @param surface_temperature Surface temperature in °C
     * @return Radiation energy loss factor
     */
    float calculateRadiationLoss(float surface_temperature) const;

    /**
     * @brief Estimate tile mass for energy calculations
     * @param tile GTile to analyze
     * @return Estimated mass in tonnes
     */
    double estimateTileMass(const GTile& tile) const;

    /**
     * @brief Validate energy distribution ratios
     * @return True if ratios are valid (sum ≈ 1.0)
     */
    bool validateEnergyRatios() const;
};

} // namespace warfactory