"""JSON and HTML export reporters."""

from __future__ import annotations

import json
import math
from datetime import timedelta
from typing import Any

from sre_beacon.models import (
    AlertAuditReport,
    AvailabilityResult,
    IncidentMetrics,
    MaturityReport,
    SLOResult,
    ToilReport,
)


# ---------------------------------------------------------------------------
# JSON export
# ---------------------------------------------------------------------------

def export_json(data: dict, output_path: str) -> None:
    """Export any report data as JSON."""
    with open(output_path, "w", encoding="utf-8") as fh:
        json.dump(data, fh, indent=2, default=_json_default)


def slo_results_to_dict(results: list[SLOResult]) -> dict:
    return {
        "slo_compliance": [
            {
                "name": r.slo.name,
                "service": r.slo.service,
                "sli_type": r.slo.sli_type.value,
                "target": r.slo.target,
                "actual": r.actual,
                "compliant": r.compliant,
                "error_budget_total_min": round(r.error_budget_total_minutes, 2),
                "error_budget_remaining_pct": round(r.error_budget_remaining_pct, 2),
                "burn_rate": r.burn_rate,
            }
            for r in results
        ],
        "summary": {
            "total": len(results),
            "compliant": sum(1 for r in results if r.compliant),
        },
    }


def availability_results_to_dict(results: list[AvailabilityResult]) -> dict:
    return {
        "availability": [
            {
                "service": r.service,
                "availability_pct": r.availability_pct,
                "nines": r.nines if not math.isinf(r.nines) else "inf",
                "uptime_minutes": r.uptime_minutes,
                "downtime_minutes": r.downtime_minutes,
                "period": r.period,
            }
            for r in results
        ]
    }


def incident_metrics_to_dict(metrics: IncidentMetrics) -> dict:
    return {
        "incidents": {
            "total": metrics.total_incidents,
            "p1_p2": metrics.p1_p2_count,
            "mttr_seconds": metrics.mttr.total_seconds() if metrics.mttr else None,
            "mtta_seconds": metrics.mtta.total_seconds() if metrics.mtta else None,
            "mtbf_seconds": metrics.mtbf.total_seconds() if metrics.mtbf else None,
            "action_items_pct": metrics.incidents_with_action_items_pct,
            "by_severity": metrics.by_severity,
            "by_service": metrics.by_service,
        }
    }


def toil_report_to_dict(report: ToilReport) -> dict:
    return {
        "toil": {
            "total_hours_per_month": report.total_toil_hours_per_month,
            "toil_percentage": report.toil_percentage,
            "automatable_hours": report.automatable_hours_per_month,
            "automation_potential_pct": report.automation_potential_pct,
            "by_category": report.by_category,
            "by_frequency": report.by_frequency,
        }
    }


def alert_audit_to_dict(report: AlertAuditReport) -> dict:
    return {
        "alert_audit": {
            "total_rules": report.total_rules,
            "score": report.score,
            "grade": report.grade,
            "issues": [
                {
                    "rule_id": i.rule_id,
                    "severity": i.severity.value,
                    "alert_name": i.alert_name,
                    "message": i.message,
                    "suggestion": i.suggestion,
                }
                for i in report.issues
            ],
            "summary": {
                "critical": report.critical_count,
                "high": report.high_count,
                "medium": report.medium_count,
                "low": report.low_count,
                "info": report.info_count,
            },
        }
    }


def maturity_report_to_dict(report: MaturityReport) -> dict:
    return {
        "maturity": {
            "overall_score": round(report.overall_score, 2),
            "overall_level": report.overall_level.value,
            "dimensions": [
                {
                    "name": d.name,
                    "score": d.score,
                    "level": d.level.value,
                    "findings": d.findings,
                    "recommendations": d.recommendations,
                }
                for d in report.dimensions
            ],
        }
    }


# ---------------------------------------------------------------------------
# HTML export
# ---------------------------------------------------------------------------

def export_html(title: str, data: dict, output_path: str) -> None:
    """Export report data as a styled HTML page."""
    rows = _dict_to_html_rows(data)
    html = f"""<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{title} — sre-beacon</title>
<style>
  body {{ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
         margin: 0; padding: 20px; background: #0d1117; color: #c9d1d9; }}
  h1 {{ background: linear-gradient(135deg, #58a6ff, #3fb950);
       -webkit-background-clip: text; -webkit-text-fill-color: transparent;
       font-size: 1.8em; }}
  table {{ border-collapse: collapse; width: 100%; margin: 20px 0; }}
  th {{ background: #161b22; color: #58a6ff; text-align: left; padding: 10px; }}
  td {{ border-bottom: 1px solid #21262d; padding: 8px 10px; }}
  tr:hover {{ background: #161b22; }}
  .badge {{ padding: 2px 8px; border-radius: 4px; font-size: 0.85em; font-weight: 600; }}
  .badge-critical {{ background: #da3633; color: white; }}
  .badge-high {{ background: #d29922; color: white; }}
  .badge-medium {{ background: #e3b341; color: black; }}
  .badge-low {{ background: #58a6ff; color: white; }}
  .badge-info {{ background: #484f58; color: white; }}
  footer {{ margin-top: 40px; color: #484f58; font-size: 0.85em; }}
</style>
</head>
<body>
<h1>📡 {title}</h1>
<p>Generated by <strong>sre-beacon</strong></p>
<table>
<tr><th>Key</th><th>Value</th></tr>
{rows}
</table>
<footer>sre-beacon v1.0.0</footer>
</body>
</html>"""
    with open(output_path, "w", encoding="utf-8") as fh:
        fh.write(html)


# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------

def _json_default(obj: Any) -> Any:
    if isinstance(obj, timedelta):
        return obj.total_seconds()
    if hasattr(obj, "value"):
        return obj.value
    if isinstance(obj, float) and math.isinf(obj):
        return "inf"
    raise TypeError(f"Object of type {type(obj)} is not JSON serializable")


def _dict_to_html_rows(data: dict, prefix: str = "") -> str:
    rows = []
    for key, value in data.items():
        full_key = f"{prefix}.{key}" if prefix else key
        if isinstance(value, dict):
            rows.append(_dict_to_html_rows(value, full_key))
        elif isinstance(value, list):
            for i, item in enumerate(value):
                if isinstance(item, dict):
                    rows.append(_dict_to_html_rows(item, f"{full_key}[{i}]"))
                else:
                    rows.append(f"<tr><td>{full_key}[{i}]</td><td>{_escape(item)}</td></tr>")
        else:
            rows.append(f"<tr><td>{full_key}</td><td>{_escape(value)}</td></tr>")
    return "\n".join(rows)


def _escape(value: Any) -> str:
    s = str(value)
    return s.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
