#!/usr/bin/env python3
# File: scripts/report_marker_stats.py
# Purpose: Collect pytest marker counts to monitor Phase 1 rollout of technique markers.
# Context: Invoked by bin/test-marker-stats to provide weekly reporting without manual parsing.

"""Summarise pytest --collect-only results for configured markers."""

from __future__ import annotations

import argparse
import re
import subprocess
import sys
from collections.abc import Iterable


DEFAULT_MARKERS: list[str] = ["boundary", "error_case", "security"]


class MarkerCollectionError(RuntimeError):
    """Raised when pytest collection fails for a marker."""


def parse_args(argv: Iterable[str]) -> argparse.Namespace:
    """Parse CLI arguments for marker collection."""

    parser = argparse.ArgumentParser(
        description="Collect pytest markers using --collect-only to track Phase 1 adoption."
    )
    parser.add_argument(
        "marker",
        nargs="*",
        default=DEFAULT_MARKERS,
        help="Marker names to collect (defaults to boundary, error_case, security).",
    )
    parser.add_argument(
        "--pytest-args",
        nargs=argparse.REMAINDER,
        help=(
            "Additional arguments forwarded to pytest after --collect-only -m <marker>."
        ),
    )
    return parser.parse_args(list(argv))


def collect_marker(marker: str, extra_args: Iterable[str] | None) -> int:
    """Run pytest --collect-only for a marker and return the collected test count."""

    args = [sys.executable, "-m", "pytest", "--collect-only", "-m", marker]
    if extra_args:
        args.extend(extra_args)

    result = subprocess.run(args, capture_output=True, text=True, check=False)
    if result.returncode != 0:
        raise MarkerCollectionError(
            f"pytest collection failed for marker '{marker}' with code {result.returncode}"
        )

    output = f"{result.stdout}\n{result.stderr}"
    match = re.search(r"collected (\d+) items", output)
    if not match:
        raise MarkerCollectionError(
            f"Unable to parse collected item count for marker '{marker}'."
        )

    return int(match.group(1))


def render_table(counts: dict[str, int]) -> str:
    """Render a simple text table for marker counts."""

    header = f"{'Marker':<18} {'Collected':>10}"
    divider = "-" * len(header)
    body_lines = [f"{name:<18} {count:>10}" for name, count in counts.items()]
    return "\n".join([header, divider, *body_lines])


def main(argv: Iterable[str]) -> int:
    """Entry point for marker collection reporting."""

    args = parse_args(argv)
    extra_args = args.pytest_args if args.pytest_args else []

    counts: dict[str, int] = {}
    for marker in args.marker:
        counts[marker] = collect_marker(marker, extra_args)

    print(render_table(counts))
    return 0


if __name__ == "__main__":
    try:
        raise SystemExit(main(sys.argv[1:]))
    except MarkerCollectionError as exc:
        print(f"ERROR: {exc}", file=sys.stderr)
        raise SystemExit(1)
