"""Python 3. Set DEEPFAKEPOLICY_API_KEY; run: python check-media.py photo.jpg"""
import json
import os
import sys
import time
import uuid
from pathlib import Path
from urllib.request import Request, urlopen
from urllib.error import HTTPError

ORIGIN = "https://deepfakepolicy.com"
KEY = os.environ["DEEPFAKEPOLICY_API_KEY"]
source = Path(sys.argv[1])
types = {".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".png": "image/png", ".webp": "image/webp", ".gif": "image/gif", ".mp4": "video/mp4", ".mov": "video/quicktime", ".m4v": "video/x-m4v"}
content_type = types[source.suffix.lower()]
service_tier = sys.argv[2] if len(sys.argv) > 2 else "full"
if service_tier not in ("basic", "full") or (content_type.startswith("video/") and service_tier == "basic"):
    raise ValueError("Choose basic for photos or full for photos/videos.")
media = source.read_bytes()

def api(path, method="GET", data=None, headers=None):
    for attempt in range(4):
        request = Request(ORIGIN + path, data=data, method=method,
                          headers={"Authorization": "Bearer " + KEY, **(headers or {})})
        try:
            with urlopen(request, timeout=180) as response:
                body = response.read()
                return json.loads(body) if body else None
        except HTTPError as error:
            if error.code == 429 and attempt < 3:
                time.sleep(min(120, int(error.headers.get("Retry-After", "10"))))
                continue  # Keep the same idempotency key for retries.
            raise RuntimeError(error.read().decode()) from error

job = api("/v1/jobs", "POST", json.dumps({
    "modality": "video" if content_type.startswith("video/") else "image",
    "analysisMode": "quick",
    "serviceTier": service_tier,
    "source": {"name": source.name, "contentType": content_type, "sizeBytes": len(media)},
}).encode(), {"Content-Type": "application/json", "Idempotency-Key": str(uuid.uuid4())})
if job["links"].get("upload"):
    api(job["links"]["upload"], "PUT", media, {"Content-Type": content_type})
result, deadline = job, time.monotonic() + 600
while result["status"] not in ("completed", "failed", "deleted", "deletion_pending"):
    if time.monotonic() > deadline:
        raise TimeoutError("Poll " + job["links"]["self"] + "; do not create another job.")
    time.sleep(2)
    result = api(job["links"]["self"])
if result["status"] != "completed":
    raise RuntimeError(json.dumps(result.get("error") or result["status"]))
print(json.dumps(result, indent=2))
# After saving the report, optionally api(job["links"]["delete"], "DELETE").
