"""Audio processing utilities."""

import io
import wave
from typing import Optional

import numpy as np
import pyaudio


class AudioProcessor:
    """Handles audio capture and processing."""

    def __init__(self, sample_rate: int = 16000, channels: int = 1):
        """Initialize audio processor."""
        self.sample_rate = sample_rate
        self.channels = channels
        self.chunk_size = 1024
        self.format = pyaudio.paInt16

        # Initialize PyAudio
        self.audio = pyaudio.PyAudio()

        # Audio buffer for accumulating chunks
        self.buffer = []
        self.min_speech_duration = 0.5  # seconds

    def start_recording(self) -> pyaudio.Stream:
        """Start audio recording stream."""
        stream = self.audio.open(
            format=self.format,
            channels=self.channels,
            rate=self.sample_rate,
            input=True,
            frames_per_buffer=self.chunk_size,
        )
        return stream

    def stop_recording(self, stream: pyaudio.Stream) -> None:
        """Stop audio recording."""
        stream.stop_stream()
        stream.close()

    def process_chunk(self, audio_bytes: bytes) -> np.ndarray:
        """Convert audio bytes to numpy array."""
        # Convert bytes to numpy array
        audio_array = np.frombuffer(audio_bytes, dtype=np.int16)

        # Normalize to [-1, 1]
        audio_float = audio_array.astype(np.float32) / 32768.0

        return audio_float

    def has_speech(self, audio_chunk: np.ndarray, energy_threshold: float = 0.01) -> bool:
        """Simple voice activity detection based on energy."""
        # Calculate RMS energy
        energy = np.sqrt(np.mean(audio_chunk**2))

        # Check if energy exceeds threshold
        return energy > energy_threshold

    def save_audio(self, audio_data: bytes, filepath: str) -> None:
        """Save audio data to WAV file."""
        with wave.open(filepath, "wb") as wf:
            wf.setnchannels(self.channels)
            wf.setsampwidth(self.audio.get_sample_size(self.format))
            wf.setframerate(self.sample_rate)
            wf.writeframes(audio_data)

    def __del__(self):
        """Cleanup PyAudio."""
        if hasattr(self, "audio"):
            self.audio.terminate()