"""Audio formatting utilities."""

import base64
import io

import numpy as np


def float_to_pcm16(audio: np.ndarray) -> bytes:
    """Convert float32 audio in [-1, 1] to little-endian 16-bit PCM bytes."""
    clipped = np.clip(audio, -1.0, 1.0)
    pcm = (clipped * 32767).astype(np.int16)
    return pcm.tobytes()


def pcm16_to_base64(pcm_bytes: bytes) -> str:
    return base64.b64encode(pcm_bytes).decode("ascii")


def float_to_wav_bytes(audio: np.ndarray, sample_rate: int) -> bytes:
    """Wrap float audio into a WAV file in memory."""
    pcm = float_to_pcm16(audio)
    header = _build_wav_header(len(pcm), sample_rate, 1, 16)
    return header + pcm


def _build_wav_header(data_size: int, sample_rate: int, channels: int, bits_per_sample: int) -> bytes:
    byte_rate = sample_rate * channels * bits_per_sample // 8
    block_align = channels * bits_per_sample // 8

    header = b"RIFF"
    header += (36 + data_size).to_bytes(4, "little")
    header += b"WAVE"
    header += b"fmt "
    header += (16).to_bytes(4, "little")  # subchunk size
    header += (1).to_bytes(2, "little")  # PCM
    header += channels.to_bytes(2, "little")
    header += sample_rate.to_bytes(4, "little")
    header += byte_rate.to_bytes(4, "little")
    header += block_align.to_bytes(2, "little")
    header += bits_per_sample.to_bytes(2, "little")
    header += b"data"
    header += data_size.to_bytes(4, "little")
    return header
