#!/usr/bin/env python3
"""
souleyez.ui.gap_analysis_view - Gap Analysis View

Displays comparison between Wazuh (passive) and scan (active)
vulnerability detection to identify gaps in coverage.
"""
import click
from rich.console import Console
from rich.table import Table
from rich.panel import Panel
from rich.text import Text
from typing import List, Dict
from souleyez.intelligence.gap_analyzer import GapAnalyzer, GapAnalysisResult
from souleyez.integrations.wazuh import WazuhConfig, WazuhVulnSync

console = Console()

# Severity colors
SEVERITY_COLORS = {
    'Critical': 'red bold',
    'High': 'yellow',
    'Medium': 'white',
    'Low': 'dim',
    'critical': 'red bold',
    'high': 'yellow',
    'medium': 'white',
    'low': 'dim'
}


def show_gap_analysis_view(engagement_id: int, engagement_name: str = "") -> None:
    """
    Display gap analysis view.

    Args:
        engagement_id: Current engagement ID
        engagement_name: Engagement name for display
    """
    while True:
        console.clear()
        width = console.size.width

        # Header
        console.print(Panel("Gap Analysis", style="bold cyan", width=min(width - 4, 60)))
        console.print("[dim]Compare Wazuh (passive) vs Scan (active) findings[/dim]\n")

        # Check if Wazuh is configured
        config = WazuhConfig.get_config(engagement_id)
        if not config or not config.get('enabled'):
            console.print(Panel(
                "[yellow]Wazuh is not configured for this engagement.[/yellow]\n\n"
                "Configure Wazuh in Settings → Integrations → Wazuh SIEM\n"
                "Then sync vulnerabilities before running gap analysis.",
                title="Not Configured",
                border_style="yellow"
            ))
            console.print("\n[dim]Press any key to return...[/dim]")
            click.getchar()
            return

        # Check sync status
        sync = WazuhVulnSync(engagement_id)
        sync_status = sync.get_sync_status()

        if not sync_status.get('synced'):
            console.print(Panel(
                "[yellow]No Wazuh data synced yet.[/yellow]\n\n"
                "Press [s] to sync vulnerabilities from Wazuh first.",
                title="Sync Required",
                border_style="yellow"
            ))
            console.print("\n[cyan][s][/cyan] Sync Now  [cyan][q][/cyan] Back")
            key = click.getchar().lower()
            if key == 's':
                _do_sync(engagement_id)
            elif key == 'q':
                return
            continue

        # Run gap analysis
        analyzer = GapAnalyzer(engagement_id)

        with console.status("[bold blue]Analyzing gaps..."):
            result = analyzer.analyze()
            stats = analyzer.get_coverage_stats()

        # Summary dashboard
        _render_summary_dashboard(result, stats, width)

        # Menu
        console.print("\n" + "─" * width)
        console.print(
            "[cyan][1][/cyan] Wazuh Only (scan missed)  "
            "[cyan][2][/cyan] Scan Only (Wazuh missed)  "
            "[cyan][3][/cyan] Confirmed (both)  "
            "[cyan][a][/cyan] Actionable Gaps  "
            "[cyan][s][/cyan] Re-sync  "
            "[cyan][q][/cyan] Back"
        )

        key = click.getchar().lower()

        if key == 'q':
            return
        elif key == '1':
            _show_wazuh_only(result, width)
        elif key == '2':
            _show_scan_only(result, width)
        elif key == '3':
            _show_confirmed(result, width)
        elif key == 'a':
            _show_actionable_gaps(engagement_id, width)
        elif key == 's':
            _do_sync(engagement_id)


def _render_summary_dashboard(result: GapAnalysisResult, stats: Dict, width: int) -> None:
    """Render the summary dashboard."""
    # Main stats box
    wazuh_total = result.wazuh_total
    scan_total = result.scan_total
    confirmed = len(result.confirmed)
    wazuh_only = len(result.wazuh_only)
    scan_only = len(result.scan_only)
    coverage = stats.get('coverage_pct', 0)

    # Coverage color
    if coverage >= 80:
        coverage_color = "green"
    elif coverage >= 50:
        coverage_color = "yellow"
    else:
        coverage_color = "red"

    summary_text = (
        f"[bold]Detection Sources[/bold]\n"
        f"  Wazuh (passive):  [cyan]{wazuh_total:>4}[/cyan] CVEs\n"
        f"  Scans (active):   [cyan]{scan_total:>4}[/cyan] CVEs\n\n"
        f"[bold]Analysis Results[/bold]\n"
        f"  [green]✓ Confirmed (both):[/green]     [bold]{confirmed:>4}[/bold]\n"
        f"  [yellow]⚠ Wazuh Only:[/yellow]           [bold]{wazuh_only:>4}[/bold]  ← Scans missed these\n"
        f"  [blue]○ Scan Only:[/blue]            [bold]{scan_only:>4}[/bold]  ← Wazuh missed these\n\n"
        f"[bold]Coverage:[/bold] [{coverage_color}]{coverage:.1f}%[/{coverage_color}] of Wazuh vulns confirmed by scans"
    )

    console.print(Panel(summary_text, title="Gap Analysis Summary", border_style="cyan", width=min(width - 4, 60)))

    # Severity breakdown
    sev_breakdown = stats.get('by_severity', {})
    if sev_breakdown.get('wazuh_only') or sev_breakdown.get('scan_only'):
        _render_severity_breakdown(sev_breakdown, width)


def _render_severity_breakdown(breakdown: Dict, width: int) -> None:
    """Render severity breakdown table."""
    table = Table(
        show_header=True,
        header_style="bold",
        box=None,
        padding=(0, 2),
        width=min(width - 4, 50)
    )

    table.add_column("Severity", width=10)
    table.add_column("Wazuh Only", width=12, justify="center")
    table.add_column("Scan Only", width=12, justify="center")
    table.add_column("Confirmed", width=12, justify="center")

    for sev in ['Critical', 'High', 'Medium', 'Low']:
        color = SEVERITY_COLORS.get(sev, 'white')
        wazuh_only = breakdown.get('wazuh_only', {}).get(sev, 0)
        scan_only = breakdown.get('scan_only', {}).get(sev, 0)
        confirmed = breakdown.get('confirmed', {}).get(sev, 0)

        table.add_row(
            f"[{color}]{sev}[/{color}]",
            str(wazuh_only) if wazuh_only else "-",
            str(scan_only) if scan_only else "-",
            str(confirmed) if confirmed else "-"
        )

    console.print(table)


def _show_wazuh_only(result: GapAnalysisResult, width: int) -> None:
    """Show vulnerabilities found only by Wazuh."""
    console.clear()
    console.print(Panel(
        f"[yellow]Wazuh Only - {len(result.wazuh_only)} CVEs[/yellow]\n"
        "These vulnerabilities were detected by Wazuh agents but NOT by active scans.\n"
        "They may be local/package vulnerabilities not exposed to network scanning.",
        title="Detection Gap: Scans Missed",
        border_style="yellow"
    ))

    if not result.wazuh_only:
        console.print("\n[green]No gaps - all Wazuh vulns confirmed by scans![/green]")
    else:
        _render_gaps_table(result.wazuh_only, width, show_package=True)

    console.print("\n[dim]Press any key to return...[/dim]")
    click.getchar()


def _show_scan_only(result: GapAnalysisResult, width: int) -> None:
    """Show vulnerabilities found only by scans."""
    console.clear()
    console.print(Panel(
        f"[blue]Scan Only - {len(result.scan_only)} CVEs[/blue]\n"
        "These vulnerabilities were detected by active scans but NOT by Wazuh.\n"
        "This may indicate: missing Wazuh agent, detection rule gap, or network-only vuln.",
        title="Detection Gap: Wazuh Missed",
        border_style="blue"
    ))

    if not result.scan_only:
        console.print("\n[green]No gaps - Wazuh detected all scan findings![/green]")
    else:
        _render_gaps_table(result.scan_only, width, show_tool=True)

    console.print("\n[dim]Press any key to return...[/dim]")
    click.getchar()


def _show_confirmed(result: GapAnalysisResult, width: int) -> None:
    """Show vulnerabilities confirmed by both sources."""
    console.clear()
    console.print(Panel(
        f"[green]Confirmed - {len(result.confirmed)} CVEs[/green]\n"
        "These vulnerabilities were detected by BOTH Wazuh and active scans.\n"
        "High confidence - prioritize these for exploitation.",
        title="Confirmed Vulnerabilities",
        border_style="green"
    ))

    if not result.confirmed:
        console.print("\n[yellow]No confirmed matches between Wazuh and scans.[/yellow]")
    else:
        _render_gaps_table(result.confirmed, width, show_both=True)

    console.print("\n[dim]Press any key to return...[/dim]")
    click.getchar()


def _show_actionable_gaps(engagement_id: int, width: int) -> None:
    """Show actionable gaps with recommendations."""
    console.clear()

    analyzer = GapAnalyzer(engagement_id)
    gaps = analyzer.get_actionable_gaps(limit=20)

    console.print(Panel(
        f"[yellow]Actionable Gaps - Top {len(gaps)} CVEs[/yellow]\n"
        "Prioritized vulnerabilities from Wazuh that need targeted scanning.",
        title="Action Required",
        border_style="yellow"
    ))

    if not gaps:
        console.print("\n[green]No actionable gaps - great scan coverage![/green]")
    else:
        table = Table(
            show_header=True,
            header_style="bold cyan",
            box=None,
            padding=(0, 1),
            width=min(width - 4, 120)
        )

        table.add_column("#", width=3, style="dim")
        table.add_column("PRIORITY", width=8)
        table.add_column("CVE", width=18)
        table.add_column("SEVERITY", width=10)
        table.add_column("HOST", width=15)
        table.add_column("PACKAGE", width=20)
        table.add_column("RECOMMENDATION", width=40)

        for idx, gap in enumerate(gaps, 1):
            priority = gap.get('priority', 'medium')
            priority_display = "[red]HIGH[/red]" if priority == 'high' else "[yellow]MEDIUM[/yellow]"

            severity = gap.get('severity', 'Medium')
            sev_color = SEVERITY_COLORS.get(severity, 'white')

            table.add_row(
                str(idx),
                priority_display,
                gap.get('cve_id', '-'),
                f"[{sev_color}]{severity}[/{sev_color}]",
                gap.get('host_ip', '-'),
                gap.get('package', '-')[:19],
                gap.get('recommendation', '-')[:39]
            )

        console.print(table)

    console.print("\n[dim]Press any key to return...[/dim]")
    click.getchar()


def _render_gaps_table(gaps: List, width: int, show_package: bool = False, show_tool: bool = False, show_both: bool = False) -> None:
    """Render gaps table."""
    table = Table(
        show_header=True,
        header_style="bold cyan",
        box=None,
        padding=(0, 1),
        width=min(width - 4, 120)
    )

    table.add_column("#", width=3, style="dim")
    table.add_column("CVE", width=18)
    table.add_column("SEVERITY", width=10)
    table.add_column("HOST", width=15)

    if show_package:
        table.add_column("PACKAGE", width=25)
        table.add_column("RECOMMENDATION", width=35)
    elif show_tool:
        table.add_column("TOOL", width=15)
        table.add_column("RECOMMENDATION", width=40)
    elif show_both:
        table.add_column("PACKAGE", width=20)
        table.add_column("SCAN TOOL", width=15)
        table.add_column("CONFIDENCE", width=10)

    for idx, gap in enumerate(gaps[:30], 1):
        severity = gap.severity
        sev_color = SEVERITY_COLORS.get(severity, 'white')

        row = [
            str(idx),
            gap.cve_id,
            f"[{sev_color}]{severity}[/{sev_color}]",
            gap.host_ip or "-"
        ]

        if show_package:
            package = gap.wazuh_details.get('package_name', '-') if gap.wazuh_details else '-'
            row.append(package[:24])
            row.append(gap.recommendation[:34])
        elif show_tool:
            tool = gap.scan_details.get('tool', '-') if gap.scan_details else '-'
            row.append(tool)
            row.append(gap.recommendation[:39])
        elif show_both:
            package = gap.wazuh_details.get('package_name', '-') if gap.wazuh_details else '-'
            tool = gap.scan_details.get('tool', '-') if gap.scan_details else '-'
            row.append(package[:19])
            row.append(tool)
            row.append(f"[green]{gap.confidence}[/green]")

        table.add_row(*row)

    console.print(table)

    if len(gaps) > 30:
        console.print(f"\n[dim]Showing first 30 of {len(gaps)} results.[/dim]")


def _do_sync(engagement_id: int) -> None:
    """Perform sync from Wazuh."""
    console.clear()
    console.print(Panel("Syncing vulnerabilities from Wazuh...", border_style="blue"))

    sync = WazuhVulnSync(engagement_id)

    with console.status("[bold blue]Fetching vulnerabilities..."):
        result = sync.sync_full()

    console.print()

    if result.success:
        console.print(f"[green]✓ Sync complete![/green]")
        console.print(f"  Fetched: {result.total_fetched}")
        console.print(f"  Mapped hosts: {result.mapped_hosts}")
    else:
        console.print(f"[red]✗ Sync failed[/red]")
        for err in result.errors:
            console.print(f"  [red]{err}[/red]")

    console.print("\n[dim]Press any key to continue...[/dim]")
    click.getchar()
