#!/usr/bin/env python3
"""XSDHub CLI: HTTPS validation for CI. Requires explicit --allow-upload."""
import argparse,json,sys,urllib.request,urllib.error
from pathlib import Path
p=argparse.ArgumentParser(description=__doc__)
p.add_argument('xml',type=Path);p.add_argument('--schema',type=Path,required=True);p.add_argument('--project-dir',type=Path);p.add_argument('--engine',choices=['xsd10','xsd11','schematron'],default='xsd11');p.add_argument('--allow-upload',action='store_true',help='Consent to send these files to XSDHub for server validation');p.add_argument('--output',type=Path)
a=p.parse_args()
if not a.allow_upload:p.error('Server processing requires --allow-upload. Your XML and schemas will be sent to https://xsdhub.com/api/validate.')
def read(path,limit):
 if path.stat().st_size>limit:raise ValueError(str(path)+' exceeds the size limit')
 return path.read_text(encoding='utf-8')
try:
 data={'xml':read(a.xml,10*1048576),'engine':a.engine,'consent':True}
 if a.engine=='schematron':data['schematron']=read(a.schema,1048576)
 elif a.project_dir:
  root=a.project_dir.resolve();schema=a.schema.resolve();data['rootSchema']=schema.relative_to(root).as_posix();files=[];total=0
  for file in sorted(root.rglob('*.xsd')):
   if file.is_symlink():raise ValueError('Symbolic links are not included: '+str(file))
   content=read(file,1048576);total+=len(content.encode());files.append({'path':file.relative_to(root).as_posix(),'content':content})
   if len(files)>100 or total>10*1048576:raise ValueError('Project exceeds 100 files or 10 MB')
  data['schemaFiles']=files
 else:data['xsd']=read(a.schema,1048576)
 req=urllib.request.Request('https://xsdhub.com/api/validate',data=json.dumps(data).encode(),headers={'Content-Type':'application/json'},method='POST')
 with urllib.request.urlopen(req,timeout=30) as response:result=json.load(response)
 output=json.dumps(result,indent=2)
 if a.output:a.output.write_text(output+'\n',encoding='utf-8')
 print(output);sys.exit(0 if result.get('ok') else 1)
except Exception as e:
 if isinstance(e,urllib.error.HTTPError):
  try:message=json.load(e).get('error',str(e))
  except Exception:message=str(e)
 else:message=str(e)
 print(json.dumps({'ok':False,'error':message}),file=sys.stderr);sys.exit(2)
