package net.mcreator.phayriosisreborn.command;

import com.mojang.brigadier.context.CommandContext;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.commands.Commands;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.mcreator.phayriosisreborn.meteor.PhayriosisMeteorEntityRegistry;
import net.mcreator.phayriosisreborn.meteor.PhayriosisMeteorEventData;
import net.mcreator.phayriosisreborn.meteor.PhayriosisMeteorLaunchSystem;
import net.mcreator.phayriosisreborn.meteor.PhayriosisMeteorScheduler;
import net.minecraftforge.event.RegisterCommandsEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;

/** Phase-5 deterministic diagnostics. Safe admin commands; no terrain modification. */
@Mod.EventBusSubscriber
public final class PhayriosisMeteorDebugCommand {
    private PhayriosisMeteorDebugCommand() {}

    @SubscribeEvent
    public static void registerCommand(RegisterCommandsEvent event) {
        event.getDispatcher().register(Commands.m_82127_("phayriosis_meteor_test")
                .requires(source -> source.m_6761_(2))
                .executes(PhayriosisMeteorDebugCommand::forceMeteor));
        event.getDispatcher().register(Commands.m_82127_("phayriosis_meteor_status")
                .requires(source -> source.m_6761_(2))
                .executes(PhayriosisMeteorDebugCommand::status));
    }

    private static int forceMeteor(CommandContext<CommandSourceStack> context) {
        CommandSourceStack source = context.getSource();
        Level raw = source.getUnsidedLevel();
        if (!(raw instanceof ServerLevel level)) {
            tell(source, "[Phayriosis Meteor] This command requires a server world.");
            return 0;
        }
        PhayriosisMeteorEventData state = PhayriosisMeteorEventData.get(level);
        boolean wasActive = state.activeMeteor;
        // Diagnostic command deliberately clears stale active state so repeated tests cannot
        // be blocked by a lost entity from an earlier experimental build.
        state.activeMeteor = false;
        state.activeSinceGameTime = -1.0D;
        state.pendingMeteor = true;
        state.pendingSinceGameTime = (double) level.m_46467_();
        state.nextLaunchAttemptGameTime = 0.0D;
        state.m_77762_();
        double before = state.successfulLaunches;
        PhayriosisMeteorLaunchSystem.tryLaunch(level);
        boolean launched = state.successfulLaunches > before;
        tell(source, "[Phayriosis Meteor] forced test: launched=" + launched
                + " registryReady=" + (PhayriosisMeteorEntityRegistry.METEOR != null)
                + " previousActive=" + wasActive
                + " target=(" + round1(state.lastTargetX) + ", " + round1(state.lastTargetY) + ", " + round1(state.lastTargetZ) + ")");
        return launched ? 1 : 0;
    }

    private static int status(CommandContext<CommandSourceStack> context) {
        CommandSourceStack source = context.getSource();
        Level raw = source.getUnsidedLevel();
        if (!(raw instanceof ServerLevel level)) {
            tell(source, "[Phayriosis Meteor] This command requires a server world.");
            return 0;
        }
        PhayriosisMeteorEventData s = PhayriosisMeteorEventData.get(level);
        tell(source, "[Phayriosis Meteor] registryReady=" + (PhayriosisMeteorEntityRegistry.METEOR != null)
                + " eligible=" + PhayriosisMeteorScheduler.isCurrentlyEligible(level)
                + " dayTime=" + level.m_46468_() + " gameTime=" + level.m_46467_());
        tell(source, "[Phayriosis Meteor] rolls=" + (long)s.rollAttempts
                + " successes=" + (long)s.successfulRolls
                + " pending=" + s.pendingMeteor + " active=" + s.activeMeteor
                + " launches=" + (long)s.successfulLaunches + " impacts=" + (long)s.impacts);
        tell(source, "[Phayriosis Meteor] nextCheck=" + (long)s.nextCheckGameTime
                + " lastTarget=(" + round1(s.lastTargetX) + ", " + round1(s.lastTargetY) + ", " + round1(s.lastTargetZ) + ")");
        return 1;
    }

    private static void tell(CommandSourceStack source, String message) {
        System.out.println(message);
        Entity entity = source.m_81373_();
        if (entity instanceof Player player) {
            player.m_5661_(Component.m_237113_(message), false);
        }
    }

    private static double round1(double value) {
        return Math.rint(value * 10.0D) / 10.0D;
    }
}
