# Python 3.10+. Standard library only. Run: python video-api.py https://media.example.com/video.mp4
# Set VIDEO_API_TOKEN; optionally set VIDEO_API_BASE (default below).
import json
import os
import sys
import time
import uuid
import urllib.error
import urllib.request

BASE = os.environ.get("VIDEO_API_BASE", "https://videodetector.org/api/v1").rstrip("/")
TOKEN = os.environ["VIDEO_API_TOKEN"]
next_request = 0.0


def request(method, path, body=None, key=None):
    global next_request
    headers = {"Authorization": "Bearer " + TOKEN, "Content-Type": "application/json"}
    if key:
        headers["Idempotency-Key"] = key
    data = None if body is None else json.dumps(body).encode()
    for attempt in range(6):
        time.sleep(max(0, next_request - time.monotonic()))
        req = urllib.request.Request(BASE + path, data=data, headers=headers, method=method)
        try:
            with urllib.request.urlopen(req, timeout=120) as response:
                return json.load(response)
        except urllib.error.HTTPError as error:
            try:
                detail = json.loads(error.read())
            except (ValueError, UnicodeError):
                detail = {"error": {"code": "HTTP_ERROR", "status": error.code}}
            code = detail.get("error", {}).get("code")
            if attempt == 5 or not (error.code in (429, 500, 502, 503, 504) or code in ("RESOURCE_BUSY",)):
                raise RuntimeError(detail) from None
            time.sleep(max(float(error.headers.get("Retry-After", 0)), min(2 ** attempt, 16)))
        except (urllib.error.URLError, TimeoutError):
            if attempt == 5:
                raise
            time.sleep(min(2 ** attempt, 16))
        finally:
            # Wait after the response; connection latency must not compress arrival gaps.
            next_request = time.monotonic() + 1.05
    raise RuntimeError("Request retries exhausted")


# The URL must stay accessible and its contents unchanged until detection finishes.
video_url = sys.argv[1]
if not video_url.startswith(("https://", "http://")):
    raise ValueError("Pass a publicly accessible video URL")
detection_key = os.environ.get("VIDEO_DETECTION_KEY", str(uuid.uuid4()))
print("Recovery key:", detection_key)
job = request("POST", "/video-detections", {
    "input": {"type": "url", "url": video_url},
    "client_reference": "video-example"
}, detection_key)
print("Detection ID:", job["id"])
deadline = time.monotonic() + 1800
while job["status"] in ("queued", "processing"):
    if time.monotonic() > deadline:
        raise RuntimeError("Still processing. Query the printed detection ID later; do not create another task.")
    time.sleep(15)
    job = request("GET", "/video-detections/" + job["id"])
print(json.dumps(job, indent=2, ensure_ascii=False))
