import argparse
import json


def summarize(lines):
    report = {"commands": 0, "failed": [], "declined": [], "unknown": []}
    for lineno, raw in enumerate(lines, 1):
        if not raw.strip():
            continue
        try:
            event = json.loads(raw)
        except json.JSONDecodeError as exc:
            raise ValueError(f"line {lineno}: invalid JSON") from exc
        if not isinstance(event, dict):
            raise ValueError(f"line {lineno}: expected an object")
        if event.get("type") != "item.completed":
            continue
        item = event.get("item")
        if not isinstance(item, dict):
            raise ValueError(f"line {lineno}: missing item object")
        if item.get("type") != "command_execution":
            continue
        report["commands"] += 1
        code, status = item.get("exit_code"), item.get("status")
        if code is not None and type(code) is not int:
            raise ValueError(f"line {lineno}: invalid exit_code")
        if status == "declined":
            bucket = "declined"
        elif status == "failed" or (code is not None and code != 0):
            bucket = "failed"
        elif status == "completed" and code == 0:
            continue
        else:
            bucket = "unknown"
        report[bucket].append({"line": lineno, "id": item.get("id"),
                               "command": item.get("command"),
                               "exit_code": code, "status": status})
    return report


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("log")
    args = parser.parse_args()
    try:
        with open(args.log, encoding="utf-8") as stream:
            report = summarize(stream)
    except (OSError, ValueError) as exc:
        parser.exit(2, f"{exc}\n")
    print(json.dumps(report, ensure_ascii=False, indent=2))
