import assert from "node:assert/strict";
import {readFile} from "node:fs/promises";

const themeFile = (path) =>
    readFile(new URL(`../../${path}`, import.meta.url), "utf8");

const [themeRuntime, notificationTemplate, themeStyles] = await Promise.all([
    themeFile("assets/js/theme.js"),
    themeFile("templates/components/Notification.html.twig"),
    themeFile("assets/css/app.css"),
]);

assert.doesNotMatch(
    themeRuntime,
    /showPendingCartNotification|pushThemeNotification/u,
    "Le panneau panier ne doit pas déclencher son propre toast de succès.",
);
assert.match(
    themeRuntime,
    /setupCartNotificationObserver/u,
    "Le thème doit surveiller les notifications reçues pendant un ajout au panier.",
);
assert.match(
    themeRuntime,
    /this\.cartOpen[\s\S]*notification\.remove\(\)/u,
    "Une notification d’ajout doit être supprimée lorsque le panneau panier s’ouvre.",
);

const notificationRoot = notificationTemplate.match(
    /<div[\s\S]*?data-alert-dismiss-after-value="5000">/u,
)?.[0];
const closeButton = notificationTemplate.match(
    /<button[\s\S]*?data-action="alert#close"[\s\S]*?<\/button>/u,
)?.[0];

assert.ok(notificationRoot, "Le toast rendu est introuvable.");
assert.match(
    notificationRoot,
    /x-data="heritageNotification"/u,
    "Le toast doit utiliser l’état Alpine nommé compatible CSP.",
);
assert.ok(closeButton, "Le bouton de fermeture du toast est introuvable.");
assert.match(
    closeButton,
    /@click="close"/u,
    "La croix doit fermer le toast même si le contrôleur Stimulus n’est pas connecté.",
);

const notificationAnimation = themeStyles.match(
    /@keyframes heritage-toast\s*\{[\s\S]*?\n\}/u,
)?.[0];
assert.ok(
    notificationAnimation,
    "Le thème doit définir une animation d’entrée propre aux notifications.",
);
assert.doesNotMatch(
    notificationAnimation,
    /translate(?:X)?\(\s*100%/u,
    "L’animation ne doit jamais déplacer la croix hors de la fenêtre.",
);
assert.match(
    themeStyles,
    /\.animate-toast\s*\{\s*animation:\s*heritage-toast/u,
    "Le toast Heritage doit utiliser l’animation qui conserve sa zone cliquable.",
);

const previousDocument = globalThis.document;
const previousWindow = globalThis.window;
globalThis.document = {addEventListener() {}};
globalThis.window = {addEventListener() {}};

try {
    const themeModule = await import(
        `data:text/javascript;base64,${Buffer.from(themeRuntime).toString("base64")}`
    );
    const factories = new Map();
    themeModule.default({
        data(name, factory) {
            factories.set(name, factory);
        },
    });

    const createNotification = factories.get("heritageNotification");
    assert.equal(
        typeof createNotification,
        "function",
        "Le thème doit enregistrer le comportement Alpine du toast.",
    );

    let removed = false;
    const notification = createNotification();
    notification.$root = {
        remove() {
            removed = true;
        },
    };
    notification.close();

    assert.equal(
        removed,
        true,
        "La fermeture doit supprimer le toast pour empêcher un morph de le réafficher.",
    );
} finally {
    globalThis.document = previousDocument;
    globalThis.window = previousWindow;
}

console.log(
    "OK — le panneau remplace le toast de panier et la croix ferme les autres notifications.",
);
