"""HeyGen API client for avatar video generation.

Generated by GRIMLOCK MCP Factory
"""

import logging
import os
from typing import Any

import httpx

logger = logging.getLogger("videogen_mcp")

HEYGEN_BASE_URL = "https://api.heygen.com"


class HeyGenClient:
    """Client for interacting with the HeyGen API."""

    def __init__(self, api_key: str | None = None):
        """Initialize the HeyGen client.

        Args:
            api_key: HeyGen API key. Defaults to HEYGEN_API_KEY env var.
        """
        self.api_key = api_key or os.environ.get("HEYGEN_API_KEY", "")
        self.base_url = HEYGEN_BASE_URL

    def _get_headers(self) -> dict[str, str]:
        """Get request headers with authentication.

        Returns:
            Dictionary of HTTP headers
        """
        return {
            "X-Api-Key": self.api_key,
            "Content-Type": "application/json",
            "Accept": "application/json",
        }

    async def list_avatars(
        self, filter_gender: str | None = None, include_instant: bool = True
    ) -> dict[str, Any]:
        """List available avatars.

        Args:
            filter_gender: Filter by 'male' or 'female'
            include_instant: Include custom instant avatars

        Returns:
            Dictionary with avatars list
        """
        async with httpx.AsyncClient(timeout=30.0) as client:
            response = await client.get(
                f"{self.base_url}/v2/avatars",
                headers=self._get_headers(),
            )
            response.raise_for_status()
            data = response.json()

        avatars = data.get("data", {}).get("avatars", [])

        # Apply filters
        if filter_gender:
            avatars = [a for a in avatars if a.get("gender", "").lower() == filter_gender.lower()]

        if not include_instant:
            avatars = [a for a in avatars if a.get("avatar_type") != "instant"]

        return {
            "avatars": [
                {
                    "avatar_id": a.get("avatar_id"),
                    "avatar_name": a.get("avatar_name"),
                    "gender": a.get("gender"),
                    "preview_image_url": a.get("preview_image_url"),
                    "preview_video_url": a.get("preview_video_url"),
                }
                for a in avatars
            ]
        }

    async def list_voices(
        self, filter_language: str | None = None, filter_gender: str | None = None
    ) -> dict[str, Any]:
        """List available voices.

        Args:
            filter_language: Filter by language code (e.g., 'en')
            filter_gender: Filter by 'male' or 'female'

        Returns:
            Dictionary with voices list
        """
        async with httpx.AsyncClient(timeout=30.0) as client:
            response = await client.get(
                f"{self.base_url}/v2/voices",
                headers=self._get_headers(),
            )
            response.raise_for_status()
            data = response.json()

        voices = data.get("data", {}).get("voices", [])

        # Apply filters
        if filter_language:
            voices = [
                v
                for v in voices
                if v.get("language", "").lower().startswith(filter_language.lower())
            ]

        if filter_gender:
            voices = [v for v in voices if v.get("gender", "").lower() == filter_gender.lower()]

        return {
            "voices": [
                {
                    "voice_id": v.get("voice_id"),
                    "display_name": v.get("display_name") or v.get("name"),
                    "language": v.get("language"),
                    "gender": v.get("gender"),
                    "preview_audio_url": v.get("preview_audio"),
                    "is_cloned": v.get("is_cloned", False),
                }
                for v in voices
            ]
        }

    async def create_avatar_video(
        self,
        script: str,
        avatar_id: str,
        voice_id: str,
        background: dict[str, Any] | None = None,
        aspect_ratio: str = "16:9",
        test_mode: bool = False,
    ) -> dict[str, Any]:
        """Create an avatar video.

        Args:
            script: Text for the avatar to speak
            avatar_id: Avatar ID from list_avatars
            voice_id: Voice ID from list_voices
            background: Background configuration
            aspect_ratio: '16:9', '9:16', or '1:1'
            test_mode: If True, creates watermarked preview

        Returns:
            Job information with job_id
        """
        # Calculate dimensions based on aspect ratio
        dimensions = {
            "16:9": {"width": 1920, "height": 1080},
            "9:16": {"width": 1080, "height": 1920},
            "1:1": {"width": 1080, "height": 1080},
        }
        dim = dimensions.get(aspect_ratio, dimensions["16:9"])

        # Build background config
        if background is None:
            background_config = {"type": "color", "value": "#FFFFFF"}
        else:
            background_config = background

        payload = {
            "video_inputs": [
                {
                    "character": {
                        "type": "avatar",
                        "avatar_id": avatar_id,
                        "avatar_style": "normal",
                    },
                    "voice": {
                        "type": "text",
                        "input_text": script,
                        "voice_id": voice_id,
                    },
                    "background": background_config,
                }
            ],
            "dimension": dim,
            "test": test_mode,
        }

        async with httpx.AsyncClient(timeout=60.0) as client:
            response = await client.post(
                f"{self.base_url}/v2/video/generate",
                headers=self._get_headers(),
                json=payload,
            )
            response.raise_for_status()
            data = response.json()

        video_id = data.get("data", {}).get("video_id")
        return {
            "job_id": video_id,
            "service": "heygen",
            "status": "pending",
            "estimated_duration_seconds": len(script) // 10 + 30,  # Rough estimate
        }

    async def get_video_status(self, video_id: str) -> dict[str, Any]:
        """Get video generation status.

        Args:
            video_id: Video/job ID from create_avatar_video

        Returns:
            Status information including video_url when complete
        """
        async with httpx.AsyncClient(timeout=30.0) as client:
            response = await client.get(
                f"{self.base_url}/v1/video_status.get",
                params={"video_id": video_id},
                headers=self._get_headers(),
            )
            response.raise_for_status()
            data = response.json()

        video_data = data.get("data", {})
        status_map = {
            "pending": "pending",
            "processing": "processing",
            "completed": "completed",
            "complete": "completed",
            "failed": "failed",
        }
        raw_status = video_data.get("status", "pending").lower()
        status = status_map.get(raw_status, raw_status)

        result: dict[str, Any] = {
            "status": status,
            "progress_percent": video_data.get("progress", 0),
        }

        if status == "completed":
            result["video_url"] = video_data.get("video_url")
            result["thumbnail_url"] = video_data.get("thumbnail_url")
            result["duration_seconds"] = video_data.get("duration")

        if status == "failed":
            result["error_message"] = video_data.get("error", {}).get("message", "Unknown error")

        return result

    async def list_templates(self) -> dict[str, Any]:
        """List available templates.

        Returns:
            Dictionary with templates list
        """
        async with httpx.AsyncClient(timeout=30.0) as client:
            response = await client.get(
                f"{self.base_url}/v2/templates",
                headers=self._get_headers(),
            )
            response.raise_for_status()
            data = response.json()

        templates = data.get("data", {}).get("templates", [])

        return {
            "templates": [
                {
                    "template_id": t.get("template_id"),
                    "name": t.get("name"),
                    "thumbnail_url": t.get("thumbnail_url"),
                    "variable_count": len(t.get("variables", {})),
                    "description": t.get("description", ""),
                }
                for t in templates
            ]
        }

    async def get_template_details(self, template_id: str) -> dict[str, Any]:
        """Get template details including variables.

        Args:
            template_id: Template ID from list_templates

        Returns:
            Template details with variable definitions
        """
        async with httpx.AsyncClient(timeout=30.0) as client:
            response = await client.get(
                f"{self.base_url}/v2/template/{template_id}",
                headers=self._get_headers(),
            )
            response.raise_for_status()
            data = response.json()

        template_data = data.get("data", {})
        variables = template_data.get("variables", {})

        return {
            "template_id": template_id,
            "name": template_data.get("name"),
            "variables": [
                {
                    "name": name,
                    "type": var.get("type"),
                    "current_value": var.get("properties", {}).get("content")
                    or var.get("properties", {}).get("url"),
                    "properties": var.get("properties", {}),
                }
                for name, var in variables.items()
            ],
        }

    async def generate_from_template(
        self,
        template_id: str,
        variables: dict[str, Any],
        title: str | None = None,
        test_mode: bool = False,
    ) -> dict[str, Any]:
        """Generate video from template.

        Args:
            template_id: Template ID from list_templates
            variables: Variable values mapping
            title: Optional video title
            test_mode: If True, creates watermarked preview

        Returns:
            Job information with job_id
        """
        payload: dict[str, Any] = {
            "test": test_mode,
            "caption": False,
            "variables": variables,
        }

        if title:
            payload["title"] = title

        async with httpx.AsyncClient(timeout=60.0) as client:
            response = await client.post(
                f"{self.base_url}/v2/template/{template_id}/generate",
                headers=self._get_headers(),
                json=payload,
            )
            response.raise_for_status()
            data = response.json()

        video_id = data.get("data", {}).get("video_id")
        return {
            "job_id": video_id,
            "service": "heygen",
            "status": "pending",
        }
