"""Audio utilities for dtelecom-stt SDK."""

import asyncio
import wave

from .exceptions import AudioFormatError

# PCM16 mono 16kHz constants
SAMPLE_RATE = 16000
SAMPLE_WIDTH = 2  # 16-bit = 2 bytes
CHANNELS = 1
BYTES_PER_SECOND = SAMPLE_RATE * SAMPLE_WIDTH * CHANNELS


def load_wav(path: str) -> tuple[bytes, int, int, int]:
    """Load a WAV file and return (pcm_data, sample_rate, channels, sample_width).

    Validates that the file is PCM16, 16kHz, mono.
    """
    try:
        with wave.open(path, "rb") as wf:
            sample_rate = wf.getframerate()
            channels = wf.getnchannels()
            sample_width = wf.getsampwidth()

            if sample_rate != SAMPLE_RATE:
                raise AudioFormatError(
                    f"Expected {SAMPLE_RATE}Hz, got {sample_rate}Hz. "
                    f"Resample with: ffmpeg -i input.wav -ar 16000 -ac 1 output.wav"
                )
            if channels != CHANNELS:
                raise AudioFormatError(
                    f"Expected mono, got {channels} channels. "
                    f"Convert with: ffmpeg -i input.wav -ac 1 output.wav"
                )
            if sample_width != SAMPLE_WIDTH:
                raise AudioFormatError(
                    f"Expected 16-bit, got {sample_width * 8}-bit. "
                    f"Convert with: ffmpeg -i input.wav -acodec pcm_s16le output.wav"
                )

            pcm_data = wf.readframes(wf.getnframes())
            return pcm_data, sample_rate, channels, sample_width
    except wave.Error as e:
        raise AudioFormatError(f"Cannot read WAV file: {e}") from e
    except FileNotFoundError:
        raise AudioFormatError(f"File not found: {path}")


async def stream_realtime(ws, pcm_data: bytes, chunk_ms: int = 20):
    """Stream PCM16 audio at real-time speed over a WebSocket.

    Args:
        ws: WebSocket connection (websockets library).
        pcm_data: Raw PCM16 mono 16kHz bytes.
        chunk_ms: Chunk size in milliseconds (default 20ms).
    """
    chunk_bytes = int(BYTES_PER_SECOND * chunk_ms / 1000)
    offset = 0
    while offset < len(pcm_data):
        chunk = pcm_data[offset : offset + chunk_bytes]
        await ws.send(chunk)
        offset += chunk_bytes
        await asyncio.sleep(chunk_ms / 1000)


def silence(duration_seconds: float) -> bytes:
    """Generate PCM16 silence bytes (16kHz mono)."""
    num_bytes = int(BYTES_PER_SECOND * duration_seconds)
    return b"\x00" * num_bytes
