#pragma once

#include "Volcano.h"
#include "warfactory/ResourceRegistry.h"
#include <unordered_map>
#include <vector>

namespace warfactory {

/**
 * @brief Represents physical impact effects of volcanic activity on terrain
 *
 * Models terrain modifications, resource distribution, and environmental effects
 * caused by volcanic eruptions. Handles both single eruptions and cumulative
 * effects over geological time periods.
 */
class VolcanoImpact {
public:
    enum class ImpactType {
        LAVA_FLOW,      // Gradual terrain elevation, high temperature zones
        EXPLOSIVE,      // Crater formation, debris distribution
        ASH_FALL,       // Wide-area resource distribution, fertility changes
        PYROCLASTIC     // Destructive flow patterns, terrain sculpting
    };

private:
    uint32_t volcano_id;                                    // Source volcano ID
    ImpactType impact_type;                                 // Type of volcanic impact
    float crater_radius_meters;                             // Crater/impact zone radius
    float crater_depth_meters;                              // Depth modification to terrain
    std::unordered_map<uint32_t, uint64_t> ejected_materials; // Resources distributed by eruption
    float temperature_increase_celsius;                     // Local temperature effect
    float terrain_elevation_change_meters;                  // Height change from lava/debris
    double impact_timestamp;                                // When impact occurred (years)
    float affected_area_radius_meters;                      // Total area of effect
    bool is_active_impact;                                  // Still affecting terrain

public:
    VolcanoImpact();
    VolcanoImpact(uint32_t volcano_id, ImpactType type);

    // ========================================
    // IMPACT PROPERTIES
    // ========================================

    uint32_t getVolcanoId() const { return volcano_id; }
    void setVolcanoId(uint32_t id) { volcano_id = id; }

    ImpactType getImpactType() const { return impact_type; }
    void setImpactType(ImpactType type) { impact_type = type; }

    float getCraterRadius() const { return crater_radius_meters; }
    float getCraterDepth() const { return crater_depth_meters; }
    void setCraterDimensions(float radius_meters, float depth_meters);

    float getTemperatureIncrease() const { return temperature_increase_celsius; }
    void setTemperatureIncrease(float temperature_celsius) { temperature_increase_celsius = temperature_celsius; }

    float getTerrainElevationChange() const { return terrain_elevation_change_meters; }
    void setTerrainElevationChange(float elevation_meters) { terrain_elevation_change_meters = elevation_meters; }

    double getImpactTimestamp() const { return impact_timestamp; }
    void setImpactTimestamp(double timestamp) { impact_timestamp = timestamp; }

    float getAffectedAreaRadius() const { return affected_area_radius_meters; }
    void setAffectedAreaRadius(float radius_meters) { affected_area_radius_meters = radius_meters; }

    bool isActiveImpact() const { return is_active_impact; }
    void setActiveStatus(bool active) { is_active_impact = active; }

    // ========================================
    // RESOURCE DISTRIBUTION
    // ========================================

    /**
     * @brief Get materials ejected by volcanic impact
     */
    const std::unordered_map<uint32_t, uint64_t>& getEjectedMaterials() const { return ejected_materials; }

    /**
     * @brief Add ejected resource from volcanic eruption
     * @param resource_id Resource type ejected
     * @param quantity Amount in tonnes
     */
    void addEjectedMaterial(uint32_t resource_id, uint64_t quantity);

    /**
     * @brief Get total mass of ejected materials
     * @return Total mass in tonnes
     */
    uint64_t getTotalEjectedMass() const;

    /**
     * @brief Calculate resource density at distance from impact center
     * @param distance_meters Distance from volcano center
     * @param resource_id Specific resource to check
     * @return Resource density at this distance (tonnes per square meter)
     */
    float calculateResourceDensityAtDistance(float distance_meters, uint32_t resource_id) const;

    // ========================================
    // TERRAIN MODIFICATION
    // ========================================

    /**
     * @brief Calculate terrain elevation change at specific distance
     * @param distance_meters Distance from volcano center
     * @return Elevation change in meters (positive = raised, negative = lowered)
     */
    float calculateElevationChangeAtDistance(float distance_meters) const;

    /**
     * @brief Calculate temperature effect at specific distance
     * @param distance_meters Distance from volcano center
     * @return Temperature increase in Celsius
     */
    float calculateTemperatureAtDistance(float distance_meters) const;

    /**
     * @brief Check if point is within impact zone
     * @param distance_meters Distance from volcano center
     * @return True if within affected area
     */
    bool isWithinImpactZone(float distance_meters) const;

    // ========================================
    // IMPACT SIMULATION
    // ========================================

    /**
     * @brief Simulate impact effects from volcano eruption
     * @param source_volcano Volcano that caused this impact
     * @param eruption_materials Resources ejected in eruption
     */
    void simulateImpactFromEruption(const Volcano& source_volcano,
                                   const std::unordered_map<uint32_t, uint64_t>& eruption_materials);

    /**
     * @brief Process cooling and settling of volcanic materials over time
     * @param time_step_years Time period for cooling simulation
     */
    void processCoolingAndSettling(float time_step_years);

    /**
     * @brief Create a copy of this volcanic impact
     */
    VolcanoImpact copy() const;

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

    /**
     * @brief Convert impact type enum to string
     */
    static std::string typeToString(ImpactType type);

    /**
     * @brief Convert string to impact type enum
     */
    static ImpactType stringToType(const std::string& type_str);

    /**
     * @brief Map volcano type to corresponding impact type
     * @param volcano_type Type of volcano from Volcano::VolcanoType
     * @return Corresponding impact type for this volcano
     */
    static ImpactType mapVolcanoTypeToImpact(Volcano::VolcanoType volcano_type);

private:
    /**
     * @brief Calculate distribution pattern based on impact type
     * @param distance_meters Distance from center
     * @return Distribution multiplier (0.0 to 1.0)
     */
    float calculateDistributionPattern(float distance_meters) const;

    /**
     * @brief Apply impact type-specific terrain modifications
     */
    void applyImpactTypeEffects();

    /**
     * @brief Calculate falloff factor for distance-based effects
     * @param distance_meters Distance from volcano center
     * @param max_radius Maximum effective radius
     * @return Falloff multiplier (1.0 at center, 0.0 at max_radius)
     */
    float calculateDistanceFalloff(float distance_meters, float max_radius) const;
};

} // namespace warfactory