import { describe, it, expect, vi, beforeEach } from 'vitest';

const { goToAndStop, destroy, loadAnimation } = vi.hoisted(() => {
    const goToAndStop = vi.fn();
    const destroy = vi.fn();
    const loadAnimation = vi.fn((options: { animationData: { layers: unknown[] } }) => ({
        totalFrames: 300,
        goToAndStop,
        destroy,
        animationData: options.animationData,
    }));
    return { goToAndStop, destroy, loadAnimation };
});

vi.mock('lottie-web/build/player/lottie_light', () => ({ default: { loadAnimation } }));

import { LottieDescent } from '@animations/gsap/LottieDescent';

const scene = { layers: [{ nm: 'Fond' }, { nm: 'Trace montagne' }] };

describe('LottieDescent', () => {
    beforeEach(() => {
        vi.clearAllMocks();
        vi.stubGlobal('fetch', vi.fn(async () => ({ ok: true, json: async () => structuredClone(scene) })));
    });

    it('drops the background layer and mounts one slot per theme', async () => {
        const container = document.createElement('div');
        const descent = new LottieDescent({ container, lightSrc: '/velo.json', darkSrc: '/ski.json' });

        expect(await descent.init()).toBe(true);
        expect(container.querySelectorAll('[data-lottie-slot]')).toHaveLength(2);
        expect(loadAnimation.mock.calls[0]?.[0].animationData.layers).toEqual([{ nm: 'Trace montagne' }]);
    });

    it('maps timeline progress to the last frame', async () => {
        const descent = new LottieDescent({ container: document.createElement('div'), lightSrc: '/a', darkSrc: '/b' });
        await descent.init();

        const tl = descent.buildTimeline();
        tl?.progress(1);

        expect(goToAndStop).toHaveBeenLastCalledWith(299, true);
    });

    it('resolves to false and cleans up when a scene fails to load', async () => {
        vi.spyOn(console, 'warn').mockImplementation(() => undefined);
        vi.stubGlobal('fetch', vi.fn(async (src: string) => (
            src === '/ski.json' ? { ok: false, status: 404 } : { ok: true, json: async () => structuredClone(scene) }
        )));
        const container = document.createElement('div');
        const descent = new LottieDescent({ container, lightSrc: '/velo.json', darkSrc: '/ski.json' });

        expect(await descent.init()).toBe(false);
        expect(container.children).toHaveLength(0);
        expect(descent.buildTimeline()).toBeNull();
    });
});
