import { describe, expect, it } from 'vitest';
import { PLAYER_COMBAT } from '../stats';
import { PlayerCombat } from '../PlayerCombat';

/** Тик на 1/60 с — как в игровом цикле. */
const step = (c: PlayerCombat, seconds: number): void => {
    for (let i = 0; i < Math.round(seconds * 60); i++) c.update(1 / 60);
};

describe('PlayerCombat', () => {
    it('стартует с полным здоровьем', () => {
        const c = new PlayerCombat();
        expect(c.hp).toBe(PLAYER_COMBAT.maxHp);
        expect(c.dead).toBe(false);
        expect(c.invuln).toBe(false);
    });

    it('урон не превышает остаток HP, после него неуязвимость', () => {
        const c = new PlayerCombat();
        expect(c.takeDamage(3)).toBe(3);
        expect(c.hp).toBe(2);
        expect(c.invuln).toBe(true);
        // В окно неуязвимости урон не проходит
        expect(c.takeDamage(1)).toBe(0);
        expect(c.hp).toBe(2);
    });

    it('смерть при HP 0; revive возвращает полные сердечки', () => {
        const c = new PlayerCombat();
        c.takeDamage(PLAYER_COMBAT.maxHp);
        expect(c.dead).toBe(true);
        c.revive();
        expect(c.hp).toBe(PLAYER_COMBAT.maxHp);
        expect(c.dead).toBe(false);
        expect(c.invuln).toBe(true);
    });

    it('короткий тап — удар по кулдауну', () => {
        const c = new PlayerCombat();
        c.startCharge();
        step(c, 0.1);
        expect(c.isCharging()).toBe(true);
        expect(c.release()).toBe('attack');
        // Кулдаун ещё не истёк — второй удар не проходит
        c.startCharge();
        step(c, 0.1);
        expect(c.release()).toBeNull();
        // После кулдауна снова готов
        step(c, PLAYER_COMBAT.coneCooldown);
        c.startCharge();
        step(c, 0.1);
        expect(c.release()).toBe('attack');
    });

    it('удержание дольше resonanceCharge — резонанс по своему кулдауну', () => {
        const c = new PlayerCombat();
        c.startCharge();
        step(c, PLAYER_COMBAT.resonanceCharge + 0.1);
        expect(c.release()).toBe('resonance');
        // Резонанс перезаряжается — повторный заряд молча отклоняется
        c.startCharge();
        step(c, PLAYER_COMBAT.resonanceCharge + 0.1);
        expect(c.release()).toBeNull();
        step(c, PLAYER_COMBAT.resonanceCooldown);
        c.startCharge();
        step(c, PLAYER_COMBAT.resonanceCharge + 0.1);
        expect(c.release()).toBe('resonance');
    });

    it('неуязвимость спадает со временем', () => {
        const c = new PlayerCombat();
        c.takeDamage(1);
        step(c, PLAYER_COMBAT.invulnTime + 0.05);
        expect(c.invuln).toBe(false);
        expect(c.takeDamage(1)).toBe(1);
    });
});