from __future__ import annotations

from pathlib import Path
from typing import List, Optional

import click

from bastion.models import DriftEvent, ScanResult

SEVERITY_COLORS = {
    "Critical": "red",
    "High": "yellow",
    "Medium": "cyan",
    "Low": "green",
}


def print_summary(scan_results: List[ScanResult], drift_events: Optional[List[DriftEvent]] = None) -> None:
    click.echo("")
    click.echo(click.style("═" * 60, fg="blue"))
    click.echo(click.style("  Bastion AI — Scan Summary", fg="blue", bold=True))
    click.echo(click.style("═" * 60, fg="blue"))
    click.echo("")

    if scan_results:
        click.echo(click.style(f"  Scan Timestamp: {scan_results[0].timestamp}", dim=True))
    click.echo(f"  Total Plugins Scanned: {len(scan_results)}")
    click.echo("")

    risk_counts = {"Critical": 0, "High": 0, "Medium": 0, "Low": 0}
    for result in scan_results:
        level = result.risk_level
        if level in risk_counts:
            risk_counts[level] += 1

    click.echo("  Risk Breakdown:")
    for level in ["Critical", "High", "Medium", "Low"]:
        count = risk_counts[level]
        color = SEVERITY_COLORS[level]
        label = click.style(f"  {level:>10}", fg=color, bold=(level in ("Critical", "High")))
        click.echo(f"  {label}: {count}")
    click.echo("")

    high_risk = [r for r in scan_results if r.risk_level in ("Critical", "High")]
    if high_risk:
        click.echo(click.style("  Top Findings:", bold=True))
        for result in high_risk[:5]:
            click.echo(click.style(f"    Plugin: {result.plugin_id}", fg=SEVERITY_COLORS.get(result.risk_level, "white")))
            click.echo(f"      Risk Level: {result.risk_level}")
            for cap in result.capabilities:
                click.echo(f"      - {cap.category} ({cap.severity}): {cap.description}")
                for ev in cap.evidence[:2]:
                    click.echo(click.style(f"        {ev.file}:{ev.line} [{ev.pattern_name}]", dim=True))
            click.echo("")

    if drift_events is not None and drift_events:
        click.echo(click.style("  Drift Summary:", bold=True))
        for event in drift_events:
            color = SEVERITY_COLORS.get(event.severity, "white")
            click.echo(click.style(f"    [{event.event_type.upper()}] {event.plugin_id} — {event.severity}", fg=color))
            for change in event.capability_changes[:3]:
                if isinstance(change, dict):
                    change_type = change.get("type", change.get("added", "change"))
                    category = change.get("category", "")
                    if isinstance(change_type, dict):
                        category = change_type.get("category", "")
                        change_type = "added"
                    click.echo(f"      {change_type}: {category}")
        click.echo("")
    elif drift_events is not None:
        click.echo(click.style("  No drift detected.", dim=True))
        click.echo("")

    click.echo(click.style("═" * 60, fg="blue"))
    click.echo("")


def generate_markdown_report(
    scan_results: List[ScanResult],
    drift_events: Optional[List[DriftEvent]],
    output_path: Path,
) -> None:
    lines: List[str] = []
    lines.append("# Bastion AI — Scan Report\n")

    if scan_results:
        lines.append(f"**Scan Timestamp:** {scan_results[0].timestamp}\n")
    lines.append(f"**Total Plugins Scanned:** {len(scan_results)}\n")

    risk_counts = {"Critical": 0, "High": 0, "Medium": 0, "Low": 0}
    for result in scan_results:
        level = result.risk_level
        if level in risk_counts:
            risk_counts[level] += 1

    lines.append("## Risk Breakdown\n")
    lines.append("| Severity | Count |")
    lines.append("|----------|-------|")
    for level in ["Critical", "High", "Medium", "Low"]:
        lines.append(f"| {level} | {risk_counts[level]} |")
    lines.append("")

    lines.append("## Findings\n")
    for result in scan_results:
        if not result.capabilities:
            continue
        lines.append(f"### Plugin: `{result.plugin_id}`\n")
        lines.append(f"**Risk Level:** {result.risk_level}\n")
        for cap in result.capabilities:
            lines.append(f"- **{cap.category}** ({cap.severity}): {cap.description}")
            for ev in cap.evidence:
                lines.append(f"  - `{ev.file}:{ev.line}` — {ev.pattern_name}")
                lines.append(f"    ```")
                lines.append(f"    {ev.code_snippet}")
                lines.append(f"    ```")
        lines.append("")

    if drift_events:
        lines.append("## Drift Events\n")
        for event in drift_events:
            lines.append(f"- **[{event.event_type.upper()}]** `{event.plugin_id}` — Severity: {event.severity}")
            for change in event.capability_changes:
                if isinstance(change, dict):
                    lines.append(f"  - {change}")
        lines.append("")

    with open(output_path, "w") as f:
        f.write("\n".join(lines))
