#!/usr/bin/env python3
"""Small command-line TCP JSONL client for the GDR/XDVD host server.

Examples:
  python gdr_host_cli.py --ready-file server_ready.json --op state --pretty
  python gdr_host_cli.py --host 127.0.0.1 --port 32610 --cdb "25 00 00 00 00 00 00 00 00 00" --pretty
  python gdr_host_cli.py --ready-file server_ready.json --script requests.jsonl --out responses.jsonl
"""
from __future__ import annotations

import argparse, json, socket, sys, tempfile
from pathlib import Path
from typing import Any

from gdr_host_tcp_client import run_client


def write_one_request(args: argparse.Namespace) -> Path:
    req: dict[str, Any] = {'tag': args.tag or 'cli_request'}
    if args.op:
        req['op'] = args.op
    if args.cdb:
        req['cdb_hex'] = args.cdb
    if args.data_out:
        req['data_out_hex'] = args.data_out
    if args.stage:
        req['stage'] = args.stage
    if args.xdvd_json:
        req['xdvd_json'] = args.xdvd_json
    if args.iso:
        req['iso'] = args.iso
    if args.log:
        req['log'] = args.log
    if not req.get('op') and not req.get('cdb_hex'):
        raise SystemExit('supply --script, --op, or --cdb')
    p = Path(tempfile.mktemp(prefix='gdr_host_cli_', suffix='.jsonl'))
    p.write_text(json.dumps(req, separators=(',', ':')) + '\n', encoding='utf-8')
    return p


def main() -> int:
    ap = argparse.ArgumentParser(description='Send JSONL SCSI/control requests to a GDR/XDVD TCP host server')
    ap.add_argument('--host', default='127.0.0.1')
    ap.add_argument('--port', type=int, default=32610)
    ap.add_argument('--ready-file', help='optional {host,port} JSON written by gdr_host_server.py')
    ap.add_argument('--timeout', default='10')
    ap.add_argument('--script', '-i', help='JSON/JSONL requests; when omitted, one request is built from --op/--cdb')
    ap.add_argument('--out', '-o', help='write JSONL responses here; stdout when omitted or -')
    ap.add_argument('--write-response-dir', help='optional directory for binary DATA IN/OUT payloads')
    ap.add_argument('--catalog', help='optional generated command catalog for verification annotation')
    ap.add_argument('--verify-md', help='optional compact verification markdown')
    ap.add_argument('--allow-check-condition', action='store_true', help='return 0 even when some responses are CHECK CONDITION')
    ap.add_argument('--pretty', action='store_true', help='pretty-print responses after the request completes')
    ap.add_argument('--op', help='single control op: state, media_info, eject, load, unmount, mount, reset_auth')
    ap.add_argument('--tag')
    ap.add_argument('--cdb', help='single raw CDB hex string')
    ap.add_argument('--data-out', help='single DATA OUT payload hex string')
    ap.add_argument('--stage', help='auth stage for reset_auth/mount, e.g. locked or unlocked')
    ap.add_argument('--xdvd-json', help='mount/select_media target sidecar for single request')
    ap.add_argument('--iso', help='mount/select_media target ISO for single request')
    ap.add_argument('--log', help='mount/select_media unlock log for single request')
    args = ap.parse_args()

    temp_path: Path | None = None
    if not args.script:
        temp_path = write_one_request(args)
        args.script = str(temp_path)
    try:
        # Capture stdout into a temp file when pretty-printing a single/stdout run.
        pretty_temp: Path | None = None
        if args.pretty and (not args.out or args.out == '-'):
            pretty_temp = Path(tempfile.mktemp(prefix='gdr_host_cli_resp_', suffix='.jsonl'))
            args.out = str(pretty_temp)
        rc = run_client(args)
        if args.pretty:
            src = Path(args.out) if args.out and args.out != '-' else pretty_temp
            if src and src.exists():
                for line in src.read_text(encoding='utf-8').splitlines():
                    if line.strip():
                        print(json.dumps(json.loads(line), indent=2))
        return rc
    finally:
        if temp_path:
            try: temp_path.unlink()
            except Exception: pass


if __name__ == '__main__':
    raise SystemExit(main())
