from email.utils import parsedate_to_datetime
import os
from pathlib import Path
import random
import time
import requests

api_key = os.environ["DEEPSWAPAI_API_KEY"]
base_url = "https://deepswapai.com"
headers = {"Authorization": f"Bearer {api_key}", "Accept": "application/json"}
max_poll_seconds = float(os.getenv("DEEPSWAPAI_POLL_TIMEOUT_MS", "1800000")) / 1000
task_id_file = Path("deepswapai-task-id.txt")
terminal = {"COMPLETED", "FAILED", "CANCELLED"}

def retry_after_seconds(response):
    value = response.headers.get("Retry-After")
    if not value:
        return 0
    try:
        return max(0, float(value))
    except ValueError:
        try:
            return max(0, parsedate_to_datetime(value).timestamp() - time.time())
        except (TypeError, ValueError, OverflowError):
            return 0

# Submit exactly once. Reconcile an uncertain response before another POST.
with open("identity.jpg", "rb") as source, open("scene.jpg", "rb") as target:
    response = requests.post(
        f"{base_url}/api/ai-tasks",
        headers=headers,
        files={"sourceImage": source, "targetImage": target},
        timeout=60,
    )
response.raise_for_status()
task = response.json()
task_id_file.write_text(f'{task["taskId"]}\n', encoding="utf-8")
task_id_file.chmod(0o600)
print(f'Saved taskId {task["taskId"]} to {task_id_file}')

state = task
delay_seconds = 5
deadline = time.monotonic() + max_poll_seconds
while state["status"] not in terminal:
    if time.monotonic() >= deadline:
        raise TimeoutError(f'Local polling deadline reached. Task {task["taskId"]} may still be running; resume GET polling instead of creating a duplicate task.')
    time.sleep(min(delay_seconds * random.uniform(0.8, 1.2), max(0, deadline - time.monotonic())))
    response = requests.get(
        f"{base_url}/api/ai-tasks",
        headers=headers,
        params={"taskId": task["taskId"]},
        timeout=30,
    )
    if response.status_code == 429 or response.status_code >= 500:
        delay_seconds = min(30, max(retry_after_seconds(response), delay_seconds * 1.6))
        continue
    response.raise_for_status()
    state = response.json()
    if state["status"] not in terminal:
        delay_seconds = min(30, delay_seconds * 1.6)
print(state)
