"""Voice Activity Detector avec machine d'état."""

import time
from dataclasses import dataclass
from enum import Enum
from typing import Optional, Dict, Any

from .config import VADConfig


class VADState(Enum):
    """États du VAD."""

    IDLE = "idle"
    ACTIVE = "active"
    RELEASE = "release"


@dataclass
class VADResult:
    """Résultat du VAD."""

    active: bool
    rms: float
    timestamp_ms: int
    end_of_speech: bool = False
    state: str = "idle"


class VoiceActivityDetector:
    """Détecteur d'activité vocale avec hystérésis."""

    def __init__(self, config: VADConfig, frame_duration_ms: float = 20.0):
        """
        Initialise le VAD.

        Args:
            config: Configuration VAD
            frame_duration_ms: Durée d'une frame en millisecondes
        """
        self.config = config
        self.frame_duration_ms = frame_duration_ms

        # État machine
        self.state = VADState.IDLE
        self.state_duration_ms = 0.0
        self.last_active_time_ms = 0.0

        # Statistiques
        self.total_frames = 0
        self.active_frames = 0

    def update_config(self, new_config: VADConfig) -> None:
        """Met à jour la configuration à chaud."""
        self.config = new_config

    def process(self, rms: float) -> VADResult:
        """
        Traite une frame audio et met à jour l'état VAD.

        Args:
            rms: Valeur RMS normalisée [0..1]

        Returns:
            Résultat VAD avec état et métadonnées
        """
        current_time_ms = int(time.time() * 1000)
        self.total_frames += 1

        # Seuil dépassé ?
        above_threshold = rms > self.config.threshold

        # Machine d'état
        previous_state = self.state
        end_of_speech = False

        if self.state == VADState.IDLE:
            if above_threshold:
                self.state_duration_ms += self.frame_duration_ms
                if self.state_duration_ms >= self.config.attack_ms:
                    self.state = VADState.ACTIVE
                    self.state_duration_ms = 0.0
                    self.last_active_time_ms = current_time_ms
            else:
                self.state_duration_ms = 0.0

        elif self.state == VADState.ACTIVE:
            if above_threshold:
                self.last_active_time_ms = current_time_ms
                self.state_duration_ms = 0.0
            else:
                self.state_duration_ms += self.frame_duration_ms
                if self.state_duration_ms >= self.config.release_ms:
                    self.state = VADState.RELEASE
                    self.state_duration_ms = 0.0

        elif self.state == VADState.RELEASE:
            if above_threshold:
                self.state = VADState.ACTIVE
                self.state_duration_ms = 0.0
                self.last_active_time_ms = current_time_ms
            else:
                self.state_duration_ms += self.frame_duration_ms
                # Détection fin de parole
                if (current_time_ms - self.last_active_time_ms) >= self.config.eos_ms:
                    end_of_speech = True
                    self.state = VADState.IDLE
                    self.state_duration_ms = 0.0

        # Statistiques
        is_active = self.state == VADState.ACTIVE
        if is_active:
            self.active_frames += 1

        return VADResult(
            active=is_active,
            rms=rms,
            timestamp_ms=current_time_ms,
            end_of_speech=end_of_speech,
            state=self.state.value,
        )

    def get_stats(self) -> Dict[str, Any]:
        """Retourne les statistiques du VAD."""
        if self.total_frames == 0:
            active_ratio = 0.0
        else:
            active_ratio = self.active_frames / self.total_frames

        return {
            "total_frames": self.total_frames,
            "active_frames": self.active_frames,
            "active_ratio": round(active_ratio, 3),
            "current_state": self.state.value,
            "config": self.config.to_dict(),
        }

    def reset_stats(self) -> None:
        """Remet à zéro les statistiques."""
        self.total_frames = 0
        self.active_frames = 0

    def reset(self) -> None:
        """Remet à zéro l'état complet du VAD."""
        self.state = VADState.IDLE
        self.state_duration_ms = 0.0
        self.last_active_time_ms = 0.0
        self.reset_stats()


def create_vad(
    threshold: float = 0.3,
    attack_ms: int = 80,
    release_ms: int = 200,
    eos_ms: int = 800,
) -> VoiceActivityDetector:
    """Fonction utilitaire pour créer un VAD avec config simple."""
    config = VADConfig(
        threshold=threshold, attack_ms=attack_ms, release_ms=release_ms, eos_ms=eos_ms
    )
    return VoiceActivityDetector(config)
