"""JSON reporter for machine-readable output."""

import json
from pathlib import Path

from ..models.report import ImpactReport


class JSONReporter:
    """
    Generates JSON output for impact reports.

    Useful for:
    - CI/CD pipeline integration
    - Programmatic analysis
    - Data export and archival
    """

    def report(self, impact: ImpactReport, output_file: str | Path) -> None:
        """
        Write impact report to a JSON file.

        Args:
            impact: ImpactReport to export
            output_file: Path to output JSON file
        """
        report_dict = self._build_report_dict(impact)

        output_path = Path(output_file)
        with open(output_path, "w", encoding="utf-8") as f:
            json.dump(report_dict, f, indent=2, default=str)

    def to_string(self, impact: ImpactReport) -> str:
        """
        Convert impact report to JSON string.

        Args:
            impact: ImpactReport to convert

        Returns:
            JSON string representation
        """
        report_dict = self._build_report_dict(impact)
        return json.dumps(report_dict, indent=2, default=str)

    def _build_report_dict(self, impact: ImpactReport) -> dict:
        """
        Build dictionary representation of impact report.

        Args:
            impact: ImpactReport to convert

        Returns:
            Dictionary suitable for JSON serialization
        """
        stats = impact.statistics

        return {
            "summary": {
                "total_events": impact.total_events,
                "denied_count": impact.denied_count,
                "allowed_count": impact.allowed_count,
                "denial_rate": round(impact.denial_rate, 2),
                "risk_level": impact.get_risk_level(),
                "analysis_period": {
                    "start": impact.start_time.isoformat(),
                    "end": impact.end_time.isoformat(),
                },
                "scp_policy": impact.scp_policy_name,
            },
            "simulation_metadata": {
                "confidence": stats.simulation_confidence,
                "confidence_qualifier": stats.confidence_qualifier,
                "resource_resolution_rate": round(stats.resource_resolution_rate, 2),
                "total_evaluated_events": stats.total_evaluated_events,
                "unresolved_resource_count": stats.unresolved_resource_count,
                "unevaluable_condition_keys": stats.unevaluable_keys_summary,
                "slr_events_filtered": stats.slr_events_filtered,
                "mgmt_account_events_filtered": stats.mgmt_account_events_filtered,
                "warnings": impact.warnings,
            },
            "statistics": {
                "denied_by_service": stats.denied_by_service,
                "top_denied_actions": [
                    {"action": action, "count": count}
                    for action, count in stats.top_denied_actions[:20]
                ],
                "affected_principals": [
                    {"arn": arn, "count": count}
                    for arn, count in impact.get_top_affected_principals(20)
                ],
                "denials_by_statement": stats.denials_by_statement,
                "critical_services_affected": stats.critical_services_affected,
                "production_impact_score": round(stats.production_impact_score, 2),
            },
            "denied_events": [
                {
                    "timestamp": event.event_time.isoformat(),
                    "event_id": event.event_id,
                    "action": event.iam_action,
                    "service": event.event_source,
                    "region": event.aws_region,
                    "principal": event.principal_arn,
                    "principal_type": event.principal_type,
                    "source_ip": event.source_ip_address,
                    "scp_statement": (
                        result.matched_statement.sid
                        if result.matched_statement and result.matched_statement.sid
                        else None
                    ),
                    "reason": result.reason,
                    "unevaluable_condition_keys": result.unevaluable_condition_keys,
                    "resource_arn_resolved": result.resource_arn_resolved,
                }
                for event, result in impact.denied_events
            ],
        }
