"""CLI entry point for sre-beacon."""

from __future__ import annotations

import os
import sys

import click
from rich.console import Console

from sre_beacon import __version__
from sre_beacon.analyzers.alert_analyzer import ALERT_RULES

console = Console()


@click.group()
@click.version_option(__version__, prog_name="sre-beacon")
def main():
    """📡 sre-beacon — SRE Metrics Calculator & Reliability Analyzer."""


# ---------------------------------------------------------------------------
# slo command
# ---------------------------------------------------------------------------

@main.command()
@click.argument("slo_path", type=click.Path(exists=True))
@click.argument("actuals_path", type=click.Path(exists=True))
@click.option("-v", "--verbose", is_flag=True, help="Show detailed error-budget breakdown.")
@click.option("-f", "--format", "fmt", type=click.Choice(["terminal", "json", "html"]), default="terminal")
@click.option("-o", "--output", "output_path", type=click.Path(), help="Output file path.")
def slo(slo_path: str, actuals_path: str, verbose: bool, fmt: str, output_path: str):
    """Calculate SLO compliance and error budgets.

    SLO_PATH: YAML file with SLO definitions.
    ACTUALS_PATH: YAML file with actual measured values.
    """
    from sre_beacon.calculators.slo_calculator import calculate_slos_from_yaml
    from sre_beacon.reporters.terminal_reporter import print_slo_report
    from sre_beacon.reporters.export_reporter import export_json, export_html, slo_results_to_dict

    results = calculate_slos_from_yaml(slo_path, actuals_path)
    if not results:
        console.print("[yellow]No matching SLOs found.[/yellow]")
        return

    if fmt == "terminal":
        print_slo_report(results, verbose=verbose)
    else:
        data = slo_results_to_dict(results)
        if fmt == "json":
            path = output_path or "slo-report.json"
            export_json(data, path)
            console.print(f"[green]JSON report saved to {path}[/green]")
        elif fmt == "html":
            path = output_path or "slo-report.html"
            export_html("SLO Compliance Report", data, path)
            console.print(f"[green]HTML report saved to {path}[/green]")


# ---------------------------------------------------------------------------
# availability command
# ---------------------------------------------------------------------------

@main.command()
@click.argument("path", type=click.Path(exists=True))
@click.option("-v", "--verbose", is_flag=True, help="Show nines comparison table.")
@click.option("-f", "--format", "fmt", type=click.Choice(["terminal", "json", "html"]), default="terminal")
@click.option("-o", "--output", "output_path", type=click.Path(), help="Output file path.")
def availability(path: str, verbose: bool, fmt: str, output_path: str):
    """Calculate service availability and nines.

    PATH: YAML file with service uptime data.
    """
    import yaml
    from sre_beacon.models import AvailabilityInput
    from sre_beacon.calculators.availability_calculator import calculate_availability
    from sre_beacon.reporters.terminal_reporter import print_availability_report
    from sre_beacon.reporters.export_reporter import export_json, export_html, availability_results_to_dict

    with open(path, "r", encoding="utf-8") as fh:
        data = yaml.safe_load(fh)

    inputs = []
    for svc in data.get("services", []):
        inputs.append(AvailabilityInput(
            service=svc["name"],
            total_minutes=float(svc["total_minutes"]),
            downtime_minutes=float(svc["downtime_minutes"]),
            period=svc.get("period", "30 days"),
        ))

    results = [calculate_availability(inp) for inp in inputs]

    if fmt == "terminal":
        print_availability_report(results, verbose=verbose)
    else:
        out_data = availability_results_to_dict(results)
        if fmt == "json":
            p = output_path or "availability-report.json"
            export_json(out_data, p)
            console.print(f"[green]JSON report saved to {p}[/green]")
        elif fmt == "html":
            p = output_path or "availability-report.html"
            export_html("Availability Report", out_data, p)
            console.print(f"[green]HTML report saved to {p}[/green]")


# ---------------------------------------------------------------------------
# incidents command
# ---------------------------------------------------------------------------

@main.command()
@click.argument("path", type=click.Path(exists=True))
@click.option("-v", "--verbose", is_flag=True, help="Show per-service breakdown.")
@click.option("-f", "--format", "fmt", type=click.Choice(["terminal", "json", "html"]), default="terminal")
@click.option("-o", "--output", "output_path", type=click.Path(), help="Output file path.")
def incidents(path: str, verbose: bool, fmt: str, output_path: str):
    """Analyze incident data — MTTR, MTTA, MTBF.

    PATH: YAML file with incident records.
    """
    from sre_beacon.calculators.incident_calculator import load_incidents, calculate_incident_metrics
    from sre_beacon.reporters.terminal_reporter import print_incident_report
    from sre_beacon.reporters.export_reporter import export_json, export_html, incident_metrics_to_dict

    inc_list = load_incidents(path)
    metrics = calculate_incident_metrics(inc_list)

    if fmt == "terminal":
        print_incident_report(metrics, verbose=verbose)
    else:
        out_data = incident_metrics_to_dict(metrics)
        if fmt == "json":
            p = output_path or "incident-report.json"
            export_json(out_data, p)
            console.print(f"[green]JSON report saved to {p}[/green]")
        elif fmt == "html":
            p = output_path or "incident-report.html"
            export_html("Incident Analysis Report", out_data, p)
            console.print(f"[green]HTML report saved to {p}[/green]")


# ---------------------------------------------------------------------------
# toil command
# ---------------------------------------------------------------------------

@main.command()
@click.argument("path", type=click.Path(exists=True))
@click.option("-v", "--verbose", is_flag=True, help="Show all individual tasks.")
@click.option("-f", "--format", "fmt", type=click.Choice(["terminal", "json", "html"]), default="terminal")
@click.option("-o", "--output", "output_path", type=click.Path(), help="Output file path.")
@click.option("--hours", type=float, default=160, help="Engineering hours per month (default: 160).")
def toil(path: str, verbose: bool, fmt: str, output_path: str, hours: float):
    """Estimate toil from task definitions.

    PATH: YAML file with toil task descriptions.
    """
    import yaml
    from sre_beacon.calculators.toil_calculator import load_toil_tasks, calculate_toil
    from sre_beacon.reporters.terminal_reporter import print_toil_report
    from sre_beacon.reporters.export_reporter import export_json, export_html, toil_report_to_dict

    with open(path, "r", encoding="utf-8") as fh:
        data = yaml.safe_load(fh)

    eng_hours = data.get("engineering_hours_per_month", hours)
    tasks = load_toil_tasks(path)
    report = calculate_toil(tasks, engineering_hours_per_month=eng_hours)

    if fmt == "terminal":
        print_toil_report(report, verbose=verbose)
    else:
        out_data = toil_report_to_dict(report)
        if fmt == "json":
            p = output_path or "toil-report.json"
            export_json(out_data, p)
            console.print(f"[green]JSON report saved to {p}[/green]")
        elif fmt == "html":
            p = output_path or "toil-report.html"
            export_html("Toil Analysis Report", out_data, p)
            console.print(f"[green]HTML report saved to {p}[/green]")


# ---------------------------------------------------------------------------
# alerts command
# ---------------------------------------------------------------------------

@main.command()
@click.argument("path", type=click.Path(exists=True))
@click.option("-v", "--verbose", is_flag=True, help="Show all individual issues.")
@click.option("-f", "--format", "fmt", type=click.Choice(["terminal", "json", "html"]), default="terminal")
@click.option("-o", "--output", "output_path", type=click.Path(), help="Output file path.")
@click.option("--fail-on", type=click.Choice(["critical", "high", "medium", "low"]),
              help="Exit with code 1 if issues at this severity or above are found.")
def alerts(path: str, verbose: bool, fmt: str, output_path: str, fail_on: str):
    """Audit Prometheus/Alertmanager alert rules.

    PATH: YAML file with Prometheus alert rule groups.
    """
    from sre_beacon.analyzers.alert_analyzer import load_alert_rules, analyze_alert_rules
    from sre_beacon.reporters.terminal_reporter import print_alert_audit_report
    from sre_beacon.reporters.export_reporter import export_json, export_html, alert_audit_to_dict
    from sre_beacon.models import AlertIssueSeverity

    rules = load_alert_rules(path)
    report = analyze_alert_rules(rules)

    if fmt == "terminal":
        print_alert_audit_report(report, verbose=verbose)
    else:
        out_data = alert_audit_to_dict(report)
        if fmt == "json":
            p = output_path or "alert-audit.json"
            export_json(out_data, p)
            console.print(f"[green]JSON report saved to {p}[/green]")
        elif fmt == "html":
            p = output_path or "alert-audit.html"
            export_html("Alert Rule Audit", out_data, p)
            console.print(f"[green]HTML report saved to {p}[/green]")

    if fail_on:
        severity_order = ["critical", "high", "medium", "low"]
        threshold_idx = severity_order.index(fail_on)
        for issue in report.issues:
            issue_idx = severity_order.index(issue.severity.value.lower())
            if issue_idx <= threshold_idx:
                sys.exit(1)


# ---------------------------------------------------------------------------
# maturity command
# ---------------------------------------------------------------------------

@main.command()
@click.argument("path", type=click.Path(exists=True))
@click.option("-v", "--verbose", is_flag=True, help="Show findings and recommendations per dimension.")
@click.option("-f", "--format", "fmt", type=click.Choice(["terminal", "json", "html"]), default="terminal")
@click.option("-o", "--output", "output_path", type=click.Path(), help="Output file path.")
def maturity(path: str, verbose: bool, fmt: str, output_path: str):
    """Assess SRE maturity across 8 dimensions.

    PATH: YAML file with maturity assessment answers.
    """
    from sre_beacon.analyzers.maturity_analyzer import assess_maturity_from_file
    from sre_beacon.reporters.terminal_reporter import print_maturity_report
    from sre_beacon.reporters.export_reporter import export_json, export_html, maturity_report_to_dict

    report = assess_maturity_from_file(path)

    if fmt == "terminal":
        print_maturity_report(report, verbose=verbose)
    else:
        out_data = maturity_report_to_dict(report)
        if fmt == "json":
            p = output_path or "maturity-report.json"
            export_json(out_data, p)
            console.print(f"[green]JSON report saved to {p}[/green]")
        elif fmt == "html":
            p = output_path or "maturity-report.html"
            export_html("SRE Maturity Assessment", out_data, p)
            console.print(f"[green]HTML report saved to {p}[/green]")


# ---------------------------------------------------------------------------
# demo command
# ---------------------------------------------------------------------------

@main.command()
@click.option("-v", "--verbose", is_flag=True, help="Show verbose output for all reports.")
@click.option("-d", "--dir", "demo_dir", default="sre-beacon-demo", help="Directory for demo files.")
def demo(verbose: bool, demo_dir: str):
    """Run a full demo with sample SRE data."""
    from sre_beacon.demo import create_demo_data
    from sre_beacon.calculators.slo_calculator import calculate_slos_from_yaml
    from sre_beacon.calculators.incident_calculator import load_incidents, calculate_incident_metrics
    from sre_beacon.calculators.toil_calculator import load_toil_tasks, calculate_toil
    from sre_beacon.calculators.availability_calculator import calculate_availability
    from sre_beacon.analyzers.alert_analyzer import load_alert_rules, analyze_alert_rules
    from sre_beacon.analyzers.maturity_analyzer import assess_maturity_from_file
    from sre_beacon.reporters.terminal_reporter import (
        print_slo_report, print_availability_report, print_incident_report,
        print_toil_report, print_alert_audit_report, print_maturity_report,
    )
    from sre_beacon.models import AvailabilityInput

    import yaml

    console.print("\n[bold cyan]🎪 Creating demo SRE data...[/bold cyan]\n")
    paths = create_demo_data(demo_dir)
    console.print(f"  📁 Demo files created in [bold]{demo_dir}/[/bold]\n")

    # 1. SLO
    console.print("[bold]━━━ 1/6  SLO Compliance ━━━[/bold]")
    slo_results = calculate_slos_from_yaml(paths["slos"], paths["actuals"])
    print_slo_report(slo_results, verbose=verbose)

    # 2. Availability
    console.print("[bold]━━━ 2/6  Availability ━━━[/bold]")
    with open(paths["availability"], "r", encoding="utf-8") as fh:
        avail_data = yaml.safe_load(fh)
    avail_inputs = [
        AvailabilityInput(
            service=s["name"],
            total_minutes=float(s["total_minutes"]),
            downtime_minutes=float(s["downtime_minutes"]),
            period=s.get("period", "30 days"),
        )
        for s in avail_data.get("services", [])
    ]
    avail_results = [calculate_availability(inp) for inp in avail_inputs]
    print_availability_report(avail_results, verbose=verbose)

    # 3. Incidents
    console.print("[bold]━━━ 3/6  Incident Analysis ━━━[/bold]")
    inc_list = load_incidents(paths["incidents"])
    inc_metrics = calculate_incident_metrics(inc_list)
    print_incident_report(inc_metrics, verbose=verbose)

    # 4. Toil
    console.print("[bold]━━━ 4/6  Toil Analysis ━━━[/bold]")
    with open(paths["toil"], "r", encoding="utf-8") as fh:
        toil_data = yaml.safe_load(fh)
    toil_tasks = load_toil_tasks(paths["toil"])
    toil_report = calculate_toil(
        toil_tasks,
        engineering_hours_per_month=toil_data.get("engineering_hours_per_month", 160),
    )
    print_toil_report(toil_report, verbose=verbose)

    # 5. Alert Audit
    console.print("[bold]━━━ 5/6  Alert Rule Audit ━━━[/bold]")
    alert_rules = load_alert_rules(paths["alerts"])
    alert_report = analyze_alert_rules(alert_rules)
    print_alert_audit_report(alert_report, verbose=verbose)

    # 6. Maturity
    console.print("[bold]━━━ 6/6  SRE Maturity ━━━[/bold]")
    maturity_report = assess_maturity_from_file(paths["maturity"])
    print_maturity_report(maturity_report, verbose=verbose)

    console.print("[bold green]✅ Demo complete![/bold green]\n")


# ---------------------------------------------------------------------------
# rules command
# ---------------------------------------------------------------------------

@main.command()
def rules():
    """List all alert audit rules."""
    from rich.table import Table

    table = Table(title="sre-beacon Alert Audit Rules", show_header=True, header_style="bold cyan")
    table.add_column("Rule ID", style="dim", width=14)
    table.add_column("Severity", width=10)
    table.add_column("Description")

    for rule in ALERT_RULES:
        sev = rule["severity"]
        color = {"CRITICAL": "red", "HIGH": "dark_orange", "MEDIUM": "yellow",
                 "LOW": "cyan", "INFO": "dim"}.get(sev, "white")
        table.add_row(rule["id"], f"[{color}]{sev}[/{color}]", rule["description"])

    console.print()
    console.print(table)
    console.print(f"\n  Total: {len(ALERT_RULES)} rules\n")


if __name__ == "__main__":
    main()
