/** Звук и длительность эффекта «Облако яда» (`public/oblako-yada.mp3`). */

import { getEffectsSfxGain } from './effectsSfxGain';

const POISON_CLOUD_SFX_VOLUME = 0.92;

/** Запас, если метаданные не прочитались. */
const DEFAULT_POISON_CLOUD_LIFE_MS = 1600;

export function poisonCloudEffectSoundUrl(): string {
  return new URL('oblako-yada.mp3', window.location.href).href;
}

let cachedPoisonCloudSfxDurationMs: number | null = null;

/** Длительность трека в мс (кэш после первого чтения метаданных). */
export function getPoisonCloudSfxDurationMs(): Promise<number> {
  if (cachedPoisonCloudSfxDurationMs !== null) {
    return Promise.resolve(cachedPoisonCloudSfxDurationMs);
  }
  const url = poisonCloudEffectSoundUrl();
  return new Promise((resolve) => {
    const a = new Audio();
    const done = (ms: number): void => {
      cachedPoisonCloudSfxDurationMs = ms;
      a.removeAttribute('src');
      resolve(ms);
    };
    a.addEventListener('loadedmetadata', () => {
      const d = a.duration;
      done(Number.isFinite(d) && d > 0 ? Math.round(d * 1000) : DEFAULT_POISON_CLOUD_LIFE_MS);
    });
    a.addEventListener('error', () => done(DEFAULT_POISON_CLOUD_LIFE_MS));
    a.src = url;
    a.load();
  });
}

/** Длительность визуала = длительности файла (с разумными пределами). */
export async function getPoisonCloudEffectLifeMs(): Promise<number> {
  const raw = await getPoisonCloudSfxDurationMs();
  return Math.min(60_000, Math.max(600, raw));
}

/**
 * Воспроизведение с подгонкой скорости: фактическое время звука по часам ≈ `lifeMs`,
 * чтобы совпасть с анимацией.
 */
export async function playPoisonCloudEffectSound(lifeMs: number): Promise<void> {
  try {
    const rawMs = await getPoisonCloudSfxDurationMs();
    const target = Math.max(200, lifeMs);
    const rate = Math.max(0.25, Math.min(4, rawMs / target));
    const el = new Audio(poisonCloudEffectSoundUrl());
    el.volume = Math.max(0, Math.min(1, POISON_CLOUD_SFX_VOLUME * getEffectsSfxGain()));
    el.playbackRate = rate;
    void el.play().catch(() => undefined);
  } catch {
    /* ignore */
  }
}
