#pragma once

#include <string>
#include <unordered_map>

namespace warfactory {

/**
 * @brief Climate region for weather pattern simulation
 *
 * Represents areas with specific climate characteristics including
 * temperature, humidity, wind patterns, and seasonal variations.
 * Used for biome generation and weather system simulation.
 */
class ClimateRegion {
public:
    enum class ClimateType {
        TROPICAL,           // Hot and humid year-round
        TEMPERATE,          // Moderate temperatures with seasons
        ARCTIC,             // Cold temperatures year-round
        DESERT,             // Hot and dry
        MONSOON,            // Seasonal heavy rainfall
        MEDITERRANEAN       // Warm, dry summers and mild, wet winters
    };

private:
    std::string name_type;              // Climate type name ("tropical", "temperate", etc.)
    float x_position, y_position;       // Climate zone center coordinates
    float mass;                         // Climate "mass" (influence area)
    ClimateType climate_type;           // Type of climate
    float temperature;                  // Average temperature (Celsius)
    float humidity;                     // Average humidity (0.0 to 1.0)
    float rainfall;                     // Annual rainfall (mm)
    float wind_strength;                // Average wind speed (km/h)
    float seasonal_variation;           // Temperature variation between seasons (°C)
    double formation_time;              // When climate zone was established (years)
    bool is_stable;                     // Climate pattern is stable

public:
    ClimateRegion();
    ClimateRegion(ClimateType type, float x, float y, float influence_mass);

    // ========================================
    // DUCK TYPING INTERFACE (Required by UniversalRegionFusionFunction)
    // ========================================

    /**
     * @brief Get region type name for fusion compatibility
     * @return Type name string ("tropical", "temperate", "arctic", etc.)
     */
    std::string getNameType() const { return name_type; }

    /**
     * @brief Get X coordinate of climate zone center
     * @return X position in world coordinates
     */
    float getX() const { return x_position; }

    /**
     * @brief Get Y coordinate of climate zone center
     * @return Y position in world coordinates
     */
    float getY() const { return y_position; }

    /**
     * @brief Get climate influence mass
     * @return Mass representing climate zone influence area
     */
    float getMass() const { return mass; }

    /**
     * @brief Set new position for the climate zone center
     * @param x New X coordinate
     * @param y New Y coordinate
     */
    void setPosition(float x, float y) { x_position = x; y_position = y; }

    /**
     * @brief Add mass to the climate zone (for fusion)
     * @param additional_mass Mass to add
     */
    void addMass(float additional_mass) { mass += additional_mass; }

    // ========================================
    // CLIMATE PROPERTIES
    // ========================================

    /**
     * @brief Get climate type
     * @return ClimateType enum value
     */
    ClimateType getClimateType() const { return climate_type; }

    /**
     * @brief Set climate type and update name_type accordingly
     * @param type New climate type
     */
    void setClimateType(ClimateType type);

    /**
     * @brief Get average temperature
     * @return Temperature in Celsius
     */
    float getTemperature() const { return temperature; }

    /**
     * @brief Set average temperature
     * @param temp Temperature in Celsius
     */
    void setTemperature(float temp) { temperature = temp; }

    /**
     * @brief Get humidity level
     * @return Humidity as ratio (0.0 = dry, 1.0 = saturated)
     */
    float getHumidity() const { return humidity; }

    /**
     * @brief Set humidity level
     * @param humid Humidity ratio (0.0 to 1.0)
     */
    void setHumidity(float humid) { humidity = humid; }

    /**
     * @brief Get annual rainfall
     * @return Rainfall in millimeters per year
     */
    float getRainfall() const { return rainfall; }

    /**
     * @brief Set annual rainfall
     * @param rain Rainfall in mm/year
     */
    void setRainfall(float rain) { rainfall = rain; }

    /**
     * @brief Get wind strength
     * @return Average wind speed in km/h
     */
    float getWindStrength() const { return wind_strength; }

    /**
     * @brief Set wind strength
     * @param wind Wind speed in km/h
     */
    void setWindStrength(float wind) { wind_strength = wind; }

    /**
     * @brief Get seasonal temperature variation
     * @return Temperature difference between seasons (°C)
     */
    float getSeasonalVariation() const { return seasonal_variation; }

    /**
     * @brief Set seasonal variation
     * @param variation Temperature difference in °C
     */
    void setSeasonalVariation(float variation) { seasonal_variation = variation; }

    /**
     * @brief Get formation time
     * @return Time when climate zone was established (years since world start)
     */
    double getFormationTime() const { return formation_time; }

    /**
     * @brief Set formation time
     * @param time Formation time in years
     */
    void setFormationTime(double time) { formation_time = time; }

    /**
     * @brief Check if climate is stable
     * @return True if climate pattern is stable
     */
    bool isStable() const { return is_stable; }

    /**
     * @brief Set climate stability
     * @param stable True for stable climate
     */
    void setStable(bool stable) { is_stable = stable; }

    // ========================================
    // CLIMATE SIMULATION
    // ========================================

    /**
     * @brief Calculate climate comfort index
     * @return Comfort index (0.0 = hostile, 1.0 = ideal)
     */
    float calculateComfortIndex() const;

    /**
     * @brief Calculate evaporation rate
     * @return Evaporation rate based on temperature and humidity
     */
    float calculateEvaporationRate() const;

    /**
     * @brief Calculate growing season length
     * @return Number of growing days per year
     */
    int calculateGrowingSeason() const;

    /**
     * @brief Get biome suitability for specific biome type
     * @param biome_type Biome name to check
     * @return Suitability score (0.0 to 1.0)
     */
    float getBiomeSuitability(const std::string& biome_type) const;

    /**
     * @brief Update climate based on seasonal progression
     * @param season_factor Seasonal factor (0.0 = winter, 1.0 = summer)
     */
    void updateSeasonalClimate(float season_factor);

    /**
     * @brief Apply climate change over time
     * @param time_step_years Time period for climate evolution
     * @param global_temp_change Global temperature change factor
     */
    void processClimateEvolution(float time_step_years, float global_temp_change);

    // ========================================
    // FUSION SUPPORT
    // ========================================

    /**
     * @brief Merge another climate region into this one
     * @param other ClimateRegion to merge (must be compatible type)
     * @return True if merge was successful
     */
    bool mergeWith(const ClimateRegion& other);

    /**
     * @brief Check if this region can merge with another
     * @param other ClimateRegion to check compatibility
     * @return True if regions are compatible for merging
     */
    bool canMergeWith(const ClimateRegion& other) const;

    /**
     * @brief Create a copy of this climate region
     * @return New ClimateRegion with same properties
     */
    ClimateRegion copy() const;

    // ========================================
    // UTILITY FUNCTIONS
    // ========================================

    /**
     * @brief Convert ClimateType enum to string
     * @param type ClimateType enum value
     * @return String representation
     */
    static std::string climateTypeToString(ClimateType type);

    /**
     * @brief Convert string to ClimateType enum
     * @param type_str String representation
     * @return ClimateType enum value
     */
    static ClimateType stringToClimateType(const std::string& type_str);

    /**
     * @brief Calculate climate similarity with another region
     * @param other Other climate region
     * @return Similarity score (0.0 = completely different, 1.0 = identical)
     */
    float calculateClimateSimilarity(const ClimateRegion& other) const;

    /**
     * @brief Get Köppen climate classification
     * @return Köppen climate code string
     */
    std::string getKoppenClassification() const;

private:
    /**
     * @brief Update name_type based on current climate_type
     */
    void updateNameType();

    /**
     * @brief Validate climate parameter consistency
     * @return True if climate data is realistic
     */
    bool validateClimate() const;

    /**
     * @brief Apply climate type defaults
     * @param type Climate type to apply defaults for
     */
    void applyClimateDefaults(ClimateType type);
};

} // namespace warfactory