"""
fal.ai Video Provider

API Docs: https://fal.ai/models?category=video
Pricing:  Pay-per-use, ~$0.02-$0.10/video depending on model
Auth:     API Key (key_id:key_secret format)
Endpoint: https://queue.fal.run/{model_id}

Setup:
  1. Register at https://fal.ai/
  2. Go to https://fal.ai/dashboard/keys → Create Key
  3. Set FAL_KEY in .env (format: key_id:key_secret)

Supported models:
  - fal-ai/minimax-video — MiniMax text-to-video
  - fal-ai/kling-video/v2/master/text-to-video — Kling via fal
  - fal-ai/runway-gen3/turbo/text-to-video — Runway via fal
  - fal-ai/hunyuan-video — Tencent HunyuanVideo
"""
import aiohttp
import asyncio
from flask import current_app
from . import BaseVideoProvider


class FalAIProvider(BaseVideoProvider):
    """fal.ai video generation — multi-model gateway, affordable."""

    QUEUE_URL = "https://queue.fal.run"
    STATUS_URL = "https://queue.fal.run"

    def _get_api_key(self):
        try:
            from app.models.features import VideoProviderConfig
            key, _, _ = VideoProviderConfig.get_provider_config("fal")
            if key:
                return key
        except Exception:
            pass
        return current_app.config.get("FAL_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": "fal.ai API key not configured. Set FAL_KEY in .env or admin panel."}

        # Default model: minimax-video (good quality, cheap)
        model = kwargs.get("model", "fal-ai/minimax-video")

        url = f"{self.QUEUE_URL}/{model}"
        headers = {
            "Authorization": f"Key {api_key}",
            "Content-Type": "application/json",
        }
        payload = {
            "prompt": prompt,
        }
        # Add duration if model supports it
        if "kling" in model or "minimax" in model:
            payload["duration"] = "5" if duration <= 5 else "10"

        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, 202):
                        request_id = result.get("request_id", "")
                        if not request_id:
                            # Synchronous result — video ready immediately
                            video_url = result.get("video", {}).get("url", "")
                            if video_url:
                                return {"status": "completed", "video_url": video_url, "provider": "fal"}
                            return {"status": "error", "error": f"No request_id or video: {result}"}
                        return {"status": "processing", "video_id": f"{model}|{request_id}", "provider": "fal"}
                    elif resp.status == 401:
                        return {"status": "error", "error": "Invalid fal.ai API key"}
                    elif resp.status == 422:
                        error_detail = result.get("detail", str(result))
                        return {"status": "error", "error": f"fal.ai validation error: {error_detail}"}
                    else:
                        error_msg = result.get("detail", result.get("message", str(result)))
                        return {"status": "error", "error": f"fal.ai 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": "fal.ai API key not configured"}

        # task_id format: "model_id|request_id"
        if "|" in task_id:
            model, request_id = task_id.split("|", 1)
        else:
            return {"status": "error", "error": f"Invalid task ID format: {task_id}"}

        url = f"{self.STATUS_URL}/{model}/requests/{request_id}/status"
        headers = {"Authorization": f"Key {api_key}"}

        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 == "COMPLETED":
                        # Fetch the actual result
                        result_url = f"{self.STATUS_URL}/{model}/requests/{request_id}"
                        async with session.get(result_url, headers=headers) as res_resp:
                            if res_resp.status == 200:
                                res_data = await res_resp.json()
                                video_url = res_data.get("video", {}).get("url", "")
                                if video_url:
                                    return {"status": "completed", "video_url": video_url}
                        return {"status": "error", "error": "Could not fetch result"}
                    elif status in ("FAILED", "CANCELLED"):
                        error = result.get("error", "Generation failed")
                        return {"status": "error", "error": str(error)}
                    else:
                        # IN_QUEUE, IN_PROGRESS
                        return {"status": "processing", "progress": 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}"}
