"""Google Veo API client for creative video generation.

Generated by GRIMLOCK MCP Factory
"""

import base64
import logging
import os
from typing import Any

import httpx

logger = logging.getLogger("videogen_mcp")

VEO_BASE_URL = "https://generativelanguage.googleapis.com/v1beta"


class VeoClient:
    """Client for interacting with the Google Veo API."""

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

        Args:
            api_key: Gemini API key. Defaults to GEMINI_API_KEY env var.
        """
        self.api_key = api_key or os.environ.get("GEMINI_API_KEY", "")
        self.base_url = VEO_BASE_URL

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

        Returns:
            Dictionary of HTTP headers
        """
        return {
            "x-goog-api-key": self.api_key,
            "Content-Type": "application/json",
        }

    async def generate_video(
        self,
        prompt: str,
        negative_prompt: str | None = None,
        aspect_ratio: str = "16:9",
        duration: int = 8,
        model: str = "veo-3.1-generate-preview",
        seed: int | None = None,
        sample_count: int = 1,
    ) -> dict[str, Any]:
        """Generate a video from a text prompt.

        Args:
            prompt: Description of the video to generate
            negative_prompt: Elements to avoid
            aspect_ratio: '16:9', '9:16', or '1:1'
            duration: Video duration in seconds (4, 6, or 8)
            model: Veo model version
            seed: Seed for reproducibility
            sample_count: Number of variants (1-4)

        Returns:
            Job information with operation name as job_id
        """
        parameters: dict[str, Any] = {
            "aspectRatio": aspect_ratio,
            "durationSeconds": duration,
            "sampleCount": sample_count,
        }

        if negative_prompt:
            parameters["negativePrompt"] = negative_prompt

        if seed is not None:
            parameters["seed"] = seed

        payload = {
            "instances": [{"prompt": prompt}],
            "parameters": parameters,
        }

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

        # The response contains an operation name for polling
        operation_name = data.get("name", "")

        return {
            "job_id": operation_name,
            "service": "veo",
            "status": "pending",
            "model_used": model,
        }

    async def generate_video_from_image(
        self,
        image_url: str,
        prompt: str,
        negative_prompt: str | None = None,
        duration: int = 8,
        model: str = "veo-3.1-generate-preview",
    ) -> dict[str, Any]:
        """Generate a video from an image.

        Args:
            image_url: URL of the source image
            prompt: Description of animation/motion
            negative_prompt: Elements to avoid
            duration: Video duration in seconds (4, 6, or 8)
            model: Veo model version

        Returns:
            Job information with operation name as job_id
        """
        # Fetch the image and convert to base64
        async with httpx.AsyncClient(timeout=30.0) as client:
            image_response = await client.get(image_url)
            image_response.raise_for_status()
            image_bytes = image_response.content

        # Determine mime type from content-type header
        content_type = image_response.headers.get("content-type", "image/jpeg")
        if "png" in content_type:
            mime_type = "image/png"
        elif "gif" in content_type:
            mime_type = "image/gif"
        elif "webp" in content_type:
            mime_type = "image/webp"
        else:
            mime_type = "image/jpeg"

        base64_image = base64.b64encode(image_bytes).decode("utf-8")

        parameters: dict[str, Any] = {
            "durationSeconds": duration,
        }

        if negative_prompt:
            parameters["negativePrompt"] = negative_prompt

        payload = {
            "instances": [
                {
                    "prompt": prompt,
                    "image": {
                        "bytesBase64Encoded": base64_image,
                        "mimeType": mime_type,
                    },
                }
            ],
            "parameters": parameters,
        }

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

        operation_name = data.get("name", "")

        return {
            "job_id": operation_name,
            "service": "veo",
            "status": "pending",
        }

    async def get_operation_status(self, operation_name: str) -> dict[str, Any]:
        """Get the status of a video generation operation.

        Args:
            operation_name: Operation name from generate_video

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

        done = data.get("done", False)

        if not done:
            metadata = data.get("metadata", {})
            return {
                "status": "processing",
                "progress_percent": metadata.get("progressPercent", 0),
            }

        # Check for errors
        error = data.get("error")
        if error:
            return {
                "status": "failed",
                "error_message": error.get("message", "Unknown error"),
                "error_code": error.get("code"),
            }

        # Success - extract video results
        response_data = data.get("response", {})
        generated_samples = response_data.get("generatedSamples", [])

        videos = []
        for sample in generated_samples:
            video = sample.get("video", {})
            videos.append(
                {
                    "video_url": video.get("uri"),
                    "encoding": video.get("encoding"),
                }
            )

        return {
            "status": "completed",
            "progress_percent": 100,
            "videos": videos,
            "video_url": videos[0]["video_url"] if videos else None,
        }
