"""Output formatters for MCP Security Audit results.

Provides text (terminal) and JSON output formats.
"""

from __future__ import annotations

import json
from typing import Any

from .colors import (
    BOLD, CYAN, DIM, GRAY, GREEN, RED, WHITE, YELLOW,
    c, grade_color, severity_color,
)
from .models import Finding, ScanResult, ScanSummary, Severity


def format_text(
    results: list[ScanResult],
    show_remediation: bool = False,
) -> str:
    """Format scan results as human-readable terminal output.

    Args:
        results: List of scan results to format.
        show_remediation: If True, include remediation guidance per finding.

    Returns:
        Formatted string with findings, scores, and summary.
    """
    output: list[str] = []
    total_findings = sum(len(r.findings) for r in results)
    total_lines = sum(r.lines_scanned for r in results)

    separator = c("=" * 60, DIM)
    output.append(f"\n{separator}")
    output.append(c("  MCP Security Audit — Results", BOLD, WHITE))
    output.append(separator)
    output.append(f"  Files scanned: {c(str(len(results)), BOLD, CYAN)}")
    output.append(f"  Lines scanned: {c(f'{total_lines:,}', BOLD, CYAN)}")
    findings_color = GREEN if total_findings == 0 else RED if total_findings > 5 else YELLOW
    output.append(f"  Total findings: {c(str(total_findings), BOLD, findings_color)}")
    output.append(f"{separator}\n")

    for result in results:
        if not result.findings:
            output.append(
                f"  {c('[OK]', BOLD, GREEN)} {result.file} — "
                f"Grade: {c(result.grade, BOLD, GREEN)} (0 findings)"
            )
            continue

        output.append(f"\n  {c('[FILE]', BOLD, WHITE)} {c(result.file, BOLD, CYAN)}")
        g_color = grade_color(result.grade)
        output.append(
            f"     Grade: {c(result.grade, BOLD, g_color)} | "
            f"{c(str(len(result.findings)), BOLD)} findings | "
            f"{c(f'{result.scan_time_ms:.1f}ms', DIM)}\n"
        )

        severity_order = list(Severity)
        sorted_findings = sorted(
            result.findings,
            key=lambda x: severity_order.index(x.severity),
        )
        for f in sorted_findings:
            sev_val = f.severity.value
            sev_c = severity_color(sev_val)
            icon = _severity_icon(f.severity)

            confidence_tag = ""
            if f.confidence:
                confidence_tag = f" {c(f'[{f.confidence}]', DIM)}"

            output.append(
                f"     {c(icon, BOLD, sev_c)} "
                f"{c(f'[{f.rule_id}]', BOLD, sev_c)} "
                f"{c(f.title, BOLD)} "
                f"{c(f'[{sev_val}]', sev_c)}"
                f"{confidence_tag}"
            )
            output.append(
                f"       {c('Line', DIM)} {c(str(f.line), BOLD, WHITE)}: {f.description}"
            )
            if f.code_snippet:
                output.append(f"       {c('Code:', DIM)} {c(f.code_snippet, GRAY)}")
            if f.recommendation:
                output.append(f"       {c('Fix:', DIM, GREEN)} {c(f.recommendation, GREEN)}")
            if show_remediation and f.remediation:
                output.append(f"       {c('Remediation:', DIM)} {f.remediation}")
            output.append("")

    output.append(separator)
    return "\n".join(output)


def format_json(results: list[ScanResult]) -> str:
    """Format scan results as JSON for CI/CD integration.

    Args:
        results: List of scan results to format.

    Returns:
        JSON string with findings and summary.
    """
    summary = ScanSummary(results=results)
    return json.dumps(summary.to_dict(), indent=2, ensure_ascii=False)


def format_summary_text(
    summary: ScanSummary,
    show_remediation: bool = False,
) -> str:
    """Format a ScanSummary as human-readable text.

    Args:
        summary: Aggregate scan summary.
        show_remediation: If True, include remediation guidance per finding.

    Returns:
        Formatted summary string.
    """
    return format_text(summary.results, show_remediation=show_remediation)


def format_summary_json(summary: ScanSummary) -> str:
    """Format a ScanSummary as JSON.

    Args:
        summary: Aggregate scan summary.

    Returns:
        JSON string with full summary.
    """
    return json.dumps(summary.to_dict(), indent=2, ensure_ascii=False)


def _severity_icon(severity: Severity) -> str:
    """Get a plain-text icon for a severity level.

    Args:
        severity: The severity level.

    Returns:
        Icon string for terminal output.
    """
    icons: dict[Severity, str] = {
        Severity.CRITICAL: "[!!]",
        Severity.HIGH: "[!]",
        Severity.MEDIUM: "[-]",
        Severity.LOW: "[.]",
        Severity.INFO: "[i]",
    }
    return icons.get(severity, "[?]")
