from __future__ import annotations

import json
from collections import Counter
from pathlib import Path
from typing import Any, Dict, Iterable, List, Optional

from core.threat import calculate_threat_score


class ReportBuilder:
    """Builds simple summaries for recent process and alert activity."""

    def __init__(
        self,
        events: Optional[Iterable[Dict[str, Any]]] = None,
        alerts: Optional[Iterable[Dict[str, Any]]] = None,
        health: Optional[Iterable[Dict[str, Any]]] = None,
    ):
        self.events = list(events or [])
        self.alerts = list(alerts or [])
        self.health = list(health or [])

    def build_summary(self) -> Dict[str, Any]:
        severities = Counter()
        sources = Counter()
        process_names = Counter()

        for event in self.events:
            source = str(event.get("source") or "unknown")
            severity = str(event.get("severity") or "info")
            process_name = str(event.get("process_name") or "unknown")
            sources[source] += 1
            severities[severity] += 1
            process_names[process_name] += 1

        alert_counts = Counter()
        for alert in self.alerts:
            alert_counts[str(alert.get("severity") or "info")] += 1

        return {
            "event_count": len(self.events),
            "alert_count": len(self.alerts),
            "severity_counts": dict(severities),
            "source_counts": dict(sources),
            "top_processes": dict(process_names.most_common(5)),
            "alert_severity_counts": dict(alert_counts),
        }

    def build_health_summary(self) -> Dict[str, Any]:
        component_status: Dict[str, str] = {}
        status_rank = {"healthy": 0, "warning": 1, "critical": 2, "error": 2}
        worst = "healthy"

        for item in self.health:
            component = str(item.get("component") or "unknown")
            status = str(item.get("status") or "healthy").lower()
            component_status[component] = status
            if status_rank.get(status, 0) > status_rank.get(worst, 0):
                worst = status

        return {
            "overall_status": worst,
            "component_status": component_status,
            "component_count": len(component_status),
        }

    def build_threat_score(self) -> Dict[str, Any]:
        return calculate_threat_score(self.alerts)

    def build_status_snapshot(self) -> Dict[str, Any]:
        summary = self.build_summary()
        health = self.build_health_summary()
        snapshot = {
            "event_count": summary["event_count"],
            "alert_count": summary["alert_count"],
            "severity_counts": summary["severity_counts"],
            "source_counts": summary["source_counts"],
            "top_processes": summary["top_processes"],
            "overall_status": health["overall_status"],
            "component_count": health["component_count"],
            "component_status": health["component_status"],
        }
        return snapshot

    def write_status_snapshot(self, output_path: str | Path) -> str:
        path = Path(output_path)
        path.parent.mkdir(parents=True, exist_ok=True)
        payload = self.build_status_snapshot()
        path.write_text(json.dumps(payload, indent=2, sort_keys=True), encoding="utf-8")
        return str(path)

    def render_health_summary(self) -> str:
        health = self.build_health_summary()
        lines = [
            "Operational Status",
            "==================",
            f"Overall: {health['overall_status']}",
        ]
        for component, status in sorted(health["component_status"].items()):
            lines.append(f"- {component}: {status}")
        return "\n".join(lines)

    def render_text(self) -> str:
        summary = self.build_summary()
        lines = [
            "Process Monitoring Summary",
            "==========================",
            f"Events: {summary['event_count']}",
            f"Alerts: {summary['alert_count']}",
            "",
            "Severity totals:",
        ]
        for name, count in sorted(summary["severity_counts"].items()):
            lines.append(f"- {name}: {count}")
        lines.extend(["", "Top processes:"])
        for name, count in summary["top_processes"].items():
            lines.append(f"- {name}: {count}")
        if self.health:
            lines.extend(["", self.render_health_summary()])
        return "\n".join(lines)
