#!/usr/bin/env python3
"""Connector agent client. Token comes only from CONNECTOR_TOKEN, never CLI arguments."""
import argparse
import json
import os
from pathlib import Path
import sys
from urllib.parse import quote, urlsplit
from urllib.request import Request, urlopen, HTTPRedirectHandler, build_opener
from urllib.error import HTTPError

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

def main():
    parser=argparse.ArgumentParser(description=__doc__)
    parser.add_argument('--url',default='https://connector.kasnov-dev.online')
    parser.add_argument('--project',required=True)
    sub=parser.add_subparsers(dest='command',required=True)
    sub.add_parser('status');sub.add_parser('context')
    down=sub.add_parser('download');down.add_argument('--version',type=int,required=True);down.add_argument('--out',required=True)
    up=sub.add_parser('upload');up.add_argument('--file',required=True);up.add_argument('--base',type=int,required=True);up.add_argument('--note',required=True)
    args=parser.parse_args()
    token=os.environ.get('CONNECTOR_TOKEN')
    if not token: parser.error('Set CONNECTOR_TOKEN in the environment.')
    if urlsplit(args.url).scheme!='https' or urlsplit(args.url).username or urlsplit(args.url).password: parser.error('An HTTPS service address is required.')
    import re
    if not re.fullmatch('[a-f0-9]{32}',args.project): parser.error('Invalid project identifier.')
    path='/api/projects/'+args.project
    headers={'Authorization':'Bearer '+token};data=None
    if args.command=='context':path+='/context'
    if args.command=='download':path+='/versions/'+str(args.version)+'/download'
    if args.command=='upload':
        path+='/versions';data=Path(args.file).read_bytes()
        if len(data)>32*1024*1024: parser.error('ZIP exceeds 32 MiB.')
        headers.update({'Content-Type':'application/zip','X-Base-Version':str(args.base),'X-Change-Note':quote(args.note)})
    try:
        with build_opener(NoRedirect()).open(Request(args.url.rstrip('/')+path,data=data,headers=headers),timeout=60) as response: raw=response.read()
        if args.command=='download':
            # Never overwrite a local file silently.
            with Path(args.out).open('xb') as f:f.write(raw)
            print('Saved '+args.out)
        else:print(json.dumps(json.loads(raw),ensure_ascii=False,indent=2))
    except HTTPError as e:
        print(e.read().decode('utf-8',errors='replace'),file=sys.stderr);return 1
    return 0

if __name__=='__main__':sys.exit(main())
