#!/usr/bin/env python3
"""Summarize fixed-size hex frames from serial helper logs."""

from __future__ import annotations

import argparse
import collections
import re
from pathlib import Path


FRAME_RE = re.compile(
    r"\b(?P<direction>RX|TX)(?:\s+cmd\s+0x[0-9A-Fa-f]{2})?"
    r"(?:\s+fields\b.*?)?\s+"
    r"frame\s+\d+\s+(?P<frame>(?:[0-9A-Fa-f]{2}\s*)+)(?:\s+\S.*)?$"
)


def frames_from_log(path: Path) -> list[tuple[str, str]]:
    frames: list[tuple[str, str]] = []
    for line in path.read_text(encoding="utf-8").splitlines():
        match = FRAME_RE.search(line.strip())
        if match:
            direction = match.group("direction")
            frame = " ".join(match.group("frame").upper().split())
            frames.append((direction, frame))
    return frames


def checksum_note(frame: str) -> str:
    values = [int(part, 16) for part in frame.split()]
    if len(values) != 6:
        return ""

    checksum = 0x5A
    for value in values[:5]:
        checksum ^= value

    if checksum == values[5]:
        return " checksum ok"
    return f" checksum expected {checksum:02X}"


def main() -> int:
    parser = argparse.ArgumentParser(description="Count frames in capture logs.")
    parser.add_argument("logs", nargs="+", type=Path)
    args = parser.parse_args()

    for log in args.logs:
        frames = frames_from_log(log)
        counts = collections.Counter(frames)
        print(f"{log}: {len(frames)} frames, {len(counts)} unique direction/frame pairs")
        for (direction, frame), count in counts.most_common():
            print(f"  {count:5d}  {direction:<2}  {frame}{checksum_note(frame)}")
    return 0


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