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

/**
 * Score system (task 9.3, req 12.1-12.8).
 *
 * Scoring table:
 *  - Ninja sword kill              ×2.0 base
 *  - Shuriken kill                 ×1.0 base
 *  - Perfect parry counterkill     ×3.0 base
 *  - 5-combo "刃接触" bonus         +1500
 *  - Flawless level (no damage)    ×3.0 total
 *  - Remaining time bonus          +10 pts / remaining sec
 *
 * Everything is deterministic and `Math.random`-free so QA can reproduce
 * every score calculation in unit tests.
 */

export const BASE_ENEMY_SCORE = 100;
export const COMBO_BONUS = 1500;
export const COMBO_THRESHOLD = 5;
export const TIME_BONUS_PER_SEC = 10;

export interface IScoreSnapshot {
    baseScore: number;
    comboBonus: number;
    timeBonus: number;
    flawlessMultiplier: number;
    finalScore: number;
    killCount: number;
    comboCount: number;
    consecutiveBladeHits: number;
}

export class ScoreSystem {
    private baseScore = 0;
    private comboBonus = 0;
    private killCount = 0;
    private consecutiveBladeHits = 0;
    private comboCount = 0;
    private flawless = true;
    private timeBonus = 0;

    public reset(): void {
        this.baseScore = 0;
        this.comboBonus = 0;
        this.killCount = 0;
        this.consecutiveBladeHits = 0;
        this.comboCount = 0;
        this.flawless = true;
        this.timeBonus = 0;
    }

    /** Record a kill weighted by weapon type (req 12.1-12.2). */
    public recordEnemyKill(weapon: WeaponType): void {
        this.killCount++;
        const multiplier = weapon === WeaponType.NinjaSword ? 2 : 1;
        this.baseScore += BASE_ENEMY_SCORE * multiplier;
    }

    /** Perfect parry followed by a counter-kill (req 12.3). */
    public recordParryKill(): void {
        this.killCount++;
        this.baseScore += BASE_ENEMY_SCORE * 3;
    }

    /** Record a single blade contact; every 5 contacts award a combo bonus (req 12.4). */
    public recordBladeContact(): void {
        this.consecutiveBladeHits++;
        if (this.consecutiveBladeHits >= COMBO_THRESHOLD) {
            this.comboCount++;
            this.comboBonus += COMBO_BONUS;
            this.consecutiveBladeHits = 0;
        }
    }

    /** Resets the consecutive blade counter if the combo is broken. */
    public breakBladeChain(): void {
        this.consecutiveBladeHits = 0;
    }

    /** Player took damage → flawless multiplier lost (req 12.5). */
    public markTaken(): void {
        this.flawless = false;
    }

    /** Stage-end timing bonus (req 12.6). */
    public setRemainingTimeBonus(remainingSec: number): void {
        this.timeBonus = Math.max(0, Math.floor(remainingSec)) * TIME_BONUS_PER_SEC;
    }

    public snapshot(): IScoreSnapshot {
        const flawlessMultiplier = this.flawless ? 3 : 1;
        const finalScore = (this.baseScore + this.comboBonus + this.timeBonus) * flawlessMultiplier;
        return {
            baseScore: this.baseScore,
            comboBonus: this.comboBonus,
            timeBonus: this.timeBonus,
            flawlessMultiplier,
            finalScore,
            killCount: this.killCount,
            comboCount: this.comboCount,
            consecutiveBladeHits: this.consecutiveBladeHits,
        };
    }
}
