import aiohttp
import asyncio
from flask import current_app
from . import BaseVideoProvider


class SoraProvider(BaseVideoProvider):
    """OpenAI Sora Video API provider.

    API Reference: https://developers.openai.com/api/reference/resources/videos
    - Create:   POST   /v1/videos
    - Retrieve: GET    /v1/videos/{video_id}
    - Content:  GET    /v1/videos/{video_id}/content
    """

    BASE_URL = "https://api.openai.com/v1"

    def _get_api_key(self):
        from .key_helper import get_provider_key
        key, _ = get_provider_key("sora", "OPENAI_API_KEY")
        return key

    async def generate_video(self, prompt: str, duration: int = 10, **kwargs) -> dict:
        api_key = self._get_api_key()
        if not api_key:
            return {"error": "OpenAI API key not configured", "status": "error"}

        url = f"{self.BASE_URL}/videos"
        headers = {
            "Authorization": f"Bearer {api_key}",
            "Content-Type": "application/json",
        }
        # Allowed durations: 4, 8, 12 seconds
        allowed = [4, 8, 12]
        secs = min(allowed, key=lambda x: abs(x - duration))
        payload = {
            "model": "sora-2",
            "prompt": prompt,
            "size": "1280x720",
            "seconds": str(secs),
        }

        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[:200]}"}

                    if resp.status in (200, 201, 202):
                        video_id = result.get("id", "")
                        if not video_id:
                            return {"status": "error", "error": "No video ID returned from API"}
                        return {"status": "processing", "video_id": video_id, "provider": "sora"}
                    elif resp.status == 404:
                        return {"status": "error", "error": "Sora video API endpoint not available. This API may not be enabled for your account."}
                    elif resp.status == 401:
                        return {"status": "error", "error": "Invalid OpenAI API key"}
                    elif resp.status == 429:
                        return {"status": "error", "error": "Rate limit exceeded. Please try again later."}
                    elif resp.status == 402:
                        error_detail = result.get("error", {}).get("message", "Billing limit reached") if isinstance(result, dict) else "Billing limit reached"
                        return {"status": "error", "error": f"Billing limit reached: {error_detail}. Please check your OpenAI billing settings."}
                    else:
                        error_msg = result.get("error", {}).get("message", str(result)) if isinstance(result, dict) else str(result)
                        # Catch billing-related errors
                        if "billing" in error_msg.lower() or "limit" in error_msg.lower():
                            return {"status": "error", "error": f"OpenAI billing issue: {error_msg}. Please check your OpenAI account billing."}
                        return {"status": "error", "error": error_msg}
        except asyncio.TimeoutError:
            return {"status": "error", "error": "Request timed out. Please try again."}
        except aiohttp.ClientError as e:
            return {"status": "error", "error": f"Connection error: {str(e)}"}
        except Exception as e:
            return {"status": "error", "error": f"Unexpected error: {str(e)}"}

    async def check_status(self, video_id: str) -> dict:
        api_key = self._get_api_key()
        url = f"{self.BASE_URL}/videos/{video_id}"
        headers = {"Authorization": f"Bearer {api_key}"}

        try:
            timeout = aiohttp.ClientTimeout(total=120)
            async with aiohttp.ClientSession(timeout=timeout) as session:
                async with session.get(url, headers=headers) as resp:
                    if resp.status == 404:
                        return {"status": "error", "error": "Video not found or API not available"}

                    if resp.content_type and "json" in resp.content_type:
                        data = await resp.json()
                    else:
                        return {"status": "error", "error": f"Unexpected response ({resp.status})"}

                    if resp.status != 200:
                        error_msg = data.get("error", {}).get("message", str(data)) if isinstance(data, dict) else str(data)
                        return {"status": "error", "error": error_msg}

                    status = data.get("status", "")
                    if status == "completed":
                        # Download actual video content from /v1/videos/{id}/content
                        content_url = f"{self.BASE_URL}/videos/{video_id}/content"
                        try:
                            async with session.get(content_url, headers=headers) as content_resp:
                                if content_resp.status == 200:
                                    video_bytes = await content_resp.read()
                                    return {"status": "completed", "video_bytes": video_bytes, "video_id": video_id}
                                else:
                                    return {"status": "completed", "video_url": content_url, "needs_auth": True, "video_id": video_id}
                        except Exception:
                            return {"status": "completed", "video_url": content_url, "needs_auth": True, "video_id": video_id}
                    elif status in ("failed", "error"):
                        err = data.get("error", {})
                        error_msg = err.get("message", "Generation failed") if isinstance(err, dict) else str(err or "Generation failed")
                        return {"status": "error", "error": error_msg}
                    else:
                        # queued or in-progress
                        progress = data.get("progress", 0)
                        return {"status": "processing", "progress": progress}
        except asyncio.TimeoutError:
            return {"status": "error", "error": "Status check timed out"}
        except aiohttp.ClientError as e:
            return {"status": "error", "error": f"Connection error: {str(e)}"}
        except Exception as e:
            return {"status": "error", "error": f"Unexpected error: {str(e)}"}
