import { EnemyType, ItemType } from '../data/Interfaces';

/**
 * Drop system (req 7.1-7.6).
 *
 * Rules encoded here:
 *
 *  1. **水晶玉 (crystal jade)** — deterministic: every 12th kill on forest
 *     stages spawns one above the player (req 7.1). Lifetime 13-20s (req 7.2,
 *     handled by caller).
 *  2. **点丸 / 术丸** — after 3 consecutive 赤忍 kills, 50% chance of one or
 *     the other (req 7.3).
 *  3. **魔笛** — dropped by 黑忍 on death (implemented in `HeiRenAI`). Picking
 *     it up triggers a screen-wipe (req 7.4), applied by the level manager.
 *  4. **增丸** — fixed spawn point per level config, no probability (req 7.5).
 *
 * All probabilistic decisions funnel through an injectable `random()` so
 * deterministic tests stay stable.
 */

export interface IDropSystemCfg {
    /** Kills required before a crystal jade is guaranteed. Default 12 (req 7.1). */
    crystalJadeEveryN?: number;
    /** Kills of Chi Ren required before point/spell ball eligible. Default 3. */
    dianShuWanThresholdKills?: number;
    /** Probability for dian_wan or shu_wan drop once threshold reached. Default 0.5. */
    dianShuWanProbability?: number;
    /** Injectable RNG. Default `Math.random`. */
    random?: () => number;
}

export interface IDropEvent {
    item: ItemType;
    x: number;
    y: number;
}

export class DropSystem {
    private globalKills = 0;
    private chiRenConsecutiveKills = 0;
    private readonly crystalJadeEveryN: number;
    private readonly dianShuWanThresholdKills: number;
    private readonly dianShuWanProbability: number;
    private readonly random: () => number;

    constructor(cfg: IDropSystemCfg = {}) {
        this.crystalJadeEveryN = cfg.crystalJadeEveryN ?? 12;
        this.dianShuWanThresholdKills = cfg.dianShuWanThresholdKills ?? 3;
        this.dianShuWanProbability = cfg.dianShuWanProbability ?? 0.5;
        this.random = cfg.random ?? Math.random;
    }

    /** Register an enemy kill and return any drops produced. */
    public onEnemyKilled(enemy: EnemyType, at: { x: number; y: number }): IDropEvent[] {
        this.globalKills++;
        const drops: IDropEvent[] = [];
        // Crystal-jade rule (deterministic, req 7.1).
        if (this.globalKills % this.crystalJadeEveryN === 0) {
            drops.push({ item: ItemType.CrystalJade, x: at.x, y: at.y + 180 });
        }
        // Chi Ren consecutive rule (req 7.3).
        if (enemy === EnemyType.ChiRen) {
            this.chiRenConsecutiveKills++;
            if (this.chiRenConsecutiveKills >= this.dianShuWanThresholdKills) {
                this.chiRenConsecutiveKills = 0;
                if (this.random() < this.dianShuWanProbability) {
                    const pickDian = this.random() < 0.5;
                    drops.push({
                        item: pickDian ? ItemType.DianWan : ItemType.ShuWan,
                        x: at.x,
                        y: at.y,
                    });
                }
            }
        } else {
            this.chiRenConsecutiveKills = 0;
        }
        return drops;
    }

    public reset(): void {
        this.globalKills = 0;
        this.chiRenConsecutiveKills = 0;
    }

    public get kills(): number {
        return this.globalKills;
    }
}
