"""Rich terminal reporter for all sre-beacon outputs."""

from __future__ import annotations

import math
from datetime import timedelta
from typing import List, Optional

from rich.console import Console
from rich.panel import Panel
from rich.table import Table
from rich.text import Text

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

console = Console()

_SEV_COLORS = {
    AlertIssueSeverity.CRITICAL: "red",
    AlertIssueSeverity.HIGH: "dark_orange",
    AlertIssueSeverity.MEDIUM: "yellow",
    AlertIssueSeverity.LOW: "cyan",
    AlertIssueSeverity.INFO: "dim",
}

_SEV_ICONS = {
    AlertIssueSeverity.CRITICAL: "🔴",
    AlertIssueSeverity.HIGH: "🟠",
    AlertIssueSeverity.MEDIUM: "🟡",
    AlertIssueSeverity.LOW: "🔵",
    AlertIssueSeverity.INFO: "⚪",
}

_MATURITY_COLORS = {
    MaturityLevel.INITIAL: "red",
    MaturityLevel.DEVELOPING: "dark_orange",
    MaturityLevel.DEFINED: "yellow",
    MaturityLevel.MANAGED: "green",
    MaturityLevel.OPTIMIZING: "bright_green",
}


# ---------------------------------------------------------------------------
# SLO Report
# ---------------------------------------------------------------------------

def print_slo_report(results: List[SLOResult], verbose: bool = False) -> None:
    """Print SLO compliance report."""
    console.print()
    console.print(Panel.fit(
        "[bold cyan]📊 SLO Compliance Report[/bold cyan]",
        border_style="cyan",
    ))

    table = Table(show_header=True, header_style="bold")
    table.add_column("SLO", style="white", min_width=20)
    table.add_column("Service", style="dim")
    table.add_column("Target", justify="right")
    table.add_column("Actual", justify="right")
    table.add_column("Status", justify="center")
    table.add_column("Budget Left", justify="right")
    table.add_column("Burn Rate", justify="right")

    compliant_count = 0
    for r in results:
        status = "[green]✅ PASS[/green]" if r.compliant else "[red]❌ FAIL[/red]"
        if r.compliant:
            compliant_count += 1

        budget_color = "green" if r.error_budget_remaining_pct > 50 else \
                       "yellow" if r.error_budget_remaining_pct > 20 else "red"

        burn_display = f"{r.burn_rate:.1f}x" if r.burn_rate > 0 else "—"
        burn_color = "green" if r.burn_rate <= 1.0 else \
                     "yellow" if r.burn_rate <= 2.0 else "red"

        table.add_row(
            r.slo.name,
            r.slo.service,
            f"{r.slo.target:.2f}%",
            f"{r.actual:.2f}%",
            status,
            f"[{budget_color}]{r.error_budget_remaining_pct:.1f}%[/{budget_color}]",
            f"[{burn_color}]{burn_display}[/{burn_color}]",
        )

    console.print(table)

    # Summary
    total = len(results)
    pct = (compliant_count / total * 100) if total else 0
    color = "green" if pct >= 80 else "yellow" if pct >= 50 else "red"
    console.print(f"\n  [{color}]{compliant_count}/{total} SLOs compliant ({pct:.0f}%)[/{color}]")

    if verbose:
        console.print("\n  [bold]Error Budget Details:[/bold]")
        for r in results:
            budget_min = r.error_budget_total_minutes
            consumed = r.error_budget_consumed_minutes
            remaining = budget_min - consumed
            console.print(
                f"    {r.slo.name}: "
                f"Budget={budget_min:.0f}min, "
                f"Consumed={consumed:.0f}min, "
                f"Remaining={remaining:.0f}min"
            )

    console.print()


# ---------------------------------------------------------------------------
# Availability Report
# ---------------------------------------------------------------------------

def print_availability_report(results: List[AvailabilityResult], verbose: bool = False) -> None:
    """Print availability calculation results."""
    console.print()
    console.print(Panel.fit(
        "[bold cyan]⏱️  Availability Report[/bold cyan]",
        border_style="cyan",
    ))

    for r in results:
        nines_display = f"{r.nines:.2f}" if not math.isinf(r.nines) else "∞"
        avail_color = "green" if r.availability_pct >= 99.9 else \
                      "yellow" if r.availability_pct >= 99.0 else "red"

        console.print(f"\n  [bold]{r.service}[/bold] ({r.period})")
        console.print(f"    Availability: [{avail_color}]{r.availability_pct:.4f}%[/{avail_color}]")
        console.print(f"    Nines:        {nines_display}")
        console.print(f"    Uptime:       {r.uptime_minutes:.0f} min")
        console.print(f"    Downtime:     {r.downtime_minutes:.0f} min")

        if verbose and r.allowed_downtime_by_nines:
            console.print("\n    [bold]Nines Comparison:[/bold]")
            table = Table(show_header=True, header_style="bold dim", padding=(0, 1))
            table.add_column("Level")
            table.add_column("Allowed Downtime", justify="right")
            table.add_column("Status", justify="center")
            for _n, info in sorted(r.allowed_downtime_by_nines.items()):
                status = "[green]✅ Meets[/green]" if info["meets"] else "[red]❌ Exceeds[/red]"
                table.add_row(
                    info["label"],
                    f"{info['allowed_downtime_min']:.1f} min",
                    status,
                )
            console.print(table)

    console.print()


# ---------------------------------------------------------------------------
# Incident Report
# ---------------------------------------------------------------------------

def print_incident_report(metrics: IncidentMetrics, verbose: bool = False) -> None:
    """Print incident analysis metrics."""
    console.print()
    console.print(Panel.fit(
        "[bold cyan]🚨 Incident Analysis Report[/bold cyan]",
        border_style="cyan",
    ))

    console.print(f"\n  Total Incidents:    {metrics.total_incidents}")
    console.print(f"  P1/P2 Incidents:    {metrics.p1_p2_count}")
    console.print(f"  MTTR:               {_fmt_td(metrics.mttr)}")
    console.print(f"  MTTA:               {_fmt_td(metrics.mtta)}")
    console.print(f"  MTBF:               {_fmt_td(metrics.mtbf)}")
    console.print(f"  Action Items:       {metrics.incidents_with_action_items_pct:.0f}% of incidents")

    if metrics.by_severity:
        console.print("\n  [bold]By Severity:[/bold]")
        table = Table(show_header=True, header_style="bold dim", padding=(0, 1))
        table.add_column("Severity")
        table.add_column("Count", justify="right")
        table.add_column("Avg TTR", justify="right")
        for sev in ["P1", "P2", "P3", "P4"]:
            if sev in metrics.by_severity:
                data = metrics.by_severity[sev]
                color = "red" if sev == "P1" else "dark_orange" if sev == "P2" else "yellow" if sev == "P3" else "dim"
                table.add_row(
                    f"[{color}]{sev}[/{color}]",
                    str(data["count"]),
                    _fmt_td(data.get("avg_ttr")),
                )
        console.print(table)

    if verbose and metrics.by_service:
        console.print("\n  [bold]By Service:[/bold]")
        table = Table(show_header=True, header_style="bold dim", padding=(0, 1))
        table.add_column("Service")
        table.add_column("Total", justify="right")
        table.add_column("P1/P2", justify="right")
        for svc, data in sorted(metrics.by_service.items(), key=lambda x: -x[1]["count"]):
            table.add_row(svc, str(data["count"]), str(data["p1_p2"]))
        console.print(table)

    console.print()


# ---------------------------------------------------------------------------
# Toil Report
# ---------------------------------------------------------------------------

def print_toil_report(report: ToilReport, verbose: bool = False) -> None:
    """Print toil analysis report."""
    console.print()
    console.print(Panel.fit(
        "[bold cyan]⚙️  Toil Analysis Report[/bold cyan]",
        border_style="cyan",
    ))

    pct_color = "green" if report.toil_percentage <= 15 else \
                "yellow" if report.toil_percentage <= 30 else "red"

    console.print(f"\n  Total Toil:            {report.total_toil_hours_per_month:.1f} hours/month")
    console.print(f"  Toil Percentage:       [{pct_color}]{report.toil_percentage:.1f}%[/{pct_color}] of engineering time")
    console.print(f"  Automatable:           {report.automatable_hours_per_month:.1f} hours/month ({report.automation_potential_pct:.0f}%)")
    console.print(f"  Engineering Budget:    {report.engineering_hours_per_month:.0f} hours/month")

    if report.by_category:
        console.print("\n  [bold]By Category:[/bold]")
        table = Table(show_header=True, header_style="bold dim", padding=(0, 1))
        table.add_column("Category")
        table.add_column("Hours/mo", justify="right")
        table.add_column("Tasks", justify="right")
        table.add_column("Automatable", justify="right")
        for cat, data in sorted(report.by_category.items(), key=lambda x: -x[1]["hours"]):
            table.add_row(
                cat,
                f"{data['hours']:.1f}",
                str(data["tasks"]),
                f"{data['automatable_hours']:.1f}h",
            )
        console.print(table)

    if verbose:
        console.print("\n  [bold]All Tasks:[/bold]")
        table = Table(show_header=True, header_style="bold dim", padding=(0, 1))
        table.add_column("Task")
        table.add_column("Frequency")
        table.add_column("Duration", justify="right")
        table.add_column("Automatable", justify="center")
        table.add_column("Category")
        for task in report.tasks:
            auto = "[green]Yes[/green]" if task.automatable else "[red]No[/red]"
            table.add_row(
                task.name,
                task.frequency.value,
                f"{task.duration_minutes}m",
                auto,
                task.category,
            )
        console.print(table)

    console.print()


# ---------------------------------------------------------------------------
# Alert Audit Report
# ---------------------------------------------------------------------------

def print_alert_audit_report(report: AlertAuditReport, verbose: bool = False) -> None:
    """Print alert rule audit report."""
    console.print()
    console.print(Panel.fit(
        "[bold cyan]🔔 Alert Rule Audit Report[/bold cyan]",
        border_style="cyan",
    ))

    grade_color = "green" if report.grade in ("A+", "A") else \
                  "yellow" if report.grade in ("B", "C") else "red"

    console.print(f"\n  Total Alert Rules:  {report.total_rules}")
    console.print(f"  Grade:              [{grade_color}]{report.grade}[/{grade_color}]  ({report.score}/100)")
    console.print(f"\n  Issue Summary:")
    console.print(f"    {_SEV_ICONS[AlertIssueSeverity.CRITICAL]} CRITICAL:  {report.critical_count}")
    console.print(f"    {_SEV_ICONS[AlertIssueSeverity.HIGH]}     HIGH:  {report.high_count}")
    console.print(f"    {_SEV_ICONS[AlertIssueSeverity.MEDIUM]}   MEDIUM:  {report.medium_count}")
    console.print(f"    {_SEV_ICONS[AlertIssueSeverity.LOW]}      LOW:  {report.low_count}")
    console.print(f"    {_SEV_ICONS[AlertIssueSeverity.INFO]}     INFO:  {report.info_count}")

    console.print(f"\n  Quick Stats:")
    console.print(f"    Without runbook:   {report.rules_without_runbook}")
    console.print(f"    Without severity:  {report.rules_without_severity}")
    console.print(f"    Without 'for':     {report.rules_without_for}")
    if report.duplicate_names:
        console.print(f"    Duplicate names:   {', '.join(report.duplicate_names)}")

    if verbose and report.issues:
        console.print("\n  [bold]Issues:[/bold]")
        table = Table(show_header=True, header_style="bold dim", padding=(0, 1))
        table.add_column("Rule", style="dim", width=14)
        table.add_column("Sev", width=10)
        table.add_column("Alert")
        table.add_column("Message")
        for issue in report.issues:
            color = _SEV_COLORS.get(issue.severity, "white")
            table.add_row(
                issue.rule_id,
                f"[{color}]{issue.severity.value}[/{color}]",
                issue.alert_name,
                issue.message,
            )
        console.print(table)

    console.print()


# ---------------------------------------------------------------------------
# Maturity Report
# ---------------------------------------------------------------------------

def print_maturity_report(report: MaturityReport, verbose: bool = False) -> None:
    """Print SRE maturity assessment."""
    console.print()
    console.print(Panel.fit(
        "[bold cyan]📈 SRE Maturity Assessment[/bold cyan]",
        border_style="cyan",
    ))

    level_color = _MATURITY_COLORS.get(report.overall_level, "white")
    console.print(f"\n  Overall Score:  [{level_color}]{report.overall_score:.1f}/5.0[/{level_color}]")
    console.print(f"  Overall Level:  [{level_color}]{report.overall_level.value}[/{level_color}]")

    # Dimension table
    console.print("\n  [bold]Dimensions:[/bold]")
    table = Table(show_header=True, header_style="bold dim", padding=(0, 1))
    table.add_column("Dimension", min_width=25)
    table.add_column("Score", justify="right", width=8)
    table.add_column("Level", width=14)
    table.add_column("Bar", width=20)

    for dim in report.dimensions:
        color = _MATURITY_COLORS.get(dim.level, "white")
        bar = _make_bar(dim.score, 5.0)
        table.add_row(
            dim.name,
            f"[{color}]{dim.score:.1f}[/{color}]",
            f"[{color}]{dim.level.value}[/{color}]",
            bar,
        )
    console.print(table)

    # Weakest / strongest
    if report.weakest_dimension and report.strongest_dimension:
        console.print(f"\n  ✅ Strongest: {report.strongest_dimension.name} ({report.strongest_dimension.score:.1f})")
        console.print(f"  ⚠️  Weakest:   {report.weakest_dimension.name} ({report.weakest_dimension.score:.1f})")

    if verbose:
        for dim in report.dimensions:
            console.print(f"\n  [bold]{dim.name}[/bold] — {dim.level.value} ({dim.score:.1f}/5)")
            if dim.findings:
                for f in dim.findings:
                    console.print(f"    [green]✓[/green] {f}")
            if dim.recommendations:
                for r in dim.recommendations:
                    console.print(f"    [yellow]→[/yellow] {r}")

    console.print()


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

def _fmt_td(td: Optional[timedelta]) -> str:
    if td is None:
        return "N/A"
    total_seconds = int(td.total_seconds())
    if total_seconds < 60:
        return f"{total_seconds}s"
    if total_seconds < 3600:
        return f"{total_seconds // 60}m {total_seconds % 60}s"
    hours = total_seconds // 3600
    minutes = (total_seconds % 3600) // 60
    if hours < 24:
        return f"{hours}h {minutes}m"
    days = hours // 24
    hours = hours % 24
    return f"{days}d {hours}h {minutes}m"


def _make_bar(value: float, max_value: float, width: int = 20) -> str:
    filled = int((value / max_value) * width) if max_value > 0 else 0
    bar = "█" * filled + "░" * (width - filled)
    return bar
