import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { apiFetch } from './api-fetch';

/**
 * Le jeton CSRF joint par `apiFetch`.
 *
 * Ce test existe pour une panne précise : le rapprochement TEJ, premier POST
 * écrit avec ce wrapper, partait sans jeton. `VerifyCsrfToken` le rejetait par
 * un 419 AVANT le contrôleur — donc sans la moindre trace serveur — et l'écran
 * affichait « TEJ n'a pas répondu », qui accusait la DGI d'un oubli commis dans
 * ce fichier. Un bug invisible côté serveur ne se rattrape que côté client.
 */
describe('apiFetch', () => {
    let appels: RequestInit[];

    beforeEach(() => {
        appels = [];

        // `vitest.config.ts` tourne en environnement `node` : pas de DOM. On pose
        // le strict nécessaire — `getCsrfToken()` lit le cookie XSRF-TOKEN en
        // priorité, la balise <meta> n'est qu'un filet de secours.
        vi.stubGlobal('document', {
            cookie: 'XSRF-TOKEN=jeton-de-test; other=1',
            querySelector: () => null,
        });

        vi.stubGlobal('fetch', (_input: unknown, init?: RequestInit) => {
            appels.push(init ?? {});

            return Promise.resolve(new Response('{}', { status: 200 }));
        });
    });

    afterEach(() => vi.unstubAllGlobals());

    const jeton = (init: RequestInit) => new Headers(init.headers).get('X-CSRF-TOKEN');

    it('joint le jeton sur un POST', async () => {
        await apiFetch('/fournisseurs/tej/rapprochement', { method: 'POST' });

        expect(jeton(appels[0])).toBe('jeton-de-test');
    });

    it.each(['PUT', 'PATCH', 'DELETE'])('joint le jeton sur un %s', async (method) => {
        await apiFetch('/x', { method });

        expect(jeton(appels[0])).toBe('jeton-de-test');
    });

    it("n'en joint pas sur un GET, que Laravel en dispense", async () => {
        await apiFetch('/x');

        expect(jeton(appels[0])).toBeNull();
    });

    it("n'écrase pas un jeton fourni par l'appelant", async () => {
        await apiFetch('/x', { method: 'POST', headers: { 'X-CSRF-TOKEN': 'le-sien' } });

        expect(jeton(appels[0])).toBe('le-sien');
    });

    it('conserve les autres en-têtes et le corps', async () => {
        await apiFetch('/x', { method: 'POST', headers: { Accept: 'application/json' }, body: 'a=1' });

        expect(new Headers(appels[0].headers).get('Accept')).toBe('application/json');
        expect(appels[0].body).toBe('a=1');
    });

    it("envoie un jeton vide plutôt que de lever quand ni le cookie ni la balise n'ont de jeton — l'écran doit voir le 419, pas un plantage", async () => {
        vi.stubGlobal('document', { cookie: '', querySelector: () => null });

        await apiFetch('/x', { method: 'POST' });

        expect(jeton(appels[0])).toBe('');
    });
});
