/**
 * Sfx на спек-синтезе: ключ → SoundSpec (компилирует движок, WAV не нужен).
 * Формулы — бывшие генераторы tools/audio/gen.mjs (функции экспортированы
 * там же); парити-тест sfxSpecs.test.ts сверяет renderSpec с ними численно,
 * поэтому миграция не изменила звучание.
 */
import type { AudioManager, PlayOptions, SoundSpec } from '@rpg/engine';

/** Реестр спек-звуков (ключи валидируются тем же validate-тестом, что и WAV). */
export const SPEC_SFX: Record<string, SoundSpec> = {
    // Бывший sfx/bell_hit.wav (bellHit): 4 партиала + клик, normalize 0.7.
    'sfx/bell_hit': { kind: 'chime', dur: 0.35, freq: 520, power: 5, seed: 1, peak: 0.7 },
    // Бывший sfx/whoosh.wav (whoosh): воздух «0 → 1 → 0», normalize 0.4.
    'sfx/whoosh': { kind: 'scrape', dur: 0.7, low: 200, high: 2400, seed: 160, swell: true, peak: 0.4 },
    // Бывший sfx/bell_low.wav (bellLow): три тона с тремоло 6 Гц.
    'sfx/bell_low': {
        kind: 'tone', dur: 0.9, freq: 110, w: 0.5, power: 2, peak: 0.6,
        wobbleHz: 6, wobbleDepth: 0.3,
        layers: [{ freq: 165, w: 0.25 }, { freq: 220.5, w: 0.12 }]
    },
    // Бывший sfx/ash_hiss.wav (ashHiss): шипение с нарастанием 0.08 с.
    'sfx/ash_hiss': { kind: 'scrape', dur: 0.4, low: 900, high: 4200, seed: 11, power: 2, attack: 0.08, peak: 0.55 },
    // Бывший sfx/ash_die.wav (ashDie): шум, громкость спадает вдвое к концу.
    'sfx/ash_die': { kind: 'scrape', dur: 0.6, low: 300, high: 2400, seed: 23, power: 3, fadeTo: 0.5, peak: 0.6 },
    // Бывший sfx/spit.wav (spit): тон со свипом 700→350 Гц + шипящий хвост.
    'sfx/spit': {
        kind: 'tone', dur: 0.2, freq: 700, freqTo: 350, w: 0.6, power: 3, peak: 0.5,
        layers: [{ low: 2000, high: 6000, seed: 37, w: 0.4 }]
    },
    // Бывший sfx/hurt.wav (hurt): глухой удар 90 Гц + низкий шум.
    'sfx/hurt': {
        kind: 'tone', dur: 0.25, freq: 90, w: 0.8, power: 3, peak: 0.65,
        layers: [{ low: 80, high: 400, seed: 41, w: 0.3, dur: 0.125, power: 2 }]
    },
    // Бывший sfx/mote_pickup.wav (motePickup): двойной звон 1240+1860 Гц
    // (у верхнего партиала суммарная крутизна 4+2.5 — два затухания gen.mjs).
    'sfx/mote_pickup': {
        kind: 'tone', dur: 0.45, freq: 1240, w: 0.4, power: 2.5, peak: 0.4,
        layers: [{ freq: 1860, w: 0.2, power: 6.5 }]
    },
    // Бывший sfx/pickup.wav (pickup): «пок» со взлётом 520→740 Гц.
    'sfx/pickup': { kind: 'tone', dur: 0.14, freq: 520, freqTo: 740, power: 2.5, peak: 0.4 },
    // Бывший sfx/chest_open.wav (chestOpen): скрип петель + удар крышки 110 Гц.
    'sfx/chest_open': {
        kind: 'scrape', dur: 0.55, low: 300, high: 1400, seed: 157, power: 1.5, w: 0.35, attack: 0.1, peak: 0.45,
        layers: [{ freq: 110, w: 0.7, dur: 0.12, power: 2 }]
    },
    // Бывший sfx/note.wav (note): шелест с гулким «воблером» 3.2 Гц.
    'sfx/note': {
        kind: 'scrape', dur: 0.35, low: 1800, high: 6000, seed: 159, power: 1.5, peak: 0.3,
        wobbleHz: 3.2, wobbleDepth: 0.6, wobbleBase: 0.4, wobblePhase: 1
    },
    // Бывший sfx/deer_startle.wav (deerStartle): выдох + стук копыт (блип 90 Гц).
    'sfx/deer_startle': {
        kind: 'scrape', dur: 0.4, low: 150, high: 900, seed: 161, power: 2, w: 0.7, attack: 0.05, peak: 0.4,
        layers: [{ freq: 90, w: 0.6, dur: 0.08, delay: 0.2 }]
    },
    // Бывший sfx/ui_click.wav (uiClick): короткий чистый тон 880 Гц.
    'sfx/ui_click': { kind: 'tone', dur: 0.06, freq: 880, power: 3, peak: 0.4 },
    // Бывший sfx/chime.wav (chime): колокольчик Милы, 1560 Гц + партиал 1.61×.
    'sfx/chime': {
        kind: 'tone', dur: 0.5, freq: 1560, w: 0.5, power: 3, peak: 0.45,
        layers: [{ freq: 1560 * 1.61, w: 0.25 }]
    },
    // Шаги (бывшие sfx/step_*.wav): до unlock играет спек, варианты —
    // renderSpec с сидами seed+i·10 (см. systems/StepVariants.ts).
    'sfx/step_grass': { kind: 'hit', dur: 0.12, low: 400, high: 2000, seed: 253, power: 2, peak: 0.3 },
    'sfx/step_ash': { kind: 'hit', dur: 0.14, low: 200, high: 1100, seed: 254, power: 2.5, peak: 0.3 },
    'sfx/step_water': {
        kind: 'hit', dur: 0.18, low: 600, high: 3200, seed: 255, power: 2, w: 0.6, peak: 0.3,
        layers: [{ freq: 300, w: 0.2 }]
    },
    'sfx/step_floor': {
        kind: 'hit', dur: 0.1, low: 150, high: 800, seed: 256, power: 3, w: 0.4, peak: 0.3,
        layers: [{ freq: 140, w: 0.5 }]
    },
    // Дальний шорох пепла («мир живой»): медленный вздох шума, панорама/вариации
    // задаёт тик сцены (LocationScene.updateAmbient).
    'sfx/rustle': {
        kind: 'scrape', dur: 0.5, low: 400, high: 1800, seed: 263, power: 1.2, attack: 0.15, peak: 0.25
    }
};

/**
 * Room tone интерьеров: тихий луп-гул «внутри помещения» (шина ambience).
 * Ключи — строковые id областей (см. locations.ts), БЕЗ типа AreaId — иначе
 * цикл импортов audio.ts → sfxSpecs → locations → interactables → audio.ts.
 * Проверка «ключи ⊆ AREAS» — в validate-тестах.
 */
export const ROOM_TONES: Record<string, SoundSpec> = {
    // Дом Ирвина: очаг + скрип половиц — низкий гул с медленным «дыханием».
    house_elder: { kind: 'hum', tone: 52, dur: 8, power: 2, peak: 0.3 },
    // Лавка Милы: чуть выше и с лёгким тремоло (колокольчики на витрине).
    shop: { kind: 'hum', tone: 66, dur: 8, power: 3, peak: 0.28, wobbleHz: 0.4, wobbleDepth: 0.15 }
};

/**
 * Единая точка проигрывания sfx по ключу: спек-звук — через playSpec
 * (движок компилирует сам), файловый — через play. Все play-сайты игры
 * зовут этот хелпер, а не audio.play напрямую.
 */
export function playSfx(audio: AudioManager, key: string, opts?: number | PlayOptions): void {
    const spec = SPEC_SFX[key];
    if (spec) void audio.playSpec(key, spec, opts);
    else void audio.play(key, opts);
}