/*
 * © 2026 TiedUp! Remake Contributors, distributed under GPLv3.
 */

package com.tiedup.remake.rig;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;

import net.minecraft.resources.ResourceLocation;

import org.junit.jupiter.api.Test;

import com.tiedup.remake.rig.anim.types.DirectStaticAnimation;

/**
 * Tests du registry {@link TiedUpAnimationRegistry}.
 *
 * <p>Ces tests verrouillent :</p>
 * <ul>
 *   <li>L'idempotence de {@link TiedUpAnimationRegistry#initStaticAnimations()}
 *       — un double-appel ne doit pas créer une nouvelle instance / doubler
 *       l'enregistrement. Pattern important car {@code FMLCommonSetupEvent}
 *       peut firer plusieurs fois sur hot-reload dev ou test runner.</li>
 *   <li>Le {@code registryName()} de {@link TiedUpAnimationRegistry#CONTEXT_STAND_IDLE}
 *       — alignement avec le path du JSON asset
 *       ({@code assets/tiedup/animmodels/animations/context_stand_idle.json}).
 *       Si quelqu'un renomme l'asset sans toucher le code (ou vice-versa), ce
 *       test attrape immédiatement la désynchronisation.</li>
 * </ul>
 *
 * <p>Les tests n'ont PAS besoin du runtime MC — {@code initStaticAnimations()}
 * construit juste les instances {@link DirectStaticAnimation} (pas de
 * {@code loadAnimation()} déclenché tant que {@code getAnimationClip()} n'est
 * pas lu). La {@code ResourceLocation} créée via le constructor n'a pas besoin
 * de Minecraft runtime non plus.</p>
 */
class TiedUpAnimationRegistryTest {

    /**
     * Appeler {@link TiedUpAnimationRegistry#initStaticAnimations()} deux fois
     * de suite doit être un no-op sur le second appel — le champ
     * {@code CONTEXT_STAND_IDLE} garde la même référence.
     *
     * <p>Si l'init n'était pas idempotent, un double-call (scénario hot-reload
     * dev, test runner partageant la JVM, etc.) recréerait l'instance et
     * invaliderait tous les sites qui l'ont capturée en field final ou local.
     * Le guard {@code if (CONTEXT_STAND_IDLE != null) return;} protège de ça —
     * ce test s'assure qu'il n'est pas retiré en régression.</p>
     */
    @Test
    void initStaticAnimationsIsIdempotent() {
        TiedUpAnimationRegistry.initStaticAnimations();

        assertNotNull(TiedUpAnimationRegistry.CONTEXT_STAND_IDLE,
            "Après initStaticAnimations, CONTEXT_STAND_IDLE doit être non-null");

        DirectStaticAnimation firstInstance = TiedUpAnimationRegistry.CONTEXT_STAND_IDLE;

        // Deuxième call — doit être no-op, pas recréer l'instance.
        TiedUpAnimationRegistry.initStaticAnimations();

        assertSame(firstInstance, TiedUpAnimationRegistry.CONTEXT_STAND_IDLE,
            "Un second call à initStaticAnimations ne doit pas remplacer l'instance — "
            + "le guard `if (CONTEXT_STAND_IDLE != null) return;` serait cassé sinon");
    }

    /**
     * Le {@code registryName()} de {@code CONTEXT_STAND_IDLE} doit matcher
     * {@code tiedup:context_stand_idle} — alignement avec le path du JSON
     * asset {@code assets/tiedup/animmodels/animations/context_stand_idle.json}.
     *
     * <p>Si le registry name dérive du path (via la résolution
     * {@code resourceLocation = animmodels/animations/${registry.path}.json}),
     * une désynchronisation code vs asset se traduit par un
     * {@code AssetLoadingException} runtime. Ce test est un smoke check rapide
     * au niveau de l'identité du registry name.</p>
     */
    @Test
    void contextStandIdleHasRegistryName() {
        TiedUpAnimationRegistry.initStaticAnimations();

        DirectStaticAnimation anim = TiedUpAnimationRegistry.CONTEXT_STAND_IDLE;
        assertNotNull(anim, "CONTEXT_STAND_IDLE doit être initialisé");

        ResourceLocation expected =
            ResourceLocation.fromNamespaceAndPath(TiedUpRigConstants.MODID, "context_stand_idle");

        assertEquals(expected, anim.registryName(),
            "CONTEXT_STAND_IDLE.registryName() doit être tiedup:context_stand_idle — "
            + "désynchronisation avec assets/tiedup/animmodels/animations/context_stand_idle.json sinon");
    }
}
