"""JSON formatter for scan results."""

import json
from collections import Counter
from datetime import datetime, timezone


def _sev_name(severity) -> str:
    return (severity.name if hasattr(severity, "name") else str(severity)).upper()


def _cls_name(classification) -> str:
    return (classification.name if hasattr(classification, "name") else str(classification)).upper()


class JsonFormatter:
    """Serializes a ScanResult to a JSON string."""

    def format(self, result, duration_ms: int) -> str:
        severity_counts = Counter(_sev_name(f.severity) for f in result.findings)

        endpoints = []
        for ep in result.endpoints:
            methods_list = [
                m.value if hasattr(m, "value") else str(m) for m in ep.methods
            ]
            ep_type = ep.endpoint_type
            type_str = (ep_type.value if hasattr(ep_type, "value") else str(ep_type)).lower()
            endpoints.append({
                "route": str(getattr(ep, "full_route", ep.route)),
                "methods": methods_list,
                "type": type_str,
                "classification": _cls_name(ep.classification),
                "file_path": str(ep.file_path),
                "line_number": ep.line_number,
                "function_name": ep.function_name,
            })

        findings = []
        for f in result.findings:
            ep = getattr(f, "endpoint", None)
            findings.append({
                "rule_id": f.rule_id,
                "rule_name": f.rule_name,
                "severity": _sev_name(f.severity),
                "route": str(getattr(ep, "full_route", getattr(ep, "route", ""))) if ep else "",
                "file_path": str(ep.file_path) if ep else "",
                "line_number": ep.line_number if ep else 0,
                "message": f.message,
                "recommendation": f.recommendation or "",
            })

        output = {
            "generated": datetime.now(timezone.utc).isoformat(),
            "summary": {
                "scanned_path": str(result.scan_path),
                "files_scanned": len(getattr(result, "files_scanned", [])),
                "failed_files": len(getattr(result, "parse_errors", {})),
                "total_endpoints": len(result.endpoints),
                "total_findings": len(result.findings),
                "duration_ms": duration_ms,
            },
            "severity_counts": {
                "critical": severity_counts.get("CRITICAL", 0),
                "high": severity_counts.get("HIGH", 0),
                "medium": severity_counts.get("MEDIUM", 0),
                "low": severity_counts.get("LOW", 0),
                "info": severity_counts.get("INFO", 0),
            },
            "endpoints": endpoints,
            "findings": findings,
        }

        return json.dumps(output, indent=2)
