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

Docs: https://docs.pollo.ai/m/google/veo3-fast
"""

import base64
import io
import json
import time
import ssl
import requests
from pathlib import Path
from typing import Optional
from requests.adapters import HTTPAdapter
from urllib3.util.ssl_ import create_urllib3_context
import urllib3
from PIL import Image

# Suppress SSL warnings for local proxy
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

BASE_URL = "https://pollo.ai/api/platform"

# Public URL base for serving images (nginx serves /mnt/video at this URL)
PUBLIC_URL_BASE = "https://your-server.example.com"
NFS_BASE = "/mnt/video"


class TLSAdapter(HTTPAdapter):
    """HTTP Adapter with browser-like TLS settings for local proxy."""
    def init_poolmanager(self, *args, **kwargs):
        ctx = create_urllib3_context()
        ctx.minimum_version = ssl.TLSVersion.TLSv1_2
        ctx.set_ciphers('DEFAULT:@SECLEVEL=1')
        ctx.check_hostname = False
        ctx.verify_mode = ssl.CERT_NONE
        kwargs['ssl_context'] = ctx
        return super().init_poolmanager(*args, **kwargs)


def get_session() -> requests.Session:
    """Get a requests session with browser-like TLS settings."""
    session = requests.Session()
    adapter = TLSAdapter()
    session.mount("https://", adapter)
    # Disable SSL verification for local proxy compatibility
    session.verify = False
    return session


def image_to_base64(image_path: str) -> str:
    """Convert image file to base64 string."""
    path = Path(image_path)
    with open(path, 'rb') as f:
        image_data = f.read()
    return base64.b64encode(image_data).decode('utf-8')


def path_to_public_url(file_path: str) -> str:
    """
    Convert local file path to public URL.

    /mnt/video/wb_123/session/file.jpg -> https://your-server.example.com/wb_123/session/file.jpg
    """
    path = Path(file_path).resolve()
    nfs_path = Path(NFS_BASE).resolve()

    try:
        relative = path.relative_to(nfs_path)
        return f"{PUBLIC_URL_BASE}/{relative}"
    except ValueError:
        raise ValueError(f"File path {file_path} is not under {NFS_BASE}")


def compress_image_for_pollo(
    image_path: str,
    max_size_kb: int = 100,
    save_path: Optional[str] = None
) -> str:
    """
    Compress image to fit Pollo.ai's API limits.

    Pollo has a strict limit on image size in their database (~100KB per image).

    Args:
        image_path: Path to image file
        max_size_kb: Maximum size in KB (default: 100KB due to Pollo's DB limits)
        save_path: Optional path to save compressed image (for debugging)

    Returns:
        Base64 encoded compressed image
    """
    path = Path(image_path)
    img = Image.open(path)

    # Convert to RGB if necessary (for JPEG)
    if img.mode in ('RGBA', 'P'):
        img = img.convert('RGB')

    # Start with quality 85, reduce if needed
    quality = 85
    max_bytes = max_size_kb * 1024

    while quality >= 30:
        buffer = io.BytesIO()
        img.save(buffer, format='JPEG', quality=quality, optimize=True)
        size = buffer.tell()

        if size <= max_bytes:
            buffer.seek(0)
            data = buffer.read()

            # Save compressed version if path provided
            if save_path:
                with open(save_path, 'wb') as f:
                    f.write(data)
                print(f"    Saved compressed: {save_path} ({size // 1024}KB, q={quality})")

            encoded = base64.b64encode(data).decode('utf-8')
            print(f"    Compressed to {size // 1024}KB (quality={quality})")
            return encoded

        # Reduce quality
        quality -= 10

        # If still too large at quality 50, also resize
        if quality <= 50 and size > max_bytes:
            new_width = int(img.width * 0.8)
            new_height = int(img.height * 0.8)
            img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)
            print(f"    Resized to {new_width}x{new_height}")

    # Final attempt with lowest quality
    buffer = io.BytesIO()
    img.save(buffer, format='JPEG', quality=30, optimize=True)
    buffer.seek(0)
    data = buffer.read()

    if save_path:
        with open(save_path, 'wb') as f:
            f.write(data)
        print(f"    Saved compressed: {save_path} ({len(data) // 1024}KB, q=30)")

    encoded = base64.b64encode(data).decode('utf-8')
    print(f"    Final compression: {len(data) // 1024}KB")
    return encoded


def call_kling_o1_pollo(
    prompt: str,
    api_key: str,
    first_frame_path: Optional[str] = None,
    last_frame_path: Optional[str] = None,
    first_frame_url: Optional[str] = None,
    last_frame_url: Optional[str] = None,
    aspect_ratio: str = "9:16",
    length: int = 5,
    reference_image_paths: Optional[list] = None,
    reference_image_urls: Optional[list] = None
) -> dict:
    """
    Generate video using Pollo.ai Kling Video O1 API.

    Kling O1 features:
    - Superior frame consistency
    - Aspect ratio control (9:16, 16:9, 1:1)
    - Better at handling real people/celebrities than Veo3
    - Multi-step prompting support
    - Reference images for character consistency (via `images` array)

    Args:
        prompt: Video generation prompt
        api_key: Pollo API key
        first_frame_path: Path to first frame image (converted to public URL)
        last_frame_path: Path to last frame image for interpolation (converted to public URL)
        first_frame_url: Direct URL for first frame (alternative to path)
        last_frame_url: Direct URL for last frame (alternative to path)
        aspect_ratio: Video aspect ratio ("9:16", "16:9", "1:1")
        length: Video length in seconds (3-10)
        reference_image_paths: List of file paths to reference images (converted to public URLs)
        reference_image_urls: List of direct URLs for reference images

    Returns:
        Dict with task_id and status for polling
    """
    input_data = {
        "prompt": prompt,
        "aspectRatio": aspect_ratio,
        "length": length,
        "mode": "pro"  # O1 only supports pro mode
    }

    # Collect all image URLs: start frame first, then references
    all_image_urls = []

    # Start frame goes first in the images array
    if first_frame_url:
        all_image_urls.append(first_frame_url)
    elif first_frame_path and Path(first_frame_path).exists():
        all_image_urls.append(path_to_public_url(first_frame_path))

    # Reference images follow
    if reference_image_urls:
        all_image_urls.extend(reference_image_urls)
    elif reference_image_paths:
        for ref_path in reference_image_paths:
            if Path(ref_path).exists():
                all_image_urls.append(path_to_public_url(ref_path))

    # O1 Reference To Video: all images go into `images` array (max 7)
    if all_image_urls:
        all_image_urls = all_image_urls[:7]
        input_data["images"] = all_image_urls
        print(f"  Images ({len(all_image_urls)} total):")
        for i, url in enumerate(all_image_urls):
            label = "start frame" if i == 0 else f"reference {i}"
            print(f"    [{i}] {label}: {url}")

    # Add last frame for interpolation
    if last_frame_url:
        input_data["imageTail"] = last_frame_url
        print(f"  Last frame URL: {last_frame_url}")
    elif last_frame_path and Path(last_frame_path).exists():
        url = path_to_public_url(last_frame_path)
        input_data["imageTail"] = url
        print(f"  Last frame URL: {url}")

    payload = {"input": input_data}

    print(f"  Model: Kling Video O1")
    print(f"  Aspect ratio: {aspect_ratio}")
    print(f"  Length: {length}s")
    print(f"  Mode: pro")
    print(f"  Sending request to Pollo.ai...")

    session = get_session()
    response = session.post(
        f"{BASE_URL}/generation/kling-ai/kling-video-o1",
        headers={
            "x-api-key": api_key,
            "Content-Type": "application/json"
        },
        json=payload,
        timeout=60
    )

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

    result = response.json()

    if result.get("code") != "SUCCESS":
        raise RuntimeError(f"Pollo Kling O1 API error: {result}")

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

    print(f"  Kling O1 task created: {task_id}")
    return {"task_id": task_id, "status": result.get("data", {}).get("status"), "raw": result}


def call_kling_v26_pollo(
    prompt: str,
    api_key: str,
    first_frame_path: Optional[str] = None,
    last_frame_path: Optional[str] = None,
    first_frame_url: Optional[str] = None,
    last_frame_url: Optional[str] = None,
    length: int = 5,
    generate_audio: bool = True
) -> dict:
    """
    Generate video using Pollo.ai Kling v2.6 API with audio generation.

    Kling 2.6 features:
    - Image-to-video generation with start/end frame control
    - Natural audio generation from scene
    - 5 or 10 second clips

    Args:
        prompt: Video generation prompt (include audio hints for sound effects)
        api_key: Pollo API key
        first_frame_path: Path to first frame image (converted to public URL)
        last_frame_path: Path to last frame image for end frame control (converted to public URL)
        first_frame_url: Direct URL for first frame (alternative to path)
        last_frame_url: Direct URL for last frame (alternative to path)
        length: Video length in seconds (5 or 10)
        generate_audio: Generate natural-sounding audio for the video

    Returns:
        Dict with task_id and status for polling
    """
    input_data = {
        "prompt": prompt,
        "length": length,
        "generateAudio": generate_audio
    }

    # Add first frame (Pollo only accepts URLs, not base64)
    if first_frame_url:
        print(f"  First frame URL: {first_frame_url}")
        input_data["image"] = first_frame_url
    elif first_frame_path and Path(first_frame_path).exists():
        url = path_to_public_url(first_frame_path)
        print(f"  First frame URL: {url}")
        input_data["image"] = url
    else:
        raise ValueError("first_frame_path or first_frame_url is required for Kling 2.6")

    # Add last frame for end frame control (image_tail in Kling API)
    if last_frame_url:
        print(f"  Last frame URL: {last_frame_url}")
        input_data["image_tail"] = last_frame_url
    elif last_frame_path and Path(last_frame_path).exists():
        url = path_to_public_url(last_frame_path)
        print(f"  Last frame URL: {url}")
        input_data["image_tail"] = url

    payload = {"input": input_data}

    print(f"  Model: Kling v2.6")
    print(f"  Length: {length}s")
    print(f"  Generate audio: {generate_audio}")
    print(f"  Sending request to Pollo.ai...")

    session = get_session()
    response = session.post(
        f"{BASE_URL}/generation/kling-ai/kling-v2-6",
        headers={
            "x-api-key": api_key,
            "Content-Type": "application/json"
        },
        json=payload,
        timeout=60
    )

    if response.status_code != 200:
        raise RuntimeError(f"Pollo Kling v2.6 API error: {response.status_code} - {response.text[:500]}")

    result = response.json()

    if result.get("code") != "SUCCESS":
        raise RuntimeError(f"Pollo Kling v2.6 API error: {result}")

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

    print(f"  Kling v2.6 task created: {task_id}")
    return {"task_id": task_id, "status": result.get("data", {}).get("status"), "raw": result}


def call_kling_pollo(
    prompt: str,
    api_key: str,
    first_frame_path: Optional[str] = None,
    last_frame_path: Optional[str] = None,
    first_frame_url: Optional[str] = None,
    last_frame_url: Optional[str] = None,
    negative_prompt: str = "",
    strength: int = 50,
    length: int = 5,
    mode: str = "std"
) -> dict:
    """
    Generate video using Pollo.ai Kling v2.5 Turbo API.

    Note: For better results with aspect ratio control, use call_kling_o1_pollo() instead.

    Args:
        prompt: Video generation prompt
        api_key: Pollo API key
        first_frame_path: Path to first frame image (converted to public URL)
        last_frame_path: Path to last frame image for interpolation (converted to public URL)
        first_frame_url: Direct URL for first frame (alternative to path)
        last_frame_url: Direct URL for last frame (alternative to path)
        negative_prompt: What to avoid in generation
        strength: Generation strength 0-100 (default: 50)
        length: Video length in seconds (5 or 10)
        mode: Generation mode ("std" for standard, "pro" for professional)

    Returns:
        Dict with task_id and status for polling
    """
    input_data = {
        "prompt": prompt,
        "strength": strength,
        "length": length,
        "mode": mode
    }

    if negative_prompt:
        input_data["negativePrompt"] = negative_prompt

    # Add first frame (Pollo only accepts URLs, not base64)
    if first_frame_url:
        print(f"  First frame URL: {first_frame_url}")
        input_data["image"] = first_frame_url
    elif first_frame_path and Path(first_frame_path).exists():
        url = path_to_public_url(first_frame_path)
        print(f"  First frame URL: {url}")
        input_data["image"] = url

    # Add last frame for interpolation (Pollo only accepts URLs)
    if last_frame_url:
        print(f"  Last frame URL: {last_frame_url}")
        input_data["imageTail"] = last_frame_url
    elif last_frame_path and Path(last_frame_path).exists():
        url = path_to_public_url(last_frame_path)
        print(f"  Last frame URL: {url}")
        input_data["imageTail"] = url

    payload = {"input": input_data}

    print(f"  Model: Kling v2.5 Turbo")
    print(f"  Length: {length}s")
    print(f"  Mode: {mode}")
    print(f"  Strength: {strength}")
    print(f"  Sending request to Pollo.ai...")

    session = get_session()
    response = session.post(
        f"{BASE_URL}/generation/kling-ai/kling-v2-5-turbo",
        headers={
            "x-api-key": api_key,
            "Content-Type": "application/json"
        },
        json=payload,
        timeout=60
    )

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

    result = response.json()

    if result.get("code") != "SUCCESS":
        raise RuntimeError(f"Pollo Kling API error: {result}")

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

    print(f"  Kling task created: {task_id}")
    return {"task_id": task_id, "status": result.get("data", {}).get("status"), "raw": result}


def poll_kling_pollo(
    task_id: str,
    api_key: str,
    poll_interval: int = 10,
    timeout: int = 600
) -> dict:
    """
    Poll Pollo.ai for Kling task completion.

    Args:
        task_id: Task ID from call_kling_pollo()
        api_key: Pollo 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

    session = get_session()
    while time.time() - start_time < timeout:
        try:
            response = session.get(
                f"{BASE_URL}/generation/{task_id}/status",
                headers={
                    "x-api-key": api_key,
                    "Content-Type": "application/json"
                },
                timeout=30
            )

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

            result = response.json()
            consecutive_errors = 0

            if result.get("code") != "SUCCESS":
                raise RuntimeError(f"Pollo API error: {result}")

            data = result.get("data", {})
            generations = data.get("generations", [])

            if generations:
                gen = generations[0]
                status = gen.get("status", "")

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

                if status == "failed":
                    fail_msg = gen.get("failMsg", "Unknown error")
                    raise RuntimeError(f"Kling generation failed: {fail_msg}")

                elapsed = int(time.time() - start_time)
                print(f"  Kling generating... ({elapsed}s elapsed, status: {status})")
            else:
                elapsed = int(time.time() - start_time)
                print(f"  Kling waiting... ({elapsed}s elapsed)")

        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"Kling generation timed out after {timeout}s")


def call_veo3_pollo(
    prompt: str,
    api_key: str,
    first_frame_path: Optional[str] = None,
    last_frame_path: Optional[str] = None,
    first_frame_url: Optional[str] = None,
    last_frame_url: Optional[str] = None,
    aspect_ratio: str = "16:9",
    length: int = 8,
    resolution: str = "720p",
    generate_audio: bool = False
) -> dict:
    """
    Generate video using Pollo.ai Veo 3.1 Fast API.

    Note: Pollo only accepts image URLs (not base64). Images must be publicly
    accessible. Local paths are converted to public URLs via path_to_public_url().

    Args:
        prompt: Video generation prompt
        api_key: Pollo API key
        first_frame_path: Path to first frame image (converted to public URL)
        last_frame_path: Path to last frame image for interpolation (converted to public URL)
        first_frame_url: Direct URL for first frame (alternative to path)
        last_frame_url: Direct URL for last frame (alternative to path)
        aspect_ratio: Video aspect ratio ("16:9", "9:16")
        length: Video length in seconds (4, 6, or 8)
        resolution: Video resolution ("720p", "1080p")
        generate_audio: Generate audio track (default: False)

    Returns:
        Dict with task_id and status for polling
    """
    input_data = {
        "prompt": prompt,
        "aspectRatio": aspect_ratio,
        "length": length,
        "resolution": resolution,
        "generateAudio": generate_audio
    }

    # Add first frame (Pollo only accepts URLs, not base64)
    if first_frame_url:
        print(f"  First frame URL: {first_frame_url}")
        input_data["image"] = first_frame_url
    elif first_frame_path and Path(first_frame_path).exists():
        url = path_to_public_url(first_frame_path)
        print(f"  First frame URL: {url}")
        input_data["image"] = url

    # Add last frame for interpolation (Pollo only accepts URLs)
    if last_frame_url:
        print(f"  Last frame URL: {last_frame_url}")
        input_data["imageTail"] = last_frame_url
    elif last_frame_path and Path(last_frame_path).exists():
        url = path_to_public_url(last_frame_path)
        print(f"  Last frame URL: {url}")
        input_data["imageTail"] = url

    payload = {"input": input_data}

    print(f"  Aspect ratio: {aspect_ratio}")
    print(f"  Length: {length}s")
    print(f"  Resolution: {resolution}")
    print(f"  Sending request to Pollo.ai...")

    session = get_session()
    response = session.post(
        f"{BASE_URL}/generation/google/veo3-1-fast",
        headers={
            "x-api-key": api_key,
            "Content-Type": "application/json"
        },
        json=payload,
        timeout=60
    )

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

    result = response.json()

    if result.get("code") != "SUCCESS":
        raise RuntimeError(f"Pollo API error: {result}")

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

    print(f"  Task created: {task_id}")
    return {"task_id": task_id, "status": result.get("data", {}).get("status"), "raw": result}


def poll_veo3_pollo(
    task_id: str,
    api_key: str,
    poll_interval: int = 10,
    timeout: int = 600
) -> dict:
    """
    Poll Pollo.ai for task completion.

    Args:
        task_id: Task ID from call_veo3_pollo()
        api_key: Pollo 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

    session = get_session()
    while time.time() - start_time < timeout:
        try:
            # Polling endpoint: /generation/{taskId}/status
            response = session.get(
                f"{BASE_URL}/generation/{task_id}/status",
                headers={
                    "x-api-key": api_key,
                    "Content-Type": "application/json"
                },
                timeout=30
            )

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

            result = response.json()
            consecutive_errors = 0  # Reset on success

            # Response format: {"code":"SUCCESS","data":{"taskId":"...","generations":[{"status":"succeed","url":"..."}]}}
            if result.get("code") != "SUCCESS":
                raise RuntimeError(f"Pollo API error: {result}")

            data = result.get("data", {})
            generations = data.get("generations", [])

            if generations:
                gen = generations[0]
                status = gen.get("status", "")

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

                if status == "failed":
                    fail_msg = gen.get("failMsg", "Unknown error")
                    raise RuntimeError(f"Pollo generation failed: {fail_msg}")

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

        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"Pollo Veo3 generation timed out after {timeout}s")


def download_video_pollo(video_url: str, output_path: str) -> str:
    """Download video from URL."""
    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_pollo(api_key: str) -> dict:
    """Test Pollo API connection."""
    try:
        session = get_session()
        # Simple text-to-video test
        response = session.post(
            f"{BASE_URL}/generation/google/veo3-1-fast",
            headers={
                "x-api-key": api_key,
                "Content-Type": "application/json"
            },
            json={
                "input": {
                    "prompt": "A simple red dot on white background, 1 second",
                    "aspectRatio": "16:9",
                    "length": 8,
                    "resolution": "720p",
                    "generateAudio": False
                }
            },
            timeout=30
        )

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


if __name__ == "__main__":
    import sys
    import os
    from dotenv import load_dotenv

    load_dotenv(Path(__file__).parent.parent / ".env")

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

    if len(sys.argv) < 2:
        print("Usage:")
        print("  python pollo_proxy.py test              # Test API connection")
        print("  python pollo_proxy.py url <image_path>  # Convert path to public URL")
        print("  python pollo_proxy.py generate <prompt> [image_path]  # Generate video")
        sys.exit(1)

    cmd = sys.argv[1]

    if cmd == "test":
        print("Testing Pollo API...")
        result = test_pollo(api_key)
        print(f"Result: {json.dumps(result, indent=2)}")

    elif cmd == "url":
        if len(sys.argv) < 3:
            print("Usage: python pollo_proxy.py url <image_path>")
            sys.exit(1)
        image_path = sys.argv[2]
        try:
            url = path_to_public_url(image_path)
            print(f"Public URL: {url}")
        except ValueError as e:
            print(f"Error: {e}")

    elif cmd == "generate":
        if len(sys.argv) < 3:
            print("Usage: python pollo_proxy.py generate <prompt> [image_path]")
            sys.exit(1)

        prompt = sys.argv[2]
        image_path = sys.argv[3] if len(sys.argv) > 3 else None

        print(f"Prompt: {prompt}")
        if image_path:
            print(f"Image: {image_path}")

        result = call_veo3_pollo(
            prompt=prompt,
            api_key=api_key,
            first_frame_path=image_path,
            aspect_ratio="16:9",
            length=8,
            resolution="720p"
        )

        print(f"\nTask created: {result['task_id']}")
        print("Polling for completion...")

        video_result = poll_veo3_pollo(
            task_id=result["task_id"],
            api_key=api_key,
            poll_interval=5,
            timeout=600
        )

        print(f"\nVideo URL: {video_result['uri']}")

    else:
        print(f"Unknown command: {cmd}")
