#!/usr/bin/env python3
"""arq-neo4j — Neo4j Cypher API bridge.
v0: arq-neo4j health · arq-neo4j query --cypher 'MATCH (n) RETURN count(n)'
"""
import argparse, base64, json, os, sys, urllib.request, urllib.error
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent))
from _arq_provider_base import sops_extract, call_with_audit, print_json, handle_meta_flags

PROVIDER = "neo4j"
REQUIRED_SCOPES: dict[str, list[str]] = {
    # Neo4j AuraDB token scopes — admin for health probe, read for query exec.
    "health": ["project_admin"],
    "query": ["database_read"],
}
def _uri(): return os.environ.get("NEO4J_URI") or sops_extract('["neo4j"]["neo4j_uri"]')
def _user(): return os.environ.get("NEO4J_USER") or sops_extract('["neo4j"]["neo4j_user"]') or "neo4j"
def _pass(): return os.environ.get("NEO4J_PASSWORD") or sops_extract('["neo4j"]["neo4j_password"]')

def _query(path, data=None):
    uri = _uri(); u = _user(); p = _pass()
    if not uri or not p: return 401, "missing neo4j creds"
    auth = base64.b64encode(f"{u}:{p}".encode()).decode()
    headers = {"Authorization": f"Basic {auth}", "Content-Type": "application/json"}
    if uri.endswith("/"): uri = uri[:-1]
    req = urllib.request.Request(f"{uri}{path}", data=(json.dumps(data).encode() if data else None), headers=headers, method=("POST" if data else "GET"))
    try:
        with urllib.request.urlopen(req, timeout=30) as r: return r.status, json.loads(r.read())
    except urllib.error.HTTPError as e: return e.code, e.read().decode("utf-8","ignore")
    except Exception as e: return 500, str(e)

def _health(a):
    c, d = _query("/")
    if c != 200: sys.stderr.write(f"HTTP {c}: {d}\n"); return 1
    return print_json(d)
def _cypher(a):
    c, d = _query("/db/neo4j/tx/commit", {"statements": [{"statement": a.cypher}]})
    if c != 200: sys.stderr.write(f"HTTP {c}: {d}\n"); return 1
    return print_json(d)

def main():
    handle_meta_flags(PROVIDER, REQUIRED_SCOPES)
    p = argparse.ArgumentParser(prog="arq-neo4j"); s = p.add_subparsers(dest="cmd", required=True)
    s.add_parser("health").set_defaults(func=_health, verb="health")
    sq = s.add_parser("query"); sq.add_argument("--cypher", required=True); sq.set_defaults(func=_cypher, verb="query")
    args = p.parse_args()
    return call_with_audit(PROVIDER, args.verb, args.func, args)

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