"""Audio utilities for format conversion and resampling."""

from __future__ import annotations

import io
import logging
import subprocess
import tempfile

import numpy as np
import soundfile as sf

logger = logging.getLogger(__name__)


def _convert_to_wav(audio_bytes: bytes) -> bytes:
    """Convert any audio format to WAV using ffmpeg."""
    with tempfile.NamedTemporaryFile(suffix=".input", delete=True) as inp, \
         tempfile.NamedTemporaryFile(suffix=".wav", delete=True) as out:
        inp.write(audio_bytes)
        inp.flush()
        result = subprocess.run(
            ["ffmpeg", "-y", "-i", inp.name, "-ar", "16000", "-ac", "1", "-f", "wav", out.name],
            capture_output=True,
            timeout=30,
        )
        if result.returncode != 0:
            raise RuntimeError(f"ffmpeg conversion failed: {result.stderr.decode()}")
        out.seek(0)
        return out.read()


def read_audio(audio_bytes: bytes, target_sr: int = 16000) -> np.ndarray:
    """Read audio bytes into a numpy array, resampled to target_sr and converted to mono.

    Supports WAV, FLAC, OGG natively via soundfile.
    Falls back to ffmpeg for other formats (WebM, MP3, etc.).
    """
    try:
        data, sr = sf.read(io.BytesIO(audio_bytes), dtype="float32")
    except Exception:
        logger.info("soundfile cannot read format, converting via ffmpeg")
        wav_bytes = _convert_to_wav(audio_bytes)
        data, sr = sf.read(io.BytesIO(wav_bytes), dtype="float32")

    # Convert to mono if stereo
    if data.ndim > 1:
        data = data.mean(axis=1)
    if sr != target_sr:
        data = resample(data, sr, target_sr)
    return data


def audio_to_wav_bytes(audio: np.ndarray, sample_rate: int) -> bytes:
    """Convert a numpy audio array to WAV bytes."""
    buf = io.BytesIO()
    sf.write(buf, audio, sample_rate, format="WAV")
    buf.seek(0)
    return buf.read()


def resample(audio: np.ndarray, orig_sr: int, target_sr: int) -> np.ndarray:
    """Resample audio using linear interpolation."""
    if orig_sr == target_sr:
        return audio
    duration = len(audio) / orig_sr
    target_len = int(duration * target_sr)
    indices = np.linspace(0, len(audio) - 1, target_len)
    return np.interp(indices, np.arange(len(audio)), audio).astype(np.float32)
