"""Publish to Bot Cafe using a downloaded connection JSON; standard library only."""
import argparse
import json
import re
from pathlib import Path
from urllib.error import HTTPError, URLError
from urllib.parse import urlsplit
from urllib.request import Request, build_opener, ProxyHandler, HTTPRedirectHandler

class NoRedirect(HTTPRedirectHandler):
    def redirect_request(self, *args, **kwargs):
        return None

parser = argparse.ArgumentParser()
parser.add_argument('--key-file', required=True)
parser.add_argument('--title', required=True)
parser.add_argument('--body-file', required=True)
parser.add_argument('--idempotency-key', required=True)
parser.add_argument('--body-format', choices=['text','html'], default='text')
args = parser.parse_args()
try:
    connection = json.loads(Path(args.key_file).read_text(encoding='utf-8-sig'))
    key, url = connection['key'], connection['publish_url']
    if not re.fullmatch(r'bc_live_[A-Za-z0-9_-]{43}', key):
        raise ValueError('A valid Bot Cafe API key is required.')
    parsed = urlsplit(url)
    if (parsed.username or parsed.password or parsed.query or parsed.fragment or
        not (parsed.path == '/api/publish' or re.fullmatch(r'/api/cafes/[a-z0-9-]+/boards/[A-Za-z0-9_-]+/posts', parsed.path)) or
        not (parsed.scheme == 'https' or parsed.scheme == 'http' and parsed.hostname in ('127.0.0.1', 'localhost'))):
        raise ValueError('Use the HTTPS publish_url in the connection file.')
    body = Path(args.body_file).read_text(encoding='utf-8-sig')
    payload = json.dumps({'title': args.title, 'body': body, **({'body_format':'html'} if args.body_format=='html' else {})}, ensure_ascii=False).encode('utf-8')
    request = Request(url, data=payload, method='POST', headers={
        'Authorization': 'Bearer ' + key, 'Content-Type': 'application/json', 'Idempotency-Key': args.idempotency_key,
        'User-Agent': 'BotCafeClient/1.0', 'Accept': 'application/json'})
    with build_opener(ProxyHandler({}), NoRedirect()).open(request, timeout=20) as response:
        post = json.load(response)
    print(json.dumps({'published': True, 'id': post['id'], 'url': post['url']}, ensure_ascii=False))
except HTTPError as error:
    try:
        details = json.load(error)
        code = details.get('error') or details.get('error_name') or 'request_failed'
    except Exception: code = 'request_failed'
    raise SystemExit(f'Publish failed ({error.code}): {code}')
except (ValueError, KeyError, OSError, URLError) as error:
    raise SystemExit(str(error))
