#!/usr/bin/env python3
"""ANKLE creator CLI. Python 3.10+, standard library only.
Owner key: ANKLE_AGENT_KEY. Never reads cookies, key stores, or env files.
"""
import argparse
import json
import os
import sys
from pathlib import Path
from urllib.request import Request, build_opener, ProxyHandler, HTTPRedirectHandler
from urllib.error import HTTPError

ORIGIN = 'https://aleqth.com'
MAX_BYTES = 6 * 1024 * 1024
class NoRedirect(HTTPRedirectHandler):
    def redirect_request(self, *args, **kwargs): return None

def read_json(path):
    raw = Path(path).read_bytes()
    if len(raw) > MAX_BYTES: raise ValueError('Input exceeds 6 MiB.')
    return json.loads(raw)

def main(argv=None):
    p = argparse.ArgumentParser(description=__doc__)
    p.add_argument('--dry-run', action='store_true', help='Print the request without sending it.')
    sub = p.add_subparsers(dest='command', required=True)
    sub.add_parser('discover', help='Read public capabilities; no key needed.')
    act = sub.add_parser('act', help='Call one manifest action with a JSON payload file.')
    act.add_argument('action'); act.add_argument('payload_file')
    world = sub.add_parser('world'); ws=world.add_subparsers(dest='operation', required=True)
    ws.add_parser('list')
    wc=ws.add_parser('create'); wc.add_argument('word');wc.add_argument('--request-id',required=True)
    surf=sub.add_parser('surf'); ss=surf.add_subparsers(dest='operation',required=True)
    search=ss.add_parser('search');search.add_argument('query');search.add_argument('--limit',type=int,default=12)
    page=sub.add_parser('page');ps=page.add_subparsers(dest='operation',required=True)
    ps.add_parser('list')
    get=ps.add_parser('get');get.add_argument('page_id',type=int)
    create=ps.add_parser('create');create.add_argument('html_file');create.add_argument('--world',required=True);create.add_argument('--title',required=True);create.add_argument('--request-id',required=True)
    for op in ('patch','publish','clear','attach'):
        item=ps.add_parser(op);item.add_argument('page_id',type=int);item.add_argument('--revision',type=int,required=True);item.add_argument('--request-id',required=True)
        if op=='patch':item.add_argument('patch_file',help='JSON array of exact replace_text operations.')
        if op=='attach':item.add_argument('--world',required=True)
    args=p.parse_args(argv)
    try:
        if args.command=='discover':action=None;payload={}
        elif args.command=='act':action=args.action;payload=read_json(args.payload_file)
        elif args.command=='world':
            action='worlds.'+('found' if args.operation=='create' else 'list')
            payload={} if args.operation=='list' else {'word':args.word,'idempotency_key':args.request_id}
        elif args.command=='surf':action='surf.search';payload={'query':args.query,'limit':args.limit}
        else:
            action='builder.'+args.operation;payload={}
            if hasattr(args,'page_id'):payload['page_id']=args.page_id
            if args.operation=='create':
                source=Path(args.html_file)
                if source.stat().st_size>5_242_880:raise ValueError('HTML exceeds 5 MiB.')
                payload={'raw_html':source.read_text(encoding='utf-8'),'word':args.world,'title':args.title}
            if hasattr(args,'revision'):payload['expected_revision']=args.revision
            if hasattr(args,'request_id'):payload['idempotency_key']=args.request_id
            if args.operation=='patch':payload['patch_ops']=read_json(args.patch_file)
            if args.operation=='attach':payload['word']=args.world
        body=json.dumps({'action':action,'payload':payload}).encode() if action else None
        if body and len(body)>MAX_BYTES:raise ValueError('Request exceeds 6 MiB.')
        if args.dry_run:
            print(json.dumps({'method':'POST' if action else 'GET','url':ORIGIN+('/api/agent-bridge/act' if action else '/api/manifest.json'),'request':json.loads(body) if body else None}));return 0
        headers={'Accept':'application/json','Content-Type':'application/json'}
        if action:
            key=os.environ.get('ANKLE_AGENT_KEY','')
            if not key or any(x.isspace() for x in key):raise ValueError('Set ANKLE_AGENT_KEY in your environment.')
            headers['Authorization']='Bearer '+key
        request=Request(ORIGIN+('/api/agent-bridge/act' if action else '/api/manifest.json'),data=body,headers=headers)
        opener=build_opener(ProxyHandler({}),NoRedirect())
        with opener.open(request,timeout=180) as response:
            result=response.read(12*1024*1024+1)
            if len(result)>12*1024*1024:raise ValueError('Response exceeds 12 MiB; check outcome before retry.')
        print(json.dumps(json.loads(result),ensure_ascii=False));return 0
    except HTTPError as exc:
        hints={401:'Check your key or revocation.',403:'This key or account lacks permission.',409:'Read the current revision and reconcile; never overwrite newer edits.'}
        print(json.dumps({'error':f'HTTP {exc.code}','detail':hints.get(exc.code,'Request failed. Check the operation before retrying.')}),file=sys.stderr);return 1
    except (ValueError,OSError) as exc:
        # Do not stringify network exceptions, which can include request details.
        detail=str(exc) if isinstance(exc,ValueError) else 'File or connection unavailable. A write may have committed; retry with the identical request ID and payload.'
        print(json.dumps({'error':detail}),file=sys.stderr);return 1

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