"""
Service de transcription audio via Groq Whisper Large v3.

Free tier Groq : 4h audio/jour, modèle whisper-large-v3.
Auto-détection de la langue (fr/ar/darija).

Usage :
    from app.services.whisper_service import whisper_service
    
    with open("audio.m4a", "rb") as f:
        result = await whisper_service.transcribe(f.read(), filename="audio.m4a")
    
    print(result.transcript)
    print(result.detected_language)
    print(f"{result.duration_seconds}s")
"""

import time
from dataclasses import dataclass
from typing import Optional

from groq import Groq
from app.core.config import settings


# Soft bias context sent to Whisper (not a vocabulary filter).
# Helps recognition of BTP terms and Moroccan proper nouns.
# Whisper prompt budget is ~224 tokens; this prompt stays well within bounds.
# Includes a Latin-script Darija example to bias Whisper toward Latin transcription
# even when it detects Arabic — prevents Darija from being transcribed in Arabic script.
# Callers can override by passing a custom prompt argument.
BTP_CONTEXT_PROMPT = """Transcription d'un candidat marocain BTP. Mélange français-darija en alphabet latin uniquement. Exemple darija attendu : "Ana khdemt f chantier dyal TGCC f Casablanca, 3andi khibra f installation électrique w câblage, khdemt 3 snin." Métiers : maçon, coffreur, ferrailleur, électricien, plombier, soudeur, peintre, carreleur, chef de chantier, chef d'équipe. Formations : CAP, BTS, OFPPT, CFA, ISTA. Lieux : Casablanca, Rabat, Tanger, Marrakech, Agadir, Fès. Compétences : coffrage, ferraillage, câblage, installation, lecture de plans. Entreprises : TGCC, SOMAGEC, Addoha, Sigman. Années 2000-2024. Nombres toujours en chiffres latins : 1, 2, 3, 5, 7, 10, 15, 20, 25, 30. Exemple : 'khdemt 10 snin f chantier, 3andi khibra f 3 charikate.'"""


@dataclass
class TranscriptionResult:
    """Résultat d'une transcription audio."""
    transcript: str
    detected_language: Optional[str]
    duration_seconds: float
    model: str


class WhisperService:
    """
    Wrapper autour de Groq Whisper Large v3.
    
    Instance unique partagée via la variable `whisper_service` en bas du module.
    """

    def __init__(self):
        if not settings.GROQ_API_KEY:
            raise ValueError(
                "GROQ_API_KEY manquante dans .env. "
                "Récupère-la sur https://console.groq.com/keys"
            )
        self.client = Groq(api_key=settings.GROQ_API_KEY)
        self.model = settings.WHISPER_MODEL

    # Language hint kept as None (auto-detect) by default.
    # Empirical tests on Moroccan darija scripts (Chantier 1, Sprint 8B) showed
    # Whisper auto-detect produces better transcription quality than forcing
    # language="fr" — auto-detect handles French/darija code-switching more
    # gracefully than a hard French hint, which over-translated proper nouns.
    # Callers can override per-call if a specific language is known.
    async def transcribe(
        self,
        audio_bytes: bytes,
        filename: str = "audio.m4a",
        language: Optional[str] = None,
        prompt: Optional[str] = BTP_CONTEXT_PROMPT,
    ) -> TranscriptionResult:
        """
        Transcrit un fichier audio en texte.
        
        Args:
            audio_bytes : Le contenu binaire du fichier audio.
            filename   : Nom du fichier (extension lue par Groq pour le format).
            language   : Code ISO (ex: "fr", "ar") ou None pour auto-détection.
            prompt     : Contexte optionnel (soft bias Whisper) ou None pour désactiver.
        
        Returns:
            TranscriptionResult avec transcript, langue détectée, durée.
        
        Raises:
            Exception : si l'appel Groq échoue (réseau, quota, etc.).
        """
        start_time = time.time()

        # Préparer les kwargs (language/prompt sont optionnels)
        kwargs = {
            "file": (filename, audio_bytes),
            "model": self.model,
            "response_format": "verbose_json",  # retourne aussi la langue détectée
        }
        if language:
            kwargs["language"] = language
        if prompt:
            kwargs["prompt"] = prompt

        # Appel Groq (SDK synchrone, on l'utilise en async via wrapper)
        # Note : Groq SDK est encore synchrone, on l'utilise tel quel
        transcription = self.client.audio.transcriptions.create(**kwargs)

        elapsed = time.time() - start_time

        return TranscriptionResult(
            transcript=transcription.text,
            detected_language=getattr(transcription, "language", None),
            duration_seconds=round(elapsed, 2),
            model=self.model,
        )


# Instance globale unique - importée partout dans l'app
whisper_service = WhisperService()