import { describe, expect, it, vi } from 'vitest';
import { GameLoop } from '../GameLoop';

/** Заглушки rAF: frame() продвигает кадры вручную. */
function installRaf(): (advanceMs: number) => void {
    let now = 0;
    const callbacks: ((t: number) => void)[] = [];
    vi.stubGlobal('requestAnimationFrame', (cb: (t: number) => void) => {
        callbacks.push(cb);
        return callbacks.length;
    });
    vi.stubGlobal('cancelAnimationFrame', () => undefined);
    vi.stubGlobal('performance', { now: () => now });
    return (advanceMs: number) => {
        now += advanceMs;
        const list = [...callbacks];
        callbacks.length = 0;
        for (const cb of list) cb(now);
    };
}

describe('GameLoop — ручной режим', () => {
    it('setManual(true) гасит кадры, resetTiming не даёт догонять', () => {
        const frame = installRaf();
        const updates: number[] = [];
        const loop = new GameLoop(60, {
            update: (dt) => updates.push(dt),
            render: () => undefined
        });
        loop.start();
        frame(1000); // ~60 шагов сгущаются в максимум 5
        expect(updates.length).toBe(5);

        loop.setManual(true);
        frame(1000);
        expect(updates.length).toBe(5); // кадры в ручном режиме пустые

        loop.setManual(false);
        frame(20); // resetTiming в setManual(true) обнулил аккумулятор — без «догоняния»
        expect(updates.length).toBe(6); // ровно один шаг, а не 5+5
        loop.stop();
        vi.unstubAllGlobals();
    });
});