"""Python 3.10+, standard library. Run on a server, never expose the API key."""
import json
import os
import time
import uuid
from pathlib import Path
from urllib.error import HTTPError
from urllib.parse import urlparse
from urllib.request import Request, urlopen, build_opener, HTTPRedirectHandler

base = os.environ['PODCASTR_BASE_URL'].rstrip('/')
key = os.environ['PODCASTR_API_KEY']
url = urlparse(base)
if url.scheme != 'https' and url.hostname not in ('127.0.0.1', 'localhost', '::1'):
    raise ValueError('Use HTTPS outside local development.')
class NoRedirect(HTTPRedirectHandler):
    def redirect_request(self, req, fp, code, msg, headers, newurl):
        return None
opener = build_opener(NoRedirect)
def request(path, method='GET', data=None, idempotency=None, raw=False):
    headers = {'Authorization': 'Bearer ' + key}
    if data is not None:
        headers['Content-Type'] = 'application/json'
    if idempotency:
        headers['Idempotency-Key'] = idempotency
    for attempt in range(3):
        req = Request(base + '/api/v1' + path, data=json.dumps(data).encode() if data is not None else None, headers=headers, method=method)
        try:
            with opener.open(req, timeout=20) as response:
                body = response.read()
                return body if raw else json.loads(body)
        except HTTPError as exc:
            if exc.code in (429, 502, 504) and attempt < 2:
                time.sleep(min(60, int(exc.headers.get('Retry-After', '2'))))
                continue
            error = json.loads(exc.read()).get('error', {})
            raise RuntimeError(f"{error.get('code')}: {error.get('message')} (request {error.get('request_id')})") from None

podcast = request('/podcasts', 'POST', {'title': 'Notre premier épisode', 'script': 'Bienvenue dans notre premier podcast. Les conversations font avancer les projets, une idée et une voix à la fois.', 'voice': 'coral'}, str(uuid.uuid4()))['data']
generation = request(f"/podcasts/{podcast['id']}/generations", 'POST', idempotency=str(uuid.uuid4()))['data']
deadline = time.monotonic() + 300
while time.monotonic() < deadline:
    time.sleep(2.5)
    job = request(f"/generations/{generation['id']}")['data']
    if job['status'] == 'failed':
        raise RuntimeError(job.get('error', {}).get('message', 'Generation failed.'))
    if job['status'] == 'succeeded':
        Path('podcast.mp3').write_bytes(request(f"/podcasts/{podcast['id']}/audio", raw=True))
        print(f"Saved podcast.mp3 ({job['credits']} credits)")
        break
else:
    raise TimeoutError(f"Still pending. Poll /api/v1/generations/{generation['id']} later without submitting again.")
