"""Rich-formatted validation compliance report."""

from __future__ import annotations

from typing import Any

from rich.table import Table

from hatchdx.utils.console import console
from hatchdx.validator.models import ValidationReport, ValidationResult

# Display order for categories.
_CATEGORY_ORDER = [
    "naming",
    "schema",
    "annotations",
    "errors",
    "response",
    "pagination",
]

# Display labels for categories.
_CATEGORY_LABELS = {
    "naming": "Naming Conventions",
    "schema": "Schema Validation",
    "annotations": "Tool Annotations",
    "errors": "Error Handling",
    "response": "Response Format",
    "pagination": "Pagination",
}

# Severity sort order (errors first).
_SEVERITY_ORDER = {"error": 0, "warning": 1, "info": 2}

# Severity display styles.
_SEVERITY_STYLES = {
    "error": ("[bold red]", "ERROR"),
    "warning": ("[bold yellow]", "WARN"),
    "info": ("[bold blue]", "INFO"),
}


def _severity_icon(severity: str, passed: bool) -> str:
    """Return a styled icon for the result."""
    if passed:
        return "[green]\\[PASS][/]"
    style, label = _SEVERITY_STYLES.get(severity, ("[dim]", "?"))
    return f"{style}\\[{label}][/]"


def _group_by_category(
    results: list[ValidationResult],
) -> dict[str, list[ValidationResult]]:
    """Group results by their rule category, maintaining category order."""
    groups: dict[str, list[ValidationResult]] = {}
    for cat in _CATEGORY_ORDER:
        groups[cat] = []

    for result in results:
        category = result.rule.category
        if category not in groups:
            groups[category] = []
        groups[category].append(result)

    return groups


def _sort_by_severity(results: list[ValidationResult]) -> list[ValidationResult]:
    """Sort results: failures first (by severity), then passes."""
    def sort_key(r: ValidationResult) -> tuple[int, int, str]:
        # Failed results come before passed ones.
        passed_order = 0 if not r.passed else 1
        severity_order = _SEVERITY_ORDER.get(r.rule.severity, 99)
        return (passed_order, severity_order, r.rule.name)

    return sorted(results, key=sort_key)


def report_validation(
    report: ValidationReport,
    *,
    verbose: bool = False,
    min_severity: str | None = None,
) -> int:
    """Print a compliance report and return the exit code.

    Returns 0 if no errors, 1 if any error-severity rules failed.
    Warnings do not cause a non-zero exit code.
    """
    # Filter by minimum severity if requested.
    severity_threshold = _SEVERITY_ORDER.get(min_severity, 99) if min_severity else 99
    filtered_results = [
        r for r in report.results
        if _SEVERITY_ORDER.get(r.rule.severity, 99) <= severity_threshold
    ]

    # Header
    console.print()
    console.print(f"[bold]Validation Report: {report.server_name}[/]")
    console.print(f"[dim]Tools checked: {report.tools_checked}[/]")
    console.print()

    grouped = _group_by_category(filtered_results)

    for category in _CATEGORY_ORDER:
        category_results = grouped.get(category, [])
        if not category_results:
            continue

        sorted_results = _sort_by_severity(category_results)

        # In non-verbose mode, skip categories where everything passed.
        if not verbose and all(r.passed for r in sorted_results):
            continue

        label = _CATEGORY_LABELS.get(category, category.title())
        table = Table(
            title=f"[bold]{label}[/]",
            show_edge=False,
            pad_edge=False,
            title_justify="left",
        )
        table.add_column("Status", width=8, justify="center")
        table.add_column("Rule", style="bold", min_width=20)
        table.add_column("Tool", style="cyan", min_width=10)
        table.add_column("Details", style="dim")

        for result in sorted_results:
            # In non-verbose mode, hide passing results.
            if not verbose and result.passed:
                continue

            icon = _severity_icon(result.rule.severity, result.passed)
            tool = result.tool_name or "-"
            # Truncate long messages for the table.
            message = result.message
            if len(message) > 80:
                message = message[:77] + "..."

            table.add_row(icon, result.rule.name, tool, message)

        console.print(table)
        console.print()

    # Summary line
    passed = report.passed_count
    errors = report.error_count
    warnings = report.warning_count
    infos = report.info_count

    parts = [f"[green]{passed} passed[/]"]
    if warnings:
        parts.append(f"[yellow]{warnings} warning{'s' if warnings != 1 else ''}[/]")
    if errors:
        parts.append(f"[red]{errors} error{'s' if errors != 1 else ''}[/]")
    if infos:
        parts.append(f"[blue]{infos} info[/]")

    summary = "  ".join(parts)
    console.print(f"[bold]Summary:[/] {summary}")
    console.print()

    return 1 if report.has_errors else 0


def report_validation_json(report: ValidationReport) -> dict[str, Any]:
    """Return the validation report as a JSON-serializable dict."""
    return {
        "server_name": report.server_name,
        "tools_checked": report.tools_checked,
        "timestamp": report.timestamp.isoformat(),
        "summary": {
            "passed": report.passed_count,
            "errors": report.error_count,
            "warnings": report.warning_count,
            "info": report.info_count,
            "total": len(report.results),
        },
        "results": [
            {
                "rule": r.rule.name,
                "category": r.rule.category,
                "severity": r.rule.severity,
                "passed": r.passed,
                "message": r.message,
                "tool_name": r.tool_name,
            }
            for r in report.results
        ],
    }
