package net.mcreator.phayriosisreborn.difficulty;

import java.util.UUID;

import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
import net.minecraft.world.entity.ai.attributes.AttributeModifier;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LevelAccessor;
import net.minecraftforge.event.entity.EntityJoinLevelEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.mcreator.phayriosisreborn.config.PhayriosisWorldSettings;

/** World-specific infection difficulty presets. Server authoritative and additive to normal Phayriosis rules. */
@Mod.EventBusSubscriber(modid = "phayriosisreborn", bus = Mod.EventBusSubscriber.Bus.FORGE)
public final class PhayriosisDifficultySystem {
    private static final UUID HEALTH_UUID = UUID.fromString("3e2855e0-81f1-4db1-97d8-5d9a81a34f20");
    private static final UUID DAMAGE_UUID = UUID.fromString("47d5d6c7-6cb9-452b-8e77-d73a6dc473de");

    private PhayriosisDifficultySystem() {}

    public static int mode(LevelAccessor world) {
        PhayriosisWorldSettings.ensureInitialized(world);
        int value = (int)Math.round(PhayriosisWorldSettings.get(world).infectionDifficultyMode);
        return Math.max(0, Math.min(4, value));
    }

    public static double healthMultiplier(LevelAccessor world) {
        switch (mode(world)) {
            case 0: return 0.50D;
            case 2: return 1.40D;
            case 3: return 1.80D;
            case 4: return 2.20D;
            default: return 1.00D;
        }
    }

    public static double damageMultiplier(LevelAccessor world) {
        switch (mode(world)) {
            case 0: return 0.50D;
            case 2: return 1.40D;
            case 3: return 1.70D;
            case 4: return 2.00D;
            default: return 1.00D;
        }
    }

    public static double infectionPaceMultiplier(LevelAccessor world) {
        switch (mode(world)) {
            case 0: return 0.50D;
            case 2: return 1.25D;
            case 3: return 1.35D;
            case 4: return 1.50D;
            default: return 1.00D;
        }
    }

    /** Scales phase thresholds instead of rewriting every individual point award. */
    public static double requiredPoints(LevelAccessor world, double normalThreshold) {
        return normalThreshold / infectionPaceMultiplier(world);
    }

    /** Converts a normal 1-in-N infection spread roll into the selected world difficulty pace. */
    public static int spreadRollBound(LevelAccessor world, int normalBound) {
        if (normalBound <= 1) return 1;
        int scaled = (int)Math.round(normalBound / infectionPaceMultiplier(world));
        return Math.max(1, scaled);
    }

    /**
     * Preserve the original health-growth ratios used by Phayriosis evolution.
     * Bulb: 20 starting HP -> 100 evolution HP = 5x.
     * Dome: 100 starting HP -> 150 evolution HP = 1.5x.
     * Difficulty scales both starting HP and the required evolution HP together.
     */
    public static float evolutionThreshold(LevelAccessor world, Entity entity) {
        double multiplier = healthMultiplier(world);
        String name = entity == null ? "" : entity.getClass().getName();
        if (name.endsWith(".BulbEntity")) return (float)(100.0D * multiplier);
        if (name.endsWith(".DomeEntity")) return (float)(150.0D * multiplier);
        return entity instanceof LivingEntity living ? living.m_21233_() : Float.MAX_VALUE;
    }

    @SubscribeEvent
    public static void onEntityJoin(EntityJoinLevelEvent event) {
        Level level = event.getLevel();
        if (level == null || level.m_5776_()) return;
        Entity entity = event.getEntity();
        if (!(entity instanceof LivingEntity living)) return;
        if (!isPhayriosisLivingEntity(living)) return;
        applyAttributes(level, living);
    }

    private static boolean isPhayriosisLivingEntity(LivingEntity living) {
        String name = living.getClass().getName();
        return name.startsWith("net.mcreator.phayriosisreborn.entity.");
    }

    private static void applyAttributes(LevelAccessor world, LivingEntity living) {
        float oldMax = Math.max(0.001F, living.m_21233_());
        float healthFraction = Math.max(0.0F, Math.min(1.0F, living.m_21223_() / oldMax));

        applyModifier(living.m_21051_(Attributes.f_22276_), HEALTH_UUID,
                "Phayriosis difficulty health", healthMultiplier(world) - 1.0D);
        applyModifier(living.m_21051_(Attributes.f_22281_), DAMAGE_UUID,
                "Phayriosis difficulty damage", damageMultiplier(world) - 1.0D);

        float newMax = living.m_21233_();
        living.m_21153_(Math.max(0.01F, Math.min(newMax, newMax * healthFraction)));
    }

    private static void applyModifier(AttributeInstance attribute, UUID id, String name, double amount) {
        if (attribute == null) return;
        attribute.m_22120_(id);
        if (Math.abs(amount) < 0.000001D) return;
        attribute.m_22125_(new AttributeModifier(id, name, amount, AttributeModifier.Operation.MULTIPLY_BASE));
    }
}
