"""Summarize repeated loss families by seed from traced point records."""

from __future__ import annotations

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


def read_records(path: Path) -> list[dict]:
    records = []
    for line in path.read_text(encoding="utf-8").splitlines():
        if line.strip():
            records.append(json.loads(line))
    return records


def final_signature(record: dict) -> str:
    return (
        f"{record.get('pattern')};"
        f"x={record.get('final_ball_x')};"
        f"y={record.get('final_ball_y')};"
        f"dy={record.get('final_dy')};"
        f"target={record.get('final_target_y')};"
        f"pad={record.get('final_self_paddle_y')};"
        f"err={record.get('final_paddle_error')}"
    )


def classify_seed(loss_counts: Counter, signature_counts: Counter) -> str:
    high_y165 = sum(
        count
        for signature, count in signature_counts.items()
        if signature.startswith("loss/high_down/paddle_above_target")
        and "x=202;" in signature
        and "y=165;" in signature
    )
    mid_y86 = sum(
        count
        for signature, count in signature_counts.items()
        if signature.startswith("loss/mid_down/near_target")
        and "x=202;" in signature
        and "y=86;" in signature
    )
    low_y69 = sum(
        count
        for signature, count in signature_counts.items()
        if signature.startswith("loss/low_up/paddle_above_target")
        and "x=205;" in signature
        and "y=69;" in signature
    )
    high_y173 = sum(
        count
        for signature, count in signature_counts.items()
        if signature.startswith("loss/high_down/paddle_above_target")
        and "x=204;" in signature
        and "y=173;" in signature
    )

    if high_y165 >= 7:
        return "repeated_high_down_y165"
    if mid_y86 >= 7 and low_y69 >= 1:
        return "repeated_y86_with_low_up_setup"
    if mid_y86 >= 7:
        return "repeated_y86_after_high_down"
    if high_y173 >= 1:
        return "early_high_down_y173"
    return "mixed"


def summarize(path: Path) -> dict:
    records = read_records(path)
    by_seed: dict[int, list[dict]] = defaultdict(list)
    for record in records:
        by_seed[int(record["seed"])].append(record)

    seed_summaries = []
    family_counts = Counter()
    loss_pattern_counts = Counter()
    final_signature_counts = Counter()

    for seed, seed_records in sorted(by_seed.items()):
        losses = [record for record in seed_records if record.get("outcome") == "loss"]
        loss_counts = Counter(record.get("pattern") for record in losses)
        signature_counts = Counter(final_signature(record) for record in losses)
        family = classify_seed(loss_counts, signature_counts)
        family_counts[family] += 1
        loss_pattern_counts.update(loss_counts)
        final_signature_counts.update(signature_counts)

        seed_summaries.append(
            {
                "seed": seed,
                "family": family,
                "points": len(seed_records),
                "wins": sum(1 for record in seed_records if record.get("outcome") == "win"),
                "losses": len(losses),
                "loss_patterns": dict(loss_counts),
                "top_final_signatures": [
                    {"count": count, "signature": signature}
                    for signature, count in signature_counts.most_common(5)
                ],
            }
        )

    return {
        "source": str(path),
        "seed_count": len(by_seed),
        "family_counts": dict(family_counts),
        "loss_pattern_counts": dict(loss_pattern_counts),
        "top_final_signatures": [
            {"count": count, "signature": signature}
            for signature, count in final_signature_counts.most_common(10)
        ],
        "mean_losses_per_seed": mean(summary["losses"] for summary in seed_summaries)
        if seed_summaries
        else None,
        "seeds": seed_summaries,
    }


def main() -> None:
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("jsonl", type=Path)
    parser.add_argument("--output", type=Path)
    args = parser.parse_args()

    result = summarize(args.jsonl)
    text = json.dumps(result, indent=2, sort_keys=True)
    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()
