"""State of MCP report generator.

Reads a JSONL file produced by ``navil scan-batch`` and generates an
aggregate Markdown report suitable for publishing.
"""

from __future__ import annotations

import logging
from collections import Counter
from datetime import datetime, timezone
from pathlib import Path
from typing import Any

import orjson

logger = logging.getLogger(__name__)


def _load_scan_results(jsonl_path: str | Path) -> list[dict[str, Any]]:
    """Read a JSONL file and return a list of result dicts."""
    results: list[dict[str, Any]] = []
    path = Path(jsonl_path)
    if not path.exists():
        return results
    for line in path.read_text().splitlines():
        line = line.strip()
        if not line:
            continue
        try:
            results.append(orjson.loads(line))
        except orjson.JSONDecodeError as exc:
            logger.warning("Skipping malformed JSONL line: %s", exc)
    return results


def generate_state_of_mcp_report(jsonl_path: str | Path) -> str:
    """Generate a Markdown report from batch scan results.

    Args:
        jsonl_path: Path to the JSONL file from ``navil scan-batch``.

    Returns:
        Markdown string.
    """
    records = _load_scan_results(jsonl_path)

    total = len(records)
    successful = [r for r in records if r.get("status") == "success"]
    failed = [r for r in records if r.get("status") == "error"]
    timed_out = [r for r in records if r.get("status") == "timeout"]

    # ── Aggregate stats ───────────────────────────────────────
    severity_counter: Counter[str] = Counter()
    vuln_type_counter: Counter[str] = Counter()
    scores: list[int] = []
    source_counter: Counter[str] = Counter()

    for rec in successful:
        scan = rec.get("scan", {})
        score = scan.get("security_score", 0)
        scores.append(score)
        source_counter[rec.get("source", "unknown")] += 1

        # Count findings by severity
        findings = scan.get("findings", [])
        for f in findings:
            sev = f.get("severity", "UNKNOWN") if isinstance(f, dict) else "UNKNOWN"
            severity_counter[sev] += 1

        # Count vulnerability types
        vulns = scan.get("vulnerabilities", [])
        for v in vulns:
            vid = v.get("id", "UNKNOWN") if isinstance(v, dict) else "UNKNOWN"
            vuln_type_counter[vid] += 1

    # Guard against division by zero
    avg_score = sum(scores) / len(scores) if scores else 0.0
    min_score = min(scores) if scores else 0
    max_score = max(scores) if scores else 0

    # ── Build Markdown ────────────────────────────────────────
    now = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M UTC")
    lines: list[str] = []

    lines.append("# State of MCP Security Report")
    lines.append("")
    lines.append(f"*Generated by Navil on {now}*")
    lines.append("")

    # Summary
    lines.append("## Summary")
    lines.append("")
    lines.append(f"| Metric | Value |")
    lines.append(f"|--------|-------|")
    lines.append(f"| Total servers scanned | {total} |")
    lines.append(f"| Successful scans | {len(successful)} |")
    lines.append(f"| Failed scans | {len(failed)} |")
    lines.append(f"| Timed out | {len(timed_out)} |")
    lines.append(f"| Average security score | {avg_score:.1f} / 100 |")
    lines.append(f"| Min score | {min_score} |")
    lines.append(f"| Max score | {max_score} |")
    lines.append("")

    # Findings by severity
    if severity_counter:
        lines.append("## Findings by Severity")
        lines.append("")
        lines.append("| Severity | Count |")
        lines.append("|----------|-------|")
        for sev in ["CRITICAL", "HIGH", "MEDIUM", "LOW", "INFO"]:
            count = severity_counter.get(sev, 0)
            if count > 0:
                lines.append(f"| {sev} | {count} |")
        # Any unknown severities
        for sev, count in severity_counter.most_common():
            if sev not in ("CRITICAL", "HIGH", "MEDIUM", "LOW", "INFO"):
                lines.append(f"| {sev} | {count} |")
        lines.append("")

    # Top vulnerability types
    if vuln_type_counter:
        lines.append("## Top Vulnerability Types")
        lines.append("")
        lines.append("| Vulnerability ID | Count |")
        lines.append("|-----------------|-------|")
        for vid, count in vuln_type_counter.most_common(20):
            lines.append(f"| {vid} | {count} |")
        lines.append("")

    # By source
    if source_counter:
        lines.append("## Servers by Source")
        lines.append("")
        lines.append("| Source | Count |")
        lines.append("|--------|-------|")
        for src, count in source_counter.most_common():
            lines.append(f"| {src} | {count} |")
        lines.append("")

    # Score distribution
    if scores:
        lines.append("## Score Distribution")
        lines.append("")
        buckets = {"0-20": 0, "21-40": 0, "41-60": 0, "61-80": 0, "81-100": 0}
        for s in scores:
            if s <= 20:
                buckets["0-20"] += 1
            elif s <= 40:
                buckets["21-40"] += 1
            elif s <= 60:
                buckets["41-60"] += 1
            elif s <= 80:
                buckets["61-80"] += 1
            else:
                buckets["81-100"] += 1
        lines.append("| Score Range | Count |")
        lines.append("|-------------|-------|")
        for bucket, count in buckets.items():
            lines.append(f"| {bucket} | {count} |")
        lines.append("")

    # Footer
    lines.append("---")
    lines.append("")
    lines.append("*Report generated by [Navil](https://github.com/ivanlkf/navil)*")
    lines.append("")

    return "\n".join(lines)
