import { AttackType } from '../data/Interfaces';
import { PlayerStateMachine, DamageOutcome } from './PlayerStateMachine';

/**
 * DamageSystem — the single funnel through which **every** player-facing
 * damage event must flow (req 10.1-10.6).
 *
 * Decision precedence (req 10.3):
 *   1. i-frames  → no effect
 *   2. sword parry → no effect (only vs. shuriken/sword; see PSM)
 *   3. attack type × distance → dispatch to PlayerStateMachine.takeHit
 *
 * Distance thresholds:
 *   - fireball: lethal within 100px (req 10.4)
 *   - smoke bomb: lethal within 80px (req 10.5)
 *   - shuriken / sword: any contact is eligible
 *
 * Enemy-facing damage is a separate, simpler `applyToEnemy` helper.
 */

export interface IDamageContext {
    attackType: AttackType;
    attackerX: number;
    attackerY: number;
    victimX: number;
    victimY: number;
}

export const FIREBALL_KILL_RADIUS = 100;
export const SMOKE_KILL_RADIUS = 80;

export class DamageSystem {
    constructor(private readonly psm: PlayerStateMachine) {}

    /** Try to damage the player. Returns `null` if the attack missed by distance. */
    public applyToPlayer(ctx: IDamageContext): DamageOutcome | null {
        const distance = Math.hypot(ctx.attackerX - ctx.victimX, ctx.attackerY - ctx.victimY);
        if (ctx.attackType === 'fireball' && distance > FIREBALL_KILL_RADIUS) return null;
        if (ctx.attackType === 'smoke_bomb' && distance > SMOKE_KILL_RADIUS) return null;
        // shuriken / sword rely on caller-side hitbox; reaching here means "hit".
        return this.psm.takeHit(ctx.attackType);
    }

    /**
     * Apply flat damage to an enemy HP bucket. The damage number comes from
     * the active weapon config. Returns the remaining HP (0 means killed).
     */
    public applyToEnemy(currentHp: number, damage: number): number {
        return Math.max(0, currentHp - damage);
    }
}
