#pragma once
#include <string>
#include <unordered_map>

namespace PUBGM_HitEffect {

struct AppInfo {
    std::string name = "com.tencent.tmgp.pubgmhd";
    std::string version = "3.8.0";
    bool debugMode = false;
};

struct BasicHitEffect {
    float baseDuration = 1.0f;
    float durationMultiplier = 2.5f;
    float fadeStartTime = 0.7f;
    float fadeDuration = 0.3f;
    
    float getDuration() const {
        return baseDuration * durationMultiplier;
    }
    
    float getTotalDuration() const {
        return getDuration() + fadeDuration;
    }
};

struct WeaponHitEffect {
    float sniperDuration = 3.0f;
    float assaultRifleDuration = 2.5f;
    float smgDuration = 2.0f;
    float shotgunDuration = 2.8f;
    float dmrDuration = 2.7f;
    float lmgDuration = 2.3f;
    float pistolDuration = 1.8f;
    float crossbowDuration = 3.2f;
    float meleeDuration = 1.5f;
    float grenadeDuration = 4.0f;
    
    float getWeaponHitDuration(const std::string& weaponType) const {
        static std::unordered_map<std::string, float> weaponMap = {
            {"Sniper", sniperDuration},
            {"AssaultRifle", assaultRifleDuration},
            {"SMG", smgDuration},
            {"Shotgun", shotgunDuration},
            {"DMR", dmrDuration},
            {"LMG", lmgDuration},
            {"Pistol", pistolDuration},
            {"Crossbow", crossbowDuration},
            {"Melee", meleeDuration},
            {"Grenade", grenadeDuration}
        };
        
        auto it = weaponMap.find(weaponType);
        if (it != weaponMap.end()) {
            return it->second;
        }
        return 2.0f;
    }
};

struct BodyPartHitEffect {
    float headshotDuration = 3.5f;
    float chestDuration = 2.5f;
    float stomachDuration = 2.2f;
    float armDuration = 2.0f;
    float legDuration = 1.8f;
    
    float getBodyPartDuration(const std::string& bodyPart) const {
        static std::unordered_map<std::string, float> bodyPartMap = {
            {"Head", headshotDuration},
            {"Chest", chestDuration},
            {"Stomach", stomachDuration},
            {"Arm", armDuration},
            {"Leg", legDuration}
        };
        
        auto it = bodyPartMap.find(bodyPart);
        if (it != bodyPartMap.end()) {
            return it->second;
        }
        return 2.0f;
    }
};

struct HitEffectVisuals {
    float particleLifetime = 3.0f;
    float particleSize = 1.2f;
    float particleSpeed = 0.8f;
    float particleCount = 1.5f;
    
    float bloodEffectDuration = 2.5f;
    float bloodSpread = 1.3f;
    float bloodOpacity = 0.9f;
    
    float sparkEffectDuration = 1.8f;
    float sparkBrightness = 1.4f;
    
    float smokeEffectDuration = 2.2f;
    float smokeDensity = 1.2f;
    
    float decalDuration = 30.0f;
    float decalSize = 1.1f;
    float decalFadeTime = 25.0f;
};

struct HitSoundEffects {
    float hitSoundDuration = 2.0f;
    float hitSoundVolume = 1.3f;
    float hitSoundReverb = 1.2f;
    
    float headshotSoundDuration = 2.5f;
    float headshotSoundVolume = 1.5f;
    
    float killSoundDuration = 3.0f;
    float killSoundVolume = 1.4f;
    
    float multiKillSoundDelay = 0.3f;
};

struct EnvironmentHitEffect {
    float wallHitDuration = 2.5f;
    float groundHitDuration = 2.0f;
    float vehicleHitDuration = 3.0f;
    float waterHitDuration = 1.5f;
    float glassHitDuration = 2.2f;
    
    float ricochetEffectDuration = 1.8f;
    float penetrationEffectDuration = 2.3f;
};

struct DamageNumberEffects {
    float damageNumberDuration = 2.5f;
    float damageNumberSize = 1.2f;
    float damageNumberSpeed = 0.7f;
    float damageNumberFadeTime = 0.5f;
    
    float critDamageDuration = 3.0f;
    float critDamageSize = 1.4f;
    
    float headshotNumberDuration = 3.2f;
    float headshotNumberColorSaturation = 1.3f;
};

struct ScreenEffects {
    float hitMarkerDuration = 1.5f;
    float hitMarkerSize = 1.3f;
    float hitMarkerOpacity = 0.9f;
    
    float screenShakeDuration = 1.2f;
    float screenShakeIntensity = 1.1f;
    
    float bloodScreenEffectDuration = 1.8f;
    float bloodScreenOpacity = 0.7f;
    
    float lowHealthEffectDuration = 2.5f;
    float lowHealthEffectIntensity = 1.2f;
};

struct EffectPerformance {
    float maxTotalEffects = 20.0f;
    float effectCullingDistance = 50.0f;
    float effectPriorityThreshold = 0.3f;
    bool enableEffectPooling = true;
    int effectPoolSize = 30;
    
    bool useLODEffects = true;
    float highLODDistance = 20.0f;
    float mediumLODDistance = 40.0f;
    float lowLODDistance = 60.0f;
};

class HitEffectConfig {
public:
    HitEffectConfig() = default;
    
    AppInfo getAppInfo() const { return appInfo; }
    BasicHitEffect getBasicEffect() const { return basicEffect; }
    WeaponHitEffect getWeaponEffect() const { return weaponEffect; }
    BodyPartHitEffect getBodyPartEffect() const { return bodyPartEffect; }
    HitEffectVisuals getVisuals() const { return visuals; }
    HitSoundEffects getSounds() const { return sounds; }
    EnvironmentHitEffect getEnvironment() const { return environment; }
    DamageNumberEffects getDamageNumbers() const { return damageNumbers; }
    ScreenEffects getScreenEffects() const { return screenEffects; }
    EffectPerformance getPerformance() const { return performance; }
    
    float calculateTotalHitDuration(const std::string& weaponType, const std::string& bodyPart) const {
        float weaponDuration = weaponEffect.getWeaponHitDuration(weaponType);
        float bodyPartDuration = bodyPartEffect.getBodyPartDuration(bodyPart);
        
        return (weaponDuration + bodyPartDuration) / 2.0f;
    }
    
    float getEnhancedParticleLifetime() const {
        return visuals.particleLifetime * basicEffect.durationMultiplier;
    }
    
    float getEnhancedDecalDuration() const {
        return visuals.decalDuration * 1.5f;
    }
    
    bool validateDurations() const {
        if (basicEffect.getDuration() <= 0) return false;
        if (weaponEffect.sniperDuration <= 0) return false;
        if (bodyPartEffect.headshotDuration <= 0) return false;
        
        return true;
    }
    
    std::string getConfigSummary() const {
        std::string summary;
        summary += "Base Effect Duration: " + std::to_string(basicEffect.getDuration()) + "s\n";
        summary += "Duration Multiplier: " + std::to_string(basicEffect.durationMultiplier) + "x\n";
        summary += "Headshot Duration: " + std::to_string(bodyPartEffect.headshotDuration) + "s\n";
        summary += "Sniper Hit Duration: " + std::to_string(weaponEffect.sniperDuration) + "s\n";
        summary += "Particle Lifetime: " + std::to_string(getEnhancedParticleLifetime()) + "s\n";
        summary += "Decal Duration: " + std::to_string(getEnhancedDecalDuration()) + "s\n";
        return summary;
    }
    
private:
    AppInfo appInfo;
    BasicHitEffect basicEffect;
    WeaponHitEffect weaponEffect;
    BodyPartHitEffect bodyPartEffect;
    HitEffectVisuals visuals;
    HitSoundEffects sounds;
    EnvironmentHitEffect environment;
    DamageNumberEffects damageNumbers;
    ScreenEffects screenEffects;
    EffectPerformance performance;
};

namespace EffectUtils {
    float calculateDynamicDuration(float baseDuration, float distance, float maxDistance) {
        if (distance <= maxDistance * 0.3f) return baseDuration;
        if (distance >= maxDistance) return baseDuration * 0.5f;
        
        float distanceRatio = (distance - maxDistance * 0.3f) / (maxDistance * 0.7f);
        return baseDuration * (1.0f - distanceRatio * 0.5f);
    }
    
    float calculateEffectScale(float distance, float optimalDistance) {
        if (distance <= optimalDistance) return 1.0f;
        float scale = optimalDistance / distance;
        return scale < 0.3f ? 0.3f : scale;
    }
    
    bool shouldShowEffect(float distance, float priority, float cullingDistance) {
        if (distance > cullingDistance) return false;
        if (priority < 0.1f) return false;
        return true;
    }
}

}
