"""
Runway Gen-3/Gen-4 Video Provider

API Docs: https://docs.dev.runwayml.com/
Pricing:  $0.01/credit — Gen-4 Turbo ~5 credits/5s ($0.05), Gen-3 Alpha ~10 credits/5s ($0.10)
Auth:     Bearer token (API Key from https://dev.runwayml.com/)
Endpoint: https://api.dev.runwayml.com/v1/image_to_video (or text_to_video)

Setup:
  1. Create account at https://dev.runwayml.com/
  2. Generate API key from the developer portal
  3. Set RUNWAY_API_KEY in .env
  4. Purchase credits ($0.01 per credit)
"""
import aiohttp
import asyncio
from flask import current_app
from . import BaseVideoProvider


class RunwayProvider(BaseVideoProvider):
    """Runway ML video generation provider — high cinematic quality."""

    BASE_URL = "https://api.dev.runwayml.com/v1"

    def _get_api_key(self):
        from .key_helper import get_provider_key
        key, _ = get_provider_key("runway", "RUNWAY_API_KEY")
        return key

    async def generate_video(self, prompt: str, duration: int = 5, **kwargs) -> dict:
        api_key = self._get_api_key()
        if not api_key:
            return {"status": "error", "error": "Runway API key not configured. Set RUNWAY_API_KEY in .env"}

        url = f"{self.BASE_URL}/text_to_video"
        headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
            "X-Runway-Version": "2024-11-06",
        }
        # Runway supports 5 or 10 second durations
        secs = 10 if duration > 7 else 5
        # Model: gen4_turbo (cheapest), gen4, gen3a_turbo
        model = kwargs.get("model", "gen4_turbo")

        payload = {
            "model": model,
            "promptText": prompt,
            "duration": secs,
            "ratio": "16:9",
            "watermark": False,
        }

        try:
            timeout = aiohttp.ClientTimeout(total=60)
            async with aiohttp.ClientSession(timeout=timeout) as session:
                async with session.post(url, json=payload, headers=headers) as resp:
                    if resp.content_type and "json" in resp.content_type:
                        result = await resp.json()
                    else:
                        text = await resp.text()
                        return {"status": "error", "error": f"Unexpected response ({resp.status}): {text[:300]}"}

                    if resp.status in (200, 201):
                        task_id = result.get("id", "")
                        if not task_id:
                            return {"status": "error", "error": f"No task ID returned: {result}"}
                        return {"status": "processing", "video_id": task_id, "provider": "runway"}
                    elif resp.status == 401:
                        return {"status": "error", "error": "Invalid Runway API key"}
                    elif resp.status == 402:
                        return {"status": "error", "error": "Insufficient Runway credits. Purchase more at dev.runwayml.com"}
                    elif resp.status == 429:
                        return {"status": "error", "error": "Rate limit exceeded. Try again later."}
                    else:
                        error_msg = result.get("error", result.get("message", str(result)))
                        return {"status": "error", "error": f"Runway API error ({resp.status}): {error_msg}"}
        except asyncio.TimeoutError:
            return {"status": "error", "error": "Request timed out"}
        except aiohttp.ClientError as e:
            return {"status": "error", "error": f"Connection error: {e}"}
        except Exception as e:
            return {"status": "error", "error": f"Unexpected error: {e}"}

    async def check_status(self, task_id: str) -> dict:
        api_key = self._get_api_key()
        if not api_key:
            return {"status": "error", "error": "Runway API key not configured"}

        url = f"{self.BASE_URL}/tasks/{task_id}"
        headers = {
            "Authorization": f"Bearer {api_key}",
            "X-Runway-Version": "2024-11-06",
        }

        try:
            timeout = aiohttp.ClientTimeout(total=60)
            async with aiohttp.ClientSession(timeout=timeout) as session:
                async with session.get(url, headers=headers) as resp:
                    if resp.content_type and "json" in resp.content_type:
                        result = await resp.json()
                    else:
                        return {"status": "error", "error": f"Unexpected response ({resp.status})"}

                    status = result.get("status", "")

                    if status == "SUCCEEDED":
                        output = result.get("output", [])
                        if output:
                            video_url = output[0] if isinstance(output, list) else output
                            return {"status": "completed", "video_url": video_url}
                        return {"status": "error", "error": "No video in output"}
                    elif status == "FAILED":
                        failure = result.get("failure", "Generation failed")
                        return {"status": "error", "error": str(failure)}
                    elif status == "CANCELLED":
                        return {"status": "error", "error": "Task was cancelled"}
                    else:
                        # PENDING, THROTTLED, RUNNING
                        progress = result.get("progress", 0)
                        return {"status": "processing", "progress": int(progress * 100) if progress else 0}
        except asyncio.TimeoutError:
            return {"status": "error", "error": "Status check timed out"}
        except aiohttp.ClientError as e:
            return {"status": "error", "error": f"Connection error: {e}"}
        except Exception as e:
            return {"status": "error", "error": f"Unexpected error: {e}"}
