"""
Audio Ingestion Module for VideoDetection.
Tách luồng âm thanh 16kHz Mono từ video và chia đoạn nhỏ cho mô hình NeuralFP.
"""
from __future__ import annotations

import subprocess
from dataclasses import dataclass
from pathlib import Path
from typing import Generator, Optional, Tuple

import numpy as np

from ..core.paths import TEMP_DIR, get_ffmpeg_path


@dataclass
class AudioStreamInfo:
    has_audio: bool
    sample_rate: int
    duration_sec: float


class AudioChunkExtractor:
    """
    Trích xuất audio waveform 16kHz mono phục vụ trích xuất Neural Audio Fingerprints.
    """

    def __init__(
        self,
        sample_rate: int = 16000,
        chunk_duration_sec: float = 1.0,
        hop_duration_sec: float = 0.5,
    ) -> None:
        self.sample_rate = sample_rate
        self.chunk_duration_sec = chunk_duration_sec
        self.hop_duration_sec = hop_duration_sec
        self.chunk_samples = int(self.sample_rate * self.chunk_duration_sec)
        self.hop_samples = int(self.sample_rate * self.hop_duration_sec)
        self.ffmpeg_bin = get_ffmpeg_path()

    def extract_waveform(self, video_path: Path) -> Optional[np.ndarray]:
        """
        Trích xuất toàn bộ waveform float32 [-1.0, 1.0] chuẩn hóa 16kHz Mono từ video.
        Trả về None nếu video không có tiếng (muted).
        """
        cmd = [
            self.ffmpeg_bin,
            "-v", "error",
            "-i", str(video_path),
            "-vn",
            "-ac", "1",
            "-ar", str(self.sample_rate),
            "-f", "f32le",
            "-",
        ]

        try:
            result = subprocess.run(
                cmd,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                check=False,
            )
            if result.returncode != 0 or len(result.stdout) == 0:
                return None

            waveform = np.frombuffer(result.stdout, dtype=np.float32)
            return waveform
        except Exception:
            return None

    def extract_chunks(
        self,
        video_path: Path,
    ) -> Generator[Tuple[float, np.ndarray], None, None]:
        """
        Yield: (timestamp_start_sec, chunk_array[chunk_samples] float32)
        """
        waveform = self.extract_waveform(video_path)
        if waveform is None or len(waveform) < self.chunk_samples:
            return

        total_samples = len(waveform)
        start_idx = 0

        while start_idx + self.chunk_samples <= total_samples:
            chunk = waveform[start_idx : start_idx + self.chunk_samples]
            timestamp_sec = start_idx / float(self.sample_rate)
            yield (timestamp_sec, chunk)
            start_idx += self.hop_samples
