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

/**
 * Level lifecycle manager (task 7.1 + 7.2).
 *
 * Given an `ILevelConfig`, this class:
 *   - ticks the time-limit countdown (req 8.1-8.5)
 *   - tracks kill counters by enemy type
 *   - evaluates the level objective each tick
 *   - emits a structured `LevelResult` when the level ends
 *
 * Scene + parallax rendering live in the Cocos view layer; this module is
 * intentionally engine-agnostic so the whole progression logic is Jest-
 * testable.
 */

export type LevelStatus = 'running' | 'victory' | 'timeout' | 'player_dead';

export interface ILevelResult {
    status: LevelStatus;
    elapsedSec: number;
    kills: Record<string, number>;
    remainingSec: number;
}

export class LevelMgr {
    private elapsedSec = 0;
    private kills = new Map<EnemyType, number>();
    private totalKills = 0;
    private bossKilled = false;
    private reachedTop = false;
    private playerDead = false;
    public readonly level: ILevelConfig;

    constructor(level: ILevelConfig) {
        this.level = level;
    }

    public tick(dtSec: number): LevelStatus {
        if (this.isTerminal()) return this.currentStatus();
        this.elapsedSec += dtSec;
        return this.currentStatus();
    }

    public onEnemyKilled(enemy: EnemyType): void {
        this.kills.set(enemy, (this.kills.get(enemy) ?? 0) + 1);
        this.totalKills++;
    }

    public onBossKilled(): void {
        this.bossKilled = true;
    }

    public onReachedTop(): void {
        this.reachedTop = true;
    }

    public onPlayerDied(): void {
        this.playerDead = true;
    }

    public result(): ILevelResult {
        return {
            status: this.currentStatus(),
            elapsedSec: this.elapsedSec,
            kills: this.killsAsObject(),
            remainingSec: Math.max(0, this.level.timeLimitSec - this.elapsedSec),
        };
    }

    public get totalKillsCount(): number {
        return this.totalKills;
    }

    // ------------------------------------------------------------------

    private currentStatus(): LevelStatus {
        if (this.playerDead) return 'player_dead';
        if (this.evaluateObjective(this.level.objective)) return 'victory';
        if (this.elapsedSec >= this.level.timeLimitSec) return 'timeout';
        return 'running';
    }

    private isTerminal(): boolean {
        const s = this.currentStatus();
        return s !== 'running';
    }

    private evaluateObjective(o: ILevelObjective): boolean {
        if (o.kind === 'kill_count' && o.enemy && o.count) {
            return (this.kills.get(o.enemy) ?? 0) >= o.count;
        }
        if (o.kind === 'reach_top') {
            return this.reachedTop;
        }
        if (o.kind === 'defeat_boss') {
            return this.bossKilled;
        }
        return false;
    }

    private killsAsObject(): Record<string, number> {
        const out: Record<string, number> = {};
        for (const [k, v] of this.kills.entries()) out[k] = v;
        return out;
    }
}
