"""Summarize repeated point-loss tails at fixed offsets before the loss."""

from __future__ import annotations

import argparse
import json
from collections import Counter, defaultdict
from pathlib import Path
from statistics import mean


def rounded(value: object) -> object:
    if isinstance(value, float):
        return round(value, 2)
    return value


def bucket_row(row: dict) -> tuple:
    return (
        row.get("ball_x"),
        row.get("ball_y"),
        row.get("dx"),
        row.get("dy"),
        rounded(row.get("target_y")),
        row.get("self_paddle_y"),
        row.get("action_name"),
        row.get("mode"),
    )


def summarize(path: Path, pattern: str, offsets: list[int]) -> dict:
    records = []
    for line in path.read_text(encoding="utf-8").splitlines():
        if not line.strip():
            continue
        record = json.loads(line)
        if pattern and record.get("pattern") != pattern:
            continue
        records.append(record)

    offset_rows: dict[int, list[dict]] = defaultdict(list)
    for record in records:
        window = record.get("window") or []
        for offset in offsets:
            if len(window) >= offset:
                offset_rows[offset].append(window[-offset])

    summaries = []
    for offset in offsets:
        rows = offset_rows[offset]
        if not rows:
            summaries.append({"offset": offset, "count": 0})
            continue
        bucket_counts = Counter(bucket_row(row) for row in rows)
        top_bucket, top_count = bucket_counts.most_common(1)[0]
        summaries.append(
            {
                "offset": offset,
                "count": len(rows),
                "top_count": top_count,
                "top_fraction": top_count / len(rows),
                "top": {
                    "ball_x": top_bucket[0],
                    "ball_y": top_bucket[1],
                    "dx": top_bucket[2],
                    "dy": top_bucket[3],
                    "target_y": top_bucket[4],
                    "self_paddle_y": top_bucket[5],
                    "action_name": top_bucket[6],
                    "mode": top_bucket[7],
                },
                "mean_paddle_error": mean(
                    float(row["self_paddle_y"]) - float(row["target_y"])
                    for row in rows
                    if row.get("self_paddle_y") is not None and row.get("target_y") is not None
                ),
            }
        )

    return {"source": str(path), "pattern": pattern, "records": len(records), "offsets": summaries}


def main() -> None:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("jsonl", type=Path)
    parser.add_argument("--pattern", default="")
    parser.add_argument("--offsets", default="1,2,3,4,5,6,7,8,9,10,12,14,16")
    parser.add_argument("--output", type=Path)
    args = parser.parse_args()

    offsets = [int(part.strip()) for part in args.offsets.split(",") if part.strip()]
    result = summarize(args.jsonl, args.pattern, offsets)
    text = json.dumps(result, indent=2)
    if args.output:
        args.output.parent.mkdir(parents=True, exist_ok=True)
        args.output.write_text(text + "\n", encoding="utf-8")
    print(text)


if __name__ == "__main__":
    main()
