import { describe, expect, it } from 'vitest';
import {
    aberrationShiftAt,
    blurKernel,
    blurStrengthAt,
    pulseEnvelope,
    pulseTotal,
    shimmerOffsetY
} from '../postSim';

describe('blurStrengthAt', () => {
    it('глобальный режим: сила постоянна', () => {
        expect(blurStrengthAt(0, 0, 4)).toBe(4);
        expect(blurStrengthAt(1000, 0, 4)).toBe(4);
    });

    it('пик в центре, гладкий спад до нуля на радиусе', () => {
        expect(blurStrengthAt(0, 100, 4)).toBe(4);
        expect(blurStrengthAt(100, 100, 4)).toBe(0);
        expect(blurStrengthAt(150, 100, 4)).toBe(0); // за радиусом — 0
        const mid = blurStrengthAt(50, 100, 4);
        expect(mid).toBeGreaterThan(0);
        expect(mid).toBeLessThan(4);
    });

    it('спад симметричен и монотонен', () => {
        let prev = Infinity;
        for (let d = 0; d <= 100; d += 5) {
            const v = blurStrengthAt(d, 100, 4);
            expect(v).toBeLessThanOrEqual(prev);
            prev = v;
        }
    });
});

describe('blurKernel', () => {
    it('смещения в пределах единичного круга и различны', () => {
        const k = blurKernel(8);
        expect(k.length).toBe(8);
        const seen = new Set(k.map(([x, y]) => `${x.toFixed(4)},${y.toFixed(4)}`));
        expect(seen.size).toBe(8);
        for (const [x, y] of k) {
            expect(Math.hypot(x, y)).toBeLessThanOrEqual(1);
        }
    });
});

describe('aberrationShiftAt', () => {
    it('тот же профиль спада, что у блюра', () => {
        expect(aberrationShiftAt(0, 100, 2)).toBe(2);
        expect(aberrationShiftAt(100, 100, 2)).toBe(0);
        expect(aberrationShiftAt(0, 0, 2)).toBe(2); // глобальный режим
    });
});

describe('shimmerOffsetY', () => {
    it('периодичен по X и по времени', () => {
        const p = { amp: 1.5, wavelength: 40, speed: 2 };
        expect(shimmerOffsetY(0, 0, p)).toBeCloseTo(0);
        expect(shimmerOffsetY(40, 0, p)).toBeCloseTo(0); // период по X = wavelength
        expect(shimmerOffsetY(0, 0.5, p)).toBeCloseTo(0); // период по t = 1/speed
        expect(Math.abs(shimmerOffsetY(10, 0, p))).toBeCloseTo(p.amp); // четверть волны
    });
});

describe('переэкспорт pulseEnvelope', () => {
    it('атака/плато/спад сходятся', () => {
        const spec = { attack: 0.1, hold: 0.2, decay: 0.3 };
        expect(pulseTotal(spec)).toBeCloseTo(0.6);
        expect(pulseEnvelope(0.05, spec)).toBeCloseTo(0.5);
        expect(pulseEnvelope(0.2, spec)).toBe(1);
        expect(pulseEnvelope(0.45, spec)).toBeCloseTo(0.5);
        expect(pulseEnvelope(0.7, spec)).toBe(0);
    });
});