#pragma once

#include <string>
#include <vector>

namespace warfactory {

/**
 * @brief Tectonic plate region for geological simulation
 *
 * Represents continental and oceanic crustal plates with movement,
 * collision detection, and geological evolution properties.
 * Used for realistic terrain formation and resource distribution.
 */
class TectonicRegion {
public:
    enum class PlateType {
        OCEANIC,        // Dense oceanic crust (basalt)
        CONTINENTAL,    // Light continental crust (granite)
        VOLCANIC        // Active volcanic zones
    };

private:
    std::string name_type;              // Plate type name ("oceanic", "continental", "volcanic")
    float x_position, y_position;       // Plate center coordinates
    float mass;                         // Plate mass (crustal material)
    PlateType plate_type;               // Type of tectonic plate
    float crust_thickness;              // Thickness of crustal layer (km)
    float velocity_x, velocity_y;       // Plate movement velocity (cm/year)
    float age;                          // Geological age of plate (millions of years)
    double formation_time;              // When plate was created (years)
    bool is_active;                     // Currently moving/evolving

public:
    TectonicRegion();
    TectonicRegion(PlateType type, float x, float y, float plate_mass);

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

    /**
     * @brief Get region type name for fusion compatibility
     * @return Type name string ("oceanic", "continental", "volcanic")
     */
    std::string getNameType() const { return name_type; }

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

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

    /**
     * @brief Get total mass of the tectonic plate
     * @return Mass in geological units
     */
    float getMass() const { return mass; }

    /**
     * @brief Set new position for the plate 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 plate (for fusion/collision)
     * @param additional_mass Mass to add
     */
    void addMass(float additional_mass) { mass += additional_mass; }

    // ========================================
    // TECTONIC PROPERTIES
    // ========================================

    /**
     * @brief Get plate type
     * @return PlateType enum value
     */
    PlateType getPlateType() const { return plate_type; }

    /**
     * @brief Set plate type and update name_type accordingly
     * @param type New plate type
     */
    void setPlateType(PlateType type);

    /**
     * @brief Get crustal thickness
     * @return Thickness in kilometers
     */
    float getCrustThickness() const { return crust_thickness; }

    /**
     * @brief Set crustal thickness
     * @param thickness Thickness in kilometers
     */
    void setCrustThickness(float thickness) { crust_thickness = thickness; }

    /**
     * @brief Get plate velocity components
     * @return Pair of (velocity_x, velocity_y) in cm/year
     */
    std::pair<float, float> getVelocity() const { return {velocity_x, velocity_y}; }

    /**
     * @brief Set plate movement velocity
     * @param vx Velocity in X direction (cm/year)
     * @param vy Velocity in Y direction (cm/year)
     */
    void setVelocity(float vx, float vy) { velocity_x = vx; velocity_y = vy; }

    /**
     * @brief Get geological age of plate
     * @return Age in millions of years
     */
    float getAge() const { return age; }

    /**
     * @brief Set geological age
     * @param geological_age Age in millions of years
     */
    void setAge(float geological_age) { age = geological_age; }

    /**
     * @brief Get formation time
     * @return Time when plate was created (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 plate is currently active
     * @return True if plate is moving/evolving
     */
    bool isActive() const { return is_active; }

    /**
     * @brief Set plate activity status
     * @param active True to activate plate movement
     */
    void setActive(bool active) { is_active = active; }

    // ========================================
    // TECTONIC PHYSICS
    // ========================================

    /**
     * @brief Update plate position based on velocity and time
     * @param time_step_years Time period for movement (years)
     */
    void updatePosition(float time_step_years);

    /**
     * @brief Calculate kinetic energy of moving plate
     * @return Kinetic energy in geological units
     */
    float calculateKineticEnergy() const;

    /**
     * @brief Calculate collision force with another plate
     * @param other Other tectonic plate
     * @return Collision force magnitude
     */
    float calculateCollisionForce(const TectonicRegion& other) const;

    /**
     * @brief Apply collision effects with another plate
     * @param other Other plate involved in collision
     * @param collision_type Type of boundary ("convergent", "divergent", "transform")
     */
    void processCollision(TectonicRegion& other, const std::string& collision_type);

    /**
     * @brief Calculate stress accumulation from movement
     * @return Stress level (affects earthquake probability)
     */
    float calculateStressLevel() const;

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

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

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

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

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

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

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

    /**
     * @brief Calculate plate density based on type
     * @return Density in g/cm³
     */
    float calculatePlateDensity() const;

    /**
     * @brief Estimate subduction potential with another plate
     * @param other Other plate to check subduction against
     * @return Subduction probability (0.0 to 1.0)
     */
    float calculateSubductionPotential(const TectonicRegion& other) const;

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

    /**
     * @brief Apply velocity damping for realistic movement
     * @param damping_factor Damping coefficient
     */
    void applyVelocityDamping(float damping_factor);

    /**
     * @brief Validate region consistency
     * @return True if region data is consistent
     */
    bool validateRegion() const;
};

} // namespace warfactory