import { DropSystem } from '@logic/DropSystem';
import { EnemyType, ItemType } from '@data/Interfaces';

describe('DropSystem — crystal jade deterministic rule (req 7.1)', () => {
    it('spawns a crystal jade on exactly the 12th kill', () => {
        const ds = new DropSystem({ random: () => 1 });
        let crystalEvents = 0;
        for (let i = 1; i <= 24; i++) {
            const drops = ds.onEnemyKilled(EnemyType.YaoFang, { x: 100, y: 0 });
            if (drops.some((d) => d.item === ItemType.CrystalJade)) crystalEvents++;
        }
        expect(crystalEvents).toBe(2);
    });

    it('spawns the crystal above the kill point', () => {
        const ds = new DropSystem({ random: () => 1 });
        for (let i = 0; i < 11; i++) ds.onEnemyKilled(EnemyType.QingRen, { x: 0, y: 0 });
        const drops = ds.onEnemyKilled(EnemyType.QingRen, { x: 300, y: 20 });
        const crystal = drops.find((d) => d.item === ItemType.CrystalJade);
        expect(crystal!.y).toBeGreaterThan(20);
    });
});

describe('DropSystem — Chi Ren consecutive rule (req 7.3)', () => {
    it('drops dian_wan or shu_wan on the 3rd consecutive Chi Ren kill if RNG <0.5', () => {
        const ds = new DropSystem({
            dianShuWanProbability: 0.5,
            random: (() => {
                // probability check then which-item check both pass
                const vals = [0.1, 0.2];
                let i = 0;
                return () => vals[i++ % vals.length];
            })(),
        });
        ds.onEnemyKilled(EnemyType.ChiRen, { x: 0, y: 0 });
        ds.onEnemyKilled(EnemyType.ChiRen, { x: 0, y: 0 });
        const drops = ds.onEnemyKilled(EnemyType.ChiRen, { x: 50, y: 10 });
        expect(drops.find((d) => d.item === ItemType.DianWan)).toBeDefined();
    });

    it('does not drop when RNG fails probability', () => {
        const ds = new DropSystem({ dianShuWanProbability: 0.5, random: () => 0.95 });
        ds.onEnemyKilled(EnemyType.ChiRen, { x: 0, y: 0 });
        ds.onEnemyKilled(EnemyType.ChiRen, { x: 0, y: 0 });
        const drops = ds.onEnemyKilled(EnemyType.ChiRen, { x: 0, y: 0 });
        expect(drops.filter((d) => d.item !== ItemType.CrystalJade).length).toBe(0);
    });

    it('non-Chi-Ren kill resets the consecutive counter', () => {
        const ds = new DropSystem({ dianShuWanProbability: 1.0, random: () => 0 });
        ds.onEnemyKilled(EnemyType.ChiRen, { x: 0, y: 0 });
        ds.onEnemyKilled(EnemyType.ChiRen, { x: 0, y: 0 });
        ds.onEnemyKilled(EnemyType.QingRen, { x: 0, y: 0 });
        const drops = ds.onEnemyKilled(EnemyType.ChiRen, { x: 0, y: 0 });
        // Only 1 Chi Ren kill since reset — below threshold.
        expect(drops.filter((d) => d.item === ItemType.DianWan || d.item === ItemType.ShuWan).length).toBe(0);
    });
});

describe('DropSystem — reset()', () => {
    it('zeroes kill counters', () => {
        const ds = new DropSystem();
        ds.onEnemyKilled(EnemyType.QingRen, { x: 0, y: 0 });
        ds.reset();
        expect(ds.kills).toBe(0);
    });
});
