/**
 * Data-driven configuration interfaces for《影之传说》MVP.
 *
 * Every numeric default in here traces directly back to a requirement in
 * `.codebuddy/plan/kage_legend_mvp/requirements.md`. When you change a field,
 * keep the inline `req` comment in sync so QA can rebuild the traceability
 * matrix.
 *
 * NOTE: This module is platform-agnostic and MUST NOT depend on `cc`.
 */

import { PlayerColorState } from '../common/Constants';

// ---------------------------------------------------------------------------
// Enemies
// ---------------------------------------------------------------------------

/** Enum covers all enemy types required by MVP Chapter 1 (req 6.1-6.7). */
export enum EnemyType {
    /** Green ninja — shuriken + sword, 2s interval (req 6.1). */
    QingRen = 'qing_ren',
    /** Red ninja — 120px/s + smoke bomb, proactive intercept jump (req 6.2-6.3). */
    ChiRen = 'chi_ren',
    /** Black ninja — drops magic flute scroll on castle stages (req 6.5). */
    HeiRen = 'hei_ren',
    /** Monster priest — straight-line fireball, 3.0s interval (req 6.6). */
    YaoFang = 'yao_fang',
}

/** Allowed damage types (req 3.7, 3.8, 10.4-10.5). */
export type AttackType = 'shuriken' | 'sword' | 'fireball' | 'smoke_bomb';

export interface IEnemyConfig {
    id: EnemyType;
    displayName: string;
    /** Pixel sprite size (width x height). */
    size: { w: number; h: number };
    /** Horizontal movement speed (px/s). 0 means stationary. */
    moveSpeed: number;
    /** Attack interval in seconds. */
    attackIntervalSec: number;
    /** Possible attack types. */
    attacks: AttackType[];
    /** Hit points (1 means dies to any successful hit). */
    hp: number;
    /** How many enemies of this type must be killed for chapter objective (optional). */
    killObjective?: number;
    /** Drop rules specific to this enemy type (see `IItemDropRule`). */
    drops?: IItemDropRule[];
}

// ---------------------------------------------------------------------------
// Items
// ---------------------------------------------------------------------------

/** Item IDs used by MVP Chapter 1 (req 7.1-7.6, 5.1-5.6). */
export enum ItemType {
    /** 水晶玉 — auto-upgrades red → green → yellow (req 5.1-5.2). */
    CrystalJade = 'crystal_jade',
    /** 点丸 — +50% attack power, 30s (req 7.3). */
    DianWan = 'dian_wan',
    /** 术丸 — +30% move speed, 20s (req 7.3). */
    ShuWan = 'shu_wan',
    /** 魔笛 — screen-wipe one-shot kill (req 7.4). */
    MoDi = 'mo_di',
    /** 增丸 — +1 permanent life (req 7.5). */
    ZengWan = 'zeng_wan',
}

export interface IItemConfig {
    id: ItemType;
    displayName: string;
    /** Icon asset path under `assets/resources/textures/items`. */
    icon: string;
    /** Duration in seconds for timed buffs (0 / omitted for instant items). */
    durationSec?: number;
    /**
     * Relative strength of the effect (interpretation is per item type;
     * see `IItemEffectApplier` in logic layer for the actual math).
     */
    magnitude?: number;
    /** Lifetime in seconds after spawning on the map (req 7.2). */
    lifetimeSec: number;
}

/** Drop rule attached to an enemy type. Evaluated on enemy death. */
export interface IItemDropRule {
    item: ItemType;
    /** Required consecutive kills of this enemy type before drop can happen. */
    afterKills?: number;
    /** Probability 0~1 once `afterKills` condition is satisfied. */
    probability: number;
}

// ---------------------------------------------------------------------------
// Weapons
// ---------------------------------------------------------------------------

export enum WeaponType {
    Shuriken = 'shuriken',
    NinjaSword = 'ninja_sword',
}

export interface IWeaponConfig {
    id: WeaponType;
    displayName: string;
    /** Base attack interval (s). Yellow state may override for shuriken. */
    baseIntervalSec: number;
    /** Upgraded (green/yellow) interval (s). */
    upgradedIntervalSec?: number;
    /** Damage applied to standard enemies on hit. */
    damage: number;
    /** Supports parry (req 3.7 — only sword). */
    canParry: boolean;
    /** When long-pressed, max shots in a burst (req 3.5 — shuriken only). */
    burstMax?: number;
}

// ---------------------------------------------------------------------------
// Levels (Chapter 1 only)
// ---------------------------------------------------------------------------

/** Scroll direction for a level (req 8.1-8.5). */
export type ScrollDirection = 'horizontal' | 'horizontal_bi' | 'vertical';

export interface ILevelObjective {
    /** e.g. 'kill_yao_fang', 'reach_top', 'boss_defeated'. */
    kind: 'kill_count' | 'reach_top' | 'defeat_boss';
    /** For kill_count objectives — which enemy type, and how many. */
    enemy?: EnemyType;
    /** Required count for kill_count objectives. */
    count?: number;
    /** For defeat_boss objectives — boss ID. */
    bossId?: string;
}

export interface ILevelConfig {
    id: string; // e.g. '1-1'
    chapter: 1 | 2 | 3;
    displayName: string;
    /** One of 'forest' / 'cave' / 'castle_wall' / 'demon_castle'. */
    sceneTheme: string;
    scrollDirection: ScrollDirection;
    /** Time limit in seconds (req 8.1-8.4). */
    timeLimitSec: number;
    objective: ILevelObjective;
    /** Scene length in pixels (landscape 16:9 baseline, req 8.8). */
    levelLengthPx: number;
    /** BGM bundle key under `assets/resources/audio`. */
    bgm: string;
    /** Enemy spawn list evaluated by the LevelMgr. */
    enemySpawns: Array<{ type: EnemyType; atPx: number; count?: number }>;
}

// ---------------------------------------------------------------------------
// Bosses
// ---------------------------------------------------------------------------

export interface IBossAttackPhase {
    /** HP threshold at which this phase activates (1.0, 0.66, 0.33, ...). */
    hpThreshold: number;
    /** Human-readable mode id (e.g. 'pair_pincer', 'fireball_spread', 'clone_confuse'). */
    mode: string;
    /** Interval between actions in this phase (s). */
    actionIntervalSec: number;
}

export interface IBossConfig {
    id: string;
    displayName: string;
    hp: number;
    /** A non-zero value means "butterfly appearance required before damage". */
    butterflyReveal: boolean;
    /** Ordered from highest hpThreshold to lowest. */
    phases: IBossAttackPhase[];
    /** Cutscene trigger (req 8.6 / 14.1): play short "princess taken" at hp<=X. */
    princessCutsceneAtHpRatio?: number;
}

// ---------------------------------------------------------------------------
// Story intro (req 19)
// ---------------------------------------------------------------------------

export interface IStoryPageConfig {
    /** 1-based page index. */
    index: number;
    /** Texture path under `assets/resources/textures/story`. */
    illustration: string;
    /** Pixel typewriter text to display. */
    text: string;
}

export interface IStorySceneConfig {
id: string; // e.g. 'chapter_1_intro'
    bgm: string; // e.g. 'bgm_story'
    /** Max total duration (seconds); UI should auto-advance if exceeded. */
    maxDurationSec: number;
    pages: IStoryPageConfig[];
}

// ---------------------------------------------------------------------------
// Aggregate configuration table
// ---------------------------------------------------------------------------

export interface IChapter1ConfigBundle {
    enemies: IEnemyConfig[];
    items: IItemConfig[];
    weapons: IWeaponConfig[];
    levels: ILevelConfig[];
    bosses: IBossConfig[];
    stories: IStorySceneConfig[];
}

/**
 * Describes which player-state the JSON config applies to. We explicitly
 * leave **no room** for a 'casual' mode string so that future edits cannot
 * silently reintroduce the removed difficulty (decision D-4, req 13.1-13.6).
 */
export type DifficultyProfile = 'hardcore';

export const ONLY_DIFFICULTY: DifficultyProfile = 'hardcore';

/** Convenience map for looking up the red/green/yellow state that unlocks each move-speed bucket. */
export const COLOR_STATE_MOVE_BUCKET: Record<PlayerColorState, number> = {
    [PlayerColorState.Red]: 100,
    [PlayerColorState.Green]: 100,
    [PlayerColorState.Yellow]: 150,
};
