import { IBossConfig } from '../data/Interfaces';

/**
 * Boss controller — 双幻坊 (req 9.1-9.6 + 8.6-8.7).
 *
 * Key beats:
 *  1. A lone butterfly orbits the boss. Until the butterfly is hit, the boss
 *     is invulnerable (`butterflyRevealed = false`).
 *  2. First hit on the butterfly → `revealedAt` timestamp stamped, boss
 *     becomes vulnerable.
 *  3. While revealed, ANY single clean hit kills the boss (req 9.3). We still
 *     honour `phase` transitions at 2/3 and 1/3 HP for visual variety.
 *  4. When HP ≤ `princessCutsceneAtHpRatio`, we emit a one-shot `princess_taken`
 *     event (≤ 3s, battle keeps running — req 8.6 / 14.1).
 *  5. On death we emit `boss_killed` + `chapter_end_cutscene` (≤ 2s). Neither
 *     code path produces a "rope-severing rescue" event — decision D-5 / req
 *     14.5.
 */

export type BossOutcomeEvent =
    | { kind: 'phase_changed'; phase: string; actionIntervalSec: number }
    | { kind: 'butterfly_revealed' }
    | { kind: 'princess_taken_cutscene' }
    | { kind: 'boss_killed' };

export class BossController {
    private hp: number;
    private butterflyRevealed = false;
    private phaseIndex = 0;
    private princessCutscenePlayed = false;
    private killed = false;
    public readonly cfg: IBossConfig;

    constructor(cfg: IBossConfig) {
        this.cfg = cfg;
        this.hp = cfg.hp;
    }

    public get currentHp(): number {
        return this.hp;
    }
    public get currentPhase() {
        return this.cfg.phases[this.phaseIndex];
    }
    public get isButterflyRevealed(): boolean {
        return this.butterflyRevealed;
    }
    public get isDead(): boolean {
        return this.killed;
    }

    /** Called when a player's attack hits the butterfly (req 9.2). */
    public onButterflyHit(): BossOutcomeEvent[] {
        if (this.butterflyRevealed) return [];
        this.butterflyRevealed = true;
        return [{ kind: 'butterfly_revealed' }];
    }

    /**
     * Called when a player's attack hits the boss body. Before the butterfly
     * is revealed this call is a no-op; after reveal, the boss dies in one
     * hit (req 9.3).
     */
    public onBodyHit(): BossOutcomeEvent[] {
        if (!this.butterflyRevealed) return [];
        if (this.killed) return [];
        const out: BossOutcomeEvent[] = [];
        this.hp = Math.max(0, this.hp - 1);
        out.push(...this.checkPhaseTransition(), ...this.checkPrincessCutscene());
        if (this.hp === 0) {
            this.killed = true;
            out.push({ kind: 'boss_killed' });
        }
        return out;
    }

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

    private checkPhaseTransition(): BossOutcomeEvent[] {
        const hpRatio = this.hp / this.cfg.hp;
        for (let i = this.phaseIndex + 1; i < this.cfg.phases.length; i++) {
            if (hpRatio <= this.cfg.phases[i].hpThreshold) {
                this.phaseIndex = i;
                return [
                    {
                        kind: 'phase_changed',
                        phase: this.cfg.phases[i].mode,
                        actionIntervalSec: this.cfg.phases[i].actionIntervalSec,
                    },
                ];
            }
        }
        return [];
    }

    private checkPrincessCutscene(): BossOutcomeEvent[] {
        if (this.princessCutscenePlayed) return [];
        const threshold = this.cfg.princessCutsceneAtHpRatio;
        if (threshold === undefined) return [];
        const hpRatio = this.hp / this.cfg.hp;
        if (hpRatio <= threshold) {
            this.princessCutscenePlayed = true;
            return [{ kind: 'princess_taken_cutscene' }];
        }
        return [];
    }
}
