#!/usr/bin/env python3
"""
GPTunnel API client for Veo 3.1 Fast video generation.

Alternative to direct Google API, bypasses geo-restrictions.
Docs: https://docs.gptunnel.ru/media-api/veo-3-fast
"""

import base64
import time
import requests
from pathlib import Path
from typing import Optional, Tuple

BASE_URL = "https://gptunnel.ru/v1/media"


def call_veo3_gptunnel(
    prompt: str,
    api_key: str,
    first_frame_path: Optional[str] = None,
    last_frame_path: Optional[str] = None,
    aspect_ratio: str = "16:9"
) -> str:
    """
    Start Veo3 video generation via GPTunnel.

    Args:
        prompt: Video generation prompt
        api_key: GPTunnel API key
        first_frame_path: Optional path to first frame image
        last_frame_path: Optional path to last frame image (for interpolation)
        aspect_ratio: Video aspect ratio ("16:9", "9:16", "1:1")

    Returns:
        Task ID for polling
    """
    payload = {
        "model": "glabs-veo-3-1-fast",
        "prompt": prompt,
        "ar": aspect_ratio
    }

    def path_to_data_url(img_path: str) -> str:
        """Convert image file to base64 data URL."""
        img_path = Path(img_path)
        with open(img_path, 'rb') as f:
            image_data = f.read()

        # Determine mime type
        suffix = img_path.suffix.lower()
        if suffix in ['.jpg', '.jpeg']:
            mime_type = 'image/jpeg'
        elif suffix == '.png':
            mime_type = 'image/png'
        elif suffix == '.webp':
            mime_type = 'image/webp'
        else:
            mime_type = 'image/png'

        image_base64 = base64.b64encode(image_data).decode('utf-8')
        return f"data:{mime_type};base64,{image_base64}"

    # Build images array (first frame, optionally last frame)
    # NOTE: GPTunnel may not support base64 data URLs - trying anyway
    # If this fails, will fall back to text-to-video mode
    images = []
    try:
        if first_frame_path and Path(first_frame_path).exists():
            images.append(path_to_data_url(first_frame_path))
        if last_frame_path and Path(last_frame_path).exists():
            images.append(path_to_data_url(last_frame_path))
    except Exception as e:
        print(f"  Warning: Could not encode images: {e}")
        images = []

    if images:
        payload["images"] = images
        print(f"  Sending {len(images)} image(s) to GPTunnel")

    response = requests.post(
        f"{BASE_URL}/create",
        headers={
            "Authorization": api_key,
            "Content-Type": "application/json"
        },
        json=payload,
        timeout=60
    )

    if response.status_code != 200:
        raise RuntimeError(f"GPTunnel Veo3 API error: {response.status_code} - {response.text[:500]}")

    data = response.json()

    if data.get("code") != 0:
        raise RuntimeError(f"GPTunnel Veo3 error: {data}")

    task_id = data.get("id")
    if not task_id:
        raise RuntimeError(f"No task_id in response: {data}")

    return task_id


def poll_veo3_gptunnel(
    task_id: str,
    api_key: str,
    poll_interval: int = 10,
    timeout: int = 600
) -> dict:
    """
    Poll GPTunnel for Veo3 task completion.

    Args:
        task_id: Task ID from call_veo3_gptunnel()
        api_key: GPTunnel API key
        poll_interval: Seconds between polls
        timeout: Maximum wait time in seconds

    Returns:
        Dict with video URL
    """
    start_time = time.time()
    consecutive_errors = 0
    max_errors = 5

    while time.time() - start_time < timeout:
        try:
            response = requests.post(
                f"{BASE_URL}/result",
                headers={
                    "Authorization": api_key,
                    "Content-Type": "application/json"
                },
                json={"task_id": task_id},
                timeout=30
            )

            if response.status_code != 200:
                raise RuntimeError(f"GPTunnel poll error: {response.status_code} - {response.text[:500]}")

            data = response.json()
            status = data.get("status", "")
            consecutive_errors = 0  # Reset on success

            if status == "done":
                url = data.get("url")
                if not url:
                    raise RuntimeError(f"No URL in completed response: {data}")
                return {"uri": url, "state": "COMPLETE"}

            if status == "failed":
                raise RuntimeError(f"GPTunnel generation failed: {data}")

            # code != 0 with status != failed might be transient
            if data.get("code") != 0 and status not in ["idle", "running"]:
                raise RuntimeError(f"GPTunnel generation failed: {data}")

            elapsed = int(time.time() - start_time)
            print(f"  GPTunnel Veo3 generating... ({elapsed}s elapsed, status: {status})")

        except requests.exceptions.RequestException as e:
            consecutive_errors += 1
            elapsed = int(time.time() - start_time)
            print(f"  Network error ({consecutive_errors}/{max_errors}): {e}")
            if consecutive_errors >= max_errors:
                raise RuntimeError(f"Too many consecutive network errors: {e}")

        time.sleep(poll_interval)

    raise TimeoutError(f"GPTunnel Veo3 generation timed out after {timeout}s")


def download_video_gptunnel(
    video_url: str,
    output_path: str
) -> str:
    """
    Download generated video from GPTunnel.

    Args:
        video_url: Video URL from poll_veo3_gptunnel()
        output_path: Local path to save video

    Returns:
        Path to downloaded video
    """
    response = requests.get(
        video_url,
        stream=True,
        timeout=300
    )

    if response.status_code != 200:
        raise RuntimeError(f"Download error: {response.status_code}")

    with open(output_path, 'wb') as f:
        for chunk in response.iter_content(chunk_size=8192):
            f.write(chunk)

    return output_path


def test_gptunnel(api_key: str) -> dict:
    """
    Test GPTunnel API connection.

    Returns:
        Dict with test results
    """
    try:
        # Simple test - just check if we can reach the API
        response = requests.post(
            f"{BASE_URL}/create",
            headers={
                "Authorization": api_key,
                "Content-Type": "application/json"
            },
            json={
                "model": "glabs-veo-3-1-fast",
                "prompt": "A simple red dot on white background, 1 second",
                "ar": "16:9"
            },
            timeout=30
        )

        if response.status_code == 200:
            data = response.json()
            if data.get("code") == 0:
                return {"status": "ok", "task_id": data.get("id")}
            else:
                return {"status": "error", "response": data}
        else:
            return {"status": "error", "code": response.status_code, "text": response.text[:200]}
    except Exception as e:
        return {"status": "error", "message": str(e)}


if __name__ == "__main__":
    import sys
    import os

    # Load .env
    from dotenv import load_dotenv
    load_dotenv(Path(__file__).parent.parent / ".env")

    api_key = os.environ.get("GPTTUNNEL_KEY")
    if not api_key:
        print("Error: GPTTUNNEL_KEY not set in .env")
        sys.exit(1)

    if len(sys.argv) > 1 and sys.argv[1] == "test":
        print("Testing GPTunnel API...")
        result = test_gptunnel(api_key)
        print(f"Result: {result}")
    else:
        print("Usage: python gptunnel_proxy.py test")
