"""
ElevenLabs Voice Catalog Service.

Fetches and caches available voices from the ElevenLabs API.
"""

import time
from dataclasses import dataclass, field

import aiohttp

from ..core.config import settings
from ..core.logging import get_logger

logger = get_logger(__name__)

CACHE_TTL_SECONDS = 3600  # 1 hour


@dataclass
class ElevenLabsVoice:
    """Structured voice data from ElevenLabs."""
    voice_id: str
    name: str
    category: str = ""
    description: str = ""
    preview_url: str = ""
    labels: dict[str, str] = field(default_factory=dict)


class ElevenLabsVoiceService:
    def __init__(self):
        self._cache: list[ElevenLabsVoice] = []
        self._cache_time: float = 0.0

    def _is_cache_valid(self) -> bool:
        return bool(self._cache) and (time.time() - self._cache_time) < CACHE_TTL_SECONDS

    async def get_voices(self) -> list[ElevenLabsVoice]:
        """
        Fetch voices from ElevenLabs API with in-memory cache (1-hour TTL).
        Falls back to stale cache on API failure.
        """
        if self._is_cache_valid():
            return self._cache

        if not settings.elevenlabs_api_key:
            logger.warning("ElevenLabs API key not configured")
            return self._cache  # Return stale cache or empty

        try:
            voices = await self._fetch_voices()
            self._cache = voices
            self._cache_time = time.time()
            logger.info(f"Fetched {len(voices)} voices from ElevenLabs API")
            return voices
        except Exception as e:
            if self._cache:
                logger.warning(f"Failed to fetch ElevenLabs voices, using stale cache: {e}")
                return self._cache
            raise

    async def _fetch_voices(self) -> list[ElevenLabsVoice]:
        """Fetch voices from the ElevenLabs API."""
        url = "https://api.elevenlabs.io/v1/voices"
        headers = {
            "xi-api-key": settings.elevenlabs_api_key,
            "Accept": "application/json",
        }

        async with aiohttp.ClientSession() as session:
            async with session.get(url, headers=headers) as response:
                if response.status != 200:
                    error_text = await response.text()
                    raise ValueError(f"ElevenLabs API error: {response.status} - {error_text}")

                data = await response.json()

        voices: list[ElevenLabsVoice] = []
        for v in data.get("voices", []):
            voices.append(ElevenLabsVoice(
                voice_id=v.get("voice_id", ""),
                name=v.get("name", ""),
                category=v.get("category", ""),
                description=v.get("description", ""),
                preview_url=v.get("preview_url", ""),
                labels=v.get("labels", {}),
            ))

        return voices

    async def get_voice_by_id(self, voice_id: str) -> ElevenLabsVoice | None:
        """Look up a specific voice by ID."""
        voices = await self.get_voices()
        for v in voices:
            if v.voice_id == voice_id:
                return v
        return None


# Singleton instance
elevenlabs_voice_service = ElevenLabsVoiceService()
