# Copyright (c) CloudZero - ALL RIGHTS RESERVED - PROPRIETARY AND CONFIDENTIAL
# Unauthorized copying of this file and/or project, via any medium is strictly prohibited.
# Direct all questions to legal@cloudzero.com

"""Healthcheck display module for connection health status visualization.

This module provides a provider-agnostic UI for displaying connection healthcheck
results. It supports AWS today and is designed to accommodate future cloud providers
(Azure, GCP, etc.) with minimal changes.
"""

from datetime import datetime
from typing import Any

from rich.console import Console
from rich.panel import Panel
from rich.table import Table
from rich.text import Text

console = Console()

# =============================================================================
# Constants - Provider-Agnostic Design
# =============================================================================

# Status styles: (icon, color)
STATUS_STYLES: dict[str, tuple[str, str]] = {
    "healthy": ("OK", "green"),
    "degraded": ("WARN", "yellow"),
    "unhealthy": ("FAIL", "red"),
    "warning": ("WARN", "yellow"),
    "unknown": ("?", "dim"),
}

# AWS service categories for permission grouping
AWS_SERVICE_CATEGORIES: dict[str, str | list[str]] = {
    "S3": "s3:",
    "Cost Explorer": "ce:",
    "CUR": "cur:",
    "Organizations": "organizations:",
    "CloudWatch": "cloudwatch:",
    "IAM": "iam:",
    "EC2": "ec2:",
    "STS": "sts:",
    "Billing": ["budgets:", "aws-portal:", "billing:"],
}

# Future provider categories (placeholder for extensibility)
AZURE_SERVICE_CATEGORIES: dict[str, str | list[str]] = {
    "Storage": "storage.",
    "Cost Management": "costmanagement.",
    # Add more as Azure support is implemented
}

GCP_SERVICE_CATEGORIES: dict[str, str | list[str]] = {
    "Storage": "storage.",
    "Billing": "cloudbilling.",
    # Add more as GCP support is implemented
}


# =============================================================================
# Helper Functions
# =============================================================================


def get_status_indicator(status: str) -> tuple[str, str]:
    """Get status indicator text and color for a given status.

    Args:
        status: Health status string (healthy, degraded, unhealthy, etc.)

    Returns:
        Tuple of (indicator_text, color_style)
    """
    status_lower = status.lower() if status else "unknown"
    return STATUS_STYLES.get(status_lower, STATUS_STYLES["unknown"])


def get_status_icon(status: str) -> tuple[str, str]:
    """Get emoji icon and color for a status (for compact displays).

    Args:
        status: Health status string

    Returns:
        Tuple of (emoji_icon, color_style)
    """
    status_lower = status.lower() if status else "unknown"
    icons = {
        "healthy": ("✓", "green"),
        "degraded": ("!", "yellow"),
        "unhealthy": ("✗", "red"),
        "warning": ("!", "yellow"),
        "unknown": ("?", "dim"),
    }
    return icons.get(status_lower, icons["unknown"])


def get_service_categories(provider: str) -> dict[str, str | list[str]]:
    """Get service categories for permission grouping based on provider.

    Args:
        provider: Cloud provider name (aws, azure, gcp)

    Returns:
        Dictionary mapping service names to permission prefixes
    """
    provider_lower = provider.lower() if provider else "aws"
    categories = {
        "aws": AWS_SERVICE_CATEGORIES,
        "azure": AZURE_SERVICE_CATEGORIES,
        "gcp": GCP_SERVICE_CATEGORIES,
    }
    return categories.get(provider_lower, AWS_SERVICE_CATEGORIES)


def categorize_permissions(permissions: list[str], provider: str = "aws") -> dict[str, list[str]]:
    """Group permissions by service category.

    Args:
        permissions: List of permission strings
        provider: Cloud provider for category mapping

    Returns:
        Dictionary mapping service names to lists of permissions
    """
    categories = get_service_categories(provider)
    result: dict[str, list[str]] = {name: [] for name in categories}
    result["Other"] = []

    for perm in permissions:
        if not perm:
            continue
        perm_lower = perm.lower()
        categorized = False

        for service_name, prefixes in categories.items():
            if isinstance(prefixes, str):
                prefixes = [prefixes]
            for prefix in prefixes:
                if perm_lower.startswith(prefix.lower()):
                    result[service_name].append(perm)
                    categorized = True
                    break
            if categorized:
                break

        if not categorized:
            result["Other"].append(perm)

    # Remove empty categories
    return {k: v for k, v in result.items() if v}


def get_category_status(
    category_perms: list[str],
    verified: list[str],
    missing_required: list[str],
    missing_optional: list[str],
) -> tuple[str, str]:
    """Determine the status of a permission category.

    Args:
        category_perms: All permissions in this category
        verified: List of verified permissions
        missing_required: List of missing required permissions
        missing_optional: List of missing optional permissions

    Returns:
        Tuple of (status_text, color_style)
    """
    # Check if any required permissions in this category are missing
    category_missing_req = [p for p in category_perms if p in missing_required]
    category_missing_opt = [p for p in category_perms if p in missing_optional]

    if category_missing_req:
        return "FAIL", "red"
    elif category_missing_opt:
        return "WARN", "yellow"
    else:
        return "OK", "green"


def highlight_difference(value: Any, active_value: Any) -> Text:
    """Create text with difference highlighting for comparison tables.

    Args:
        value: The value to display
        active_value: The reference value from active item

    Returns:
        Rich Text object with appropriate styling
    """
    str_value = str(value) if value else "-"
    str_active = str(active_value) if active_value else "-"

    text = Text()
    if str_value != str_active and str_value != "-":
        text.append(str_value, style="white")
        text.append(" [!]", style="yellow bold")
    else:
        text.append(str_value, style="white")

    return text


def get_billing_data_path(check: dict[str, Any], provider: str = "aws") -> str:
    """Construct the full billing data path from check details.

    Args:
        check: The cur_and_data_collection check dictionary
        provider: Cloud provider name

    Returns:
        Full path string (e.g., s3://bucket/prefix/report/)
    """
    details = check.get("details", {})
    if not isinstance(details, dict):
        return "N/A"

    visible_curs = details.get("visible_curs", [])
    if not isinstance(visible_curs, list):
        return "N/A"

    # Find active CUR
    for cur in visible_curs:
        if isinstance(cur, dict) and cur.get("is_active"):
            raw_config = cur.get("raw_config", {})
            if isinstance(raw_config, dict):
                bucket = raw_config.get("S3Bucket", "")
                prefix = raw_config.get("S3Prefix", "")
                name = cur.get("name", "")

                if provider.lower() == "aws" and bucket:
                    path = f"s3://{bucket}"
                    if prefix:
                        path += f"/{prefix.strip('/')}"
                    if name:
                        path += f"/{name}/"
                    return path
    return "N/A"


def format_timestamp(timestamp: str | None) -> str:
    """Format an ISO timestamp to a human-readable string.

    Args:
        timestamp: ISO 8601 timestamp string

    Returns:
        Formatted date/time string or "N/A"
    """
    if not timestamp:
        return "N/A"
    try:
        dt = datetime.fromisoformat(timestamp.replace("Z", "+00:00"))
        return dt.strftime("%Y-%m-%d %H:%M UTC")
    except (ValueError, AttributeError):
        return str(timestamp)


def format_relative_time(timestamp: str | None) -> str:
    """Format a timestamp as relative time (e.g., '2h ago').

    Args:
        timestamp: ISO 8601 timestamp string

    Returns:
        Relative time string or "N/A"
    """
    if not timestamp:
        return "N/A"
    try:
        dt = datetime.fromisoformat(timestamp.replace("Z", "+00:00"))
        now = datetime.now(dt.tzinfo)
        delta = now - dt

        hours = delta.total_seconds() / 3600
        if hours < 1:
            minutes = int(delta.total_seconds() / 60)
            return f"{minutes}m ago"
        elif hours < 24:
            return f"{int(hours)}h ago"
        else:
            days = int(hours / 24)
            return f"{days}d ago"
    except (ValueError, AttributeError):
        return str(timestamp)


# =============================================================================
# Panel Creation Functions
# =============================================================================


def create_header_panel(data: dict[str, Any]) -> Panel:
    """Create the header panel with all connection identifiers.

    Shows: Connection ID, Connection Name, Org ID, Org Name, Provider, Types, Status

    Args:
        data: Full healthcheck response data

    Returns:
        Rich Panel with connection header information
    """
    metadata = data.get("metadata", {})
    if not isinstance(metadata, dict):
        metadata = {}

    # Extract all required fields
    conn_id = data.get("connection_id", "N/A")
    conn_name = metadata.get("connection_name", metadata.get("cz_account_name", "N/A"))
    org_id = metadata.get("cz_organization_id", "N/A")
    org_name = metadata.get("cz_organization_name", metadata.get("organization_name", "N/A"))
    provider = metadata.get("cloud_provider", "N/A")
    conn_types = metadata.get("connection_types", [])
    types_str = ", ".join(conn_types) if isinstance(conn_types, list) else (str(conn_types) if conn_types else "N/A")

    # Status information
    status = data.get("status", "unknown")
    score = data.get("overall_score", 0)
    if score is None:
        score = 0
    icon, color = get_status_icon(status)

    # Create two-column grid
    table = Table.grid(padding=(0, 2))
    table.add_column(ratio=3)
    table.add_column(ratio=2)

    # Left side - identifiers
    left = Table.grid(padding=0)
    left.add_column(style="cyan", justify="right", width=18)
    left.add_column(style="white", overflow="fold")

    left.add_row("Connection ID:", str(conn_id))
    left.add_row("Connection Name:", str(conn_name))
    left.add_row("Organization ID:", str(org_id)[:36] + ("..." if len(str(org_id)) > 36 else ""))
    left.add_row("Organization:", str(org_name))

    # Right side - provider, types, status, spend, autolink
    right = Table.grid(padding=0)
    right.add_column(style="cyan", justify="right", width=14)
    right.add_column(style="white")

    right.add_row("Provider:", str(provider).upper() if provider else "N/A")
    right.add_row("Types:", types_str)

    # 30-day spend
    spend = metadata.get("last_30_days_billed_spend")
    if spend is not None:
        try:
            spend_float = float(spend)
            spend_text = Text(f"${spend_float:,.2f}", style="green")
            right.add_row("30-Day Spend:", spend_text)
        except (ValueError, TypeError):
            right.add_row("30-Day Spend:", Text(str(spend), style="green"))

    # Auto-link status
    auto_link_enabled = metadata.get("auto_link_enabled", False)
    auto_link = metadata.get("auto_link", {})
    if auto_link_enabled:
        role_name = auto_link.get("role_name", "N/A") if isinstance(auto_link, dict) else "N/A"
        autolink_text = Text()
        autolink_text.append("Enabled", style="green")
        autolink_text.append(f" ({role_name})", style="dim")
        right.add_row("Auto-Link:", autolink_text)
    else:
        right.add_row("Auto-Link:", Text("Disabled", style="dim"))

    right.add_row("", "")

    # Status badge
    status_text = Text()
    status_text.append(f"{icon} ", style=f"bold {color}")
    status_text.append(f"{status.upper()} ", style=f"bold {color}")
    status_text.append(f"({score:.0f}%)", style=color)
    right.add_row("Status:", status_text)

    table.add_row(left, right)

    return Panel(table, title="[bold]CONNECTION HEALTHCHECK[/]", border_style=color)


def create_roles_panel(connectivity_check: dict[str, Any], data: dict[str, Any]) -> Panel:
    """Create the active roles panel showing validated role ARNs and billing path.

    Args:
        connectivity_check: The provider_connectivity check dictionary
        data: Full healthcheck response for metadata

    Returns:
        Rich Panel with role ARNs and billing data path
    """
    details = connectivity_check.get("details", {})
    if not isinstance(details, dict):
        details = {}

    metadata = data.get("metadata", {})
    if not isinstance(metadata, dict):
        metadata = {}

    provider = metadata.get("cloud_provider", "aws")
    conn_types = metadata.get("connection_types", [])
    if not isinstance(conn_types, list):
        conn_types = [str(conn_types)] if conn_types else []

    table = Table.grid(padding=0)
    table.add_column(style="cyan", width=16)
    table.add_column(style="white", overflow="fold")

    # Get role information from role_chain
    role_chain = details.get("role_chain", {})
    customer_role = role_chain.get("customer_role_arn", "N/A") if isinstance(role_chain, dict) else "N/A"

    # For AWS, show the customer role ARN
    # Future: differentiate cost vs resource roles if API provides them
    if "COST" in conn_types:
        table.add_row("Cost Role:", Text(str(customer_role), overflow="fold"))
    if "RESOURCE" in conn_types:
        table.add_row("Resource Role:", Text(str(customer_role), overflow="fold"))
    if not conn_types or ("COST" not in conn_types and "RESOURCE" not in conn_types):
        table.add_row("Active Role:", Text(str(customer_role), overflow="fold"))

    # Add billing data path for cost connections
    if "COST" in conn_types:
        # Get billing data path from cur_and_data_collection check
        checks = data.get("checks", [])
        cur_check = {}
        for check in checks:
            if isinstance(check, dict) and check.get("name") == "cur_and_data_collection":
                cur_check = check
                break

        billing_path = get_billing_data_path(cur_check, provider)
        table.add_row("", "")
        table.add_row("Billing Data:", Text(billing_path, style="bold", overflow="fold"))

    status = connectivity_check.get("status", "unknown")
    icon, color = get_status_icon(status)

    return Panel(table, title=f"[{color}]{icon} ACTIVE ROLES[/]", border_style=color)


def create_checks_summary_panel(checks: list[dict[str, Any]]) -> Panel:
    """Create a summary panel showing all healthcheck checks.

    Shows name, status, and message for each check.

    Args:
        checks: List of check dictionaries from healthcheck_result.checks

    Returns:
        Rich Panel with checks summary table
    """
    table = Table(show_header=True, header_style="bold cyan", box=None, padding=(0, 2))
    table.add_column("CHECK", style="white", width=24)
    table.add_column("STATUS", justify="center", width=10)
    table.add_column("MESSAGE", style="dim", overflow="fold")

    overall_status = "healthy"

    for check in checks:
        if not isinstance(check, dict):
            continue

        name = check.get("name", "unknown")
        status = check.get("status", "unknown")
        message = check.get("message", "")

        # Format check name for display
        display_name = name.replace("_", " ").title()

        # Get status indicator
        icon, color = get_status_icon(status)
        status_text = Text()
        status_text.append(f"{icon} ", style=color)
        status_text.append(status.upper(), style=f"bold {color}")

        # Track overall status
        if status.lower() == "unhealthy":
            overall_status = "unhealthy"
        elif status.lower() == "degraded" and overall_status != "unhealthy":
            overall_status = "degraded"

        table.add_row(display_name, status_text, message or "-")

    icon, color = get_status_icon(overall_status)
    return Panel(table, title=f"[{color}]{icon} HEALTHCHECK SUMMARY[/]", border_style=color)


def create_permissions_panel(permissions_check: dict[str, Any], provider: str = "aws") -> Panel:
    """Create the permissions panel with service-based categorization.

    Groups permissions by AWS service and shows OK/WARN/FAIL per category.

    Args:
        permissions_check: The permissions_check dictionary
        provider: Cloud provider for category mapping

    Returns:
        Rich Panel with categorized permissions table
    """
    details = permissions_check.get("details", {})
    if not isinstance(details, dict):
        details = {}

    # Extract permission lists
    required = details.get("required_permissions", [])
    optional = details.get("optional_permissions", [])
    verified = details.get("verified_permissions", [])
    missing_required = details.get("missing_required_permissions", [])
    missing_optional = details.get("missing_optional_permissions", [])

    # Ensure all are lists
    for lst in [required, optional, verified, missing_required, missing_optional]:
        if not isinstance(lst, list):
            lst = []

    all_permissions = list(set(required + optional))
    total_count = len(all_permissions)
    verified_count = len(verified)

    # Categorize all permissions
    categorized = categorize_permissions(all_permissions, provider)
    categorized_verified = categorize_permissions(verified, provider)

    # Create table
    table = Table(show_header=True, header_style="bold cyan", box=None, padding=(0, 2))
    table.add_column("SERVICE", style="white", width=16)
    table.add_column("STATUS", justify="center", width=8)
    table.add_column("PERMISSIONS", style="dim", overflow="fold")

    for service_name, service_perms in sorted(categorized.items()):
        # Determine category status
        status_text, status_color = get_category_status(service_perms, verified, missing_required, missing_optional)

        # Build permissions display
        service_verified = categorized_verified.get(service_name, [])
        service_missing_req = [p for p in service_perms if p in missing_required]
        service_missing_opt = [p for p in service_perms if p in missing_optional]

        perms_text = Text()

        # Show verified permissions (green, truncated)
        if service_verified:
            verified_display = service_verified[:3]
            perms_text.append(", ".join(verified_display), style="green")
            if len(service_verified) > 3:
                perms_text.append(f" +{len(service_verified) - 3}", style="dim green")

        # Show missing required (red)
        if service_missing_req:
            if perms_text:
                perms_text.append(" | ", style="dim")
            perms_text.append("[MISSING: ", style="red")
            perms_text.append(", ".join(service_missing_req[:2]), style="red")
            if len(service_missing_req) > 2:
                perms_text.append(f" +{len(service_missing_req) - 2}", style="dim red")
            perms_text.append("]", style="red")

        # Show missing optional (yellow)
        if service_missing_opt:
            if perms_text:
                perms_text.append(" | ", style="dim")
            perms_text.append("[optional: ", style="yellow")
            perms_text.append(", ".join(service_missing_opt[:2]), style="yellow")
            if len(service_missing_opt) > 2:
                perms_text.append(f" +{len(service_missing_opt) - 2}", style="dim yellow")
            perms_text.append("]", style="yellow")

        status_styled = Text(f"[{status_text}]", style=f"bold {status_color}")
        table.add_row(service_name, status_styled, perms_text)

    status = permissions_check.get("status", "unknown")
    icon, color = get_status_icon(status)
    title = f"[{color}]{icon} PERMISSIONS ({verified_count}/{total_count} verified)[/]"

    return Panel(table, title=title, border_style=color)


def create_billing_config_panel(cur_check: dict[str, Any]) -> Panel | None:
    """Create the active billing data configuration panel.

    Shows data collection stats and configuration for the active CUR/billing report.

    Args:
        cur_check: The cur_and_data_collection check dictionary

    Returns:
        Rich Panel with billing config, or None if no active billing data
    """
    details = cur_check.get("details", {})
    if not isinstance(details, dict):
        return None

    visible_curs = details.get("visible_curs", [])
    if not isinstance(visible_curs, list):
        return None

    # Find active CUR
    active_cur = None
    for cur in visible_curs:
        if isinstance(cur, dict) and cur.get("is_active"):
            active_cur = cur
            break

    if not active_cur:
        return None

    name = active_cur.get("name", "Unknown")
    status = active_cur.get("status", "unknown")
    raw_config = active_cur.get("raw_config", {})
    cur_stats = active_cur.get("cur_stats", {})
    data_collection = active_cur.get("data_collection", {})

    if not isinstance(raw_config, dict):
        raw_config = {}
    if not isinstance(cur_stats, dict):
        cur_stats = {}
    if not isinstance(data_collection, dict):
        data_collection = {}

    # Create two-column layout
    main_table = Table.grid(padding=(0, 3))
    main_table.add_column(ratio=1)
    main_table.add_column(ratio=1)

    # Header row
    header = Table.grid(padding=0)
    header.add_column()

    icon, color = get_status_icon(status)
    report_count = data_collection.get("report_count", 0) or 0
    last_drop = cur_stats.get("cur_drop_datetime")
    last_drop_rel = format_relative_time(last_drop)

    header_text = Text()
    header_text.append(f"Report: {name} ", style="bold white")
    header_text.append(f"| Status: {icon} {status.upper()} ", style=color)
    header_text.append(f"| Last Drop: {last_drop_rel} ", style="dim")
    header_text.append(f"| Files: {report_count:,}", style="dim")
    header.add_row(header_text)

    # Left column - Data Collection
    left = Table.grid(padding=0)
    left.add_column(style="cyan", width=22)
    left.add_column(style="white", overflow="fold")

    left.add_row(Text("DATA COLLECTION", style="bold"), "")

    last_collection = data_collection.get("last_collection_time")
    left.add_row("Last Collection:", format_timestamp(last_collection))

    avg_current = cur_stats.get("avg_cur_drop_time_current")
    if avg_current:
        left.add_row("Avg Drop (Current):", f"{avg_current:.1f}h")

    avg_previous = cur_stats.get("avg_cur_drop_time_previous")
    if avg_previous:
        left.add_row("Avg Drop (Previous):", f"{avg_previous:.1f}h")

    latest_file = data_collection.get("latest_file_path")
    if latest_file:
        # Truncate long paths
        if len(str(latest_file)) > 50:
            latest_file = "..." + str(latest_file)[-47:]
        left.add_row("Latest File:", Text(str(latest_file), overflow="fold"))

    # Right column - Configuration
    right = Table.grid(padding=0)
    right.add_column(style="cyan", width=16)
    right.add_column(style="white", overflow="fold")

    right.add_row(Text("CONFIGURATION", style="bold"), "")

    bucket = raw_config.get("S3Bucket", "N/A")
    prefix = raw_config.get("S3Prefix", "")
    region = raw_config.get("S3Region", "N/A")
    location = f"s3://{bucket}/{prefix}" if bucket != "N/A" else "N/A"
    right.add_row("Location:", Text(location, overflow="fold"))
    right.add_row("Region:", region)

    time_unit = raw_config.get("TimeUnit", "N/A")
    format_type = raw_config.get("Format", "N/A")
    compression = raw_config.get("Compression", "N/A")
    right.add_row("Format:", f"{format_type} | {time_unit} | {compression}")

    schema = raw_config.get("AdditionalSchemaElements", [])
    if isinstance(schema, list) and schema:
        right.add_row("Schema:", ", ".join(schema))

    main_table.add_row(left, right)

    # Combine header and content
    combined = Table.grid(padding=0)
    combined.add_column()
    combined.add_row(header)
    combined.add_row(Text(""))
    combined.add_row(main_table)

    check_status = cur_check.get("status", "unknown")
    check_icon, check_color = get_status_icon(check_status)

    return Panel(combined, title=f"[{check_color}]{check_icon} ACTIVE BILLING DATA[/]", border_style=check_color)


def create_billing_comparison_panel(cur_check: dict[str, Any]) -> Panel | None:
    """Create the billing data comparison panel with difference highlighting.

    Shows side-by-side comparison of all visible CURs/billing reports.

    Args:
        cur_check: The cur_and_data_collection check dictionary

    Returns:
        Rich Panel with comparison table, or None if less than 2 CURs
    """
    details = cur_check.get("details", {})
    if not isinstance(details, dict):
        return None

    visible_curs = details.get("visible_curs", [])
    if not isinstance(visible_curs, list) or len(visible_curs) < 2:
        return None

    # Sort with active CUR first
    sorted_curs = sorted(visible_curs, key=lambda c: (not c.get("is_active", False), c.get("name", "")))

    # Limit to 4 CURs for display
    display_curs = sorted_curs[:4]

    # Find active CUR values for comparison
    active_cur = next((c for c in display_curs if c.get("is_active")), display_curs[0])
    active_config = active_cur.get("raw_config", {})
    if not isinstance(active_config, dict):
        active_config = {}

    # Create comparison table
    table = Table(show_header=True, header_style="bold cyan", box=None, padding=(0, 1))
    table.add_column("FIELD", style="cyan", width=16)

    # Add column for each CUR
    for cur in display_curs:
        name = cur.get("name", "Unknown")
        is_active = cur.get("is_active", False)
        col_title = f"{name} *" if is_active else name
        table.add_column(col_title, overflow="fold")

    # Define comparison fields
    fields = [
        ("Status", lambda c: c.get("status", "unknown").upper()),
        ("Compatible", lambda c: "YES" if c.get("is_healthy") else "NO"),
        ("Accessible", lambda c: "YES" if c.get("is_accessible") else "NO"),
        ("Time Unit", lambda c: c.get("raw_config", {}).get("TimeUnit", "-")),
        ("Format", lambda c: c.get("raw_config", {}).get("Format", "-")),
        ("Compression", lambda c: c.get("raw_config", {}).get("Compression", "-")),
        ("S3 Bucket", lambda c: c.get("raw_config", {}).get("S3Bucket", "-")),
        ("S3 Region", lambda c: c.get("raw_config", {}).get("S3Region", "-")),
        ("Schema", lambda c: str(len(c.get("raw_config", {}).get("AdditionalSchemaElements", []))) + " elements"),
        ("Refresh", lambda c: "Yes" if c.get("raw_config", {}).get("RefreshClosedReports") else "No"),
        (
            "Versioning",
            lambda c: "NEW" if c.get("raw_config", {}).get("ReportVersioning") == "CREATE_NEW_REPORT" else "OVERWRITE",
        ),
        (
            "Reason",
            lambda c: c.get("health_details", {}).get("reason", "-")
            if isinstance(c.get("health_details"), dict)
            else "-",
        ),
    ]

    # Fields that use color based on value, not comparison
    color_coded_fields = {"Compatible", "Accessible", "Status"}

    for field_name, get_value in fields:
        row_values = [field_name]
        active_value = get_value(active_cur)

        for cur in display_curs:
            value = get_value(cur)

            # Special color coding for certain fields
            if field_name in color_coded_fields:
                if value == "YES" or value == "HEALTHY":
                    style = "bold green" if cur.get("is_active") else "green"
                elif value == "NO" or value == "UNHEALTHY":
                    style = "bold red" if cur.get("is_active") else "red"
                else:
                    style = "bold yellow" if cur.get("is_active") else "yellow"
                row_values.append(Text(str(value), style=style))
            elif cur.get("is_active"):
                row_values.append(Text(str(value), style="bold white"))
            else:
                row_values.append(highlight_difference(value, active_value))

        table.add_row(*row_values)

    # Add legend
    legend = Text()
    legend.append("* = Active | ", style="dim")
    legend.append("[!]", style="yellow bold")
    legend.append(" = Differs from active", style="dim")

    combined = Table.grid(padding=0)
    combined.add_column()
    combined.add_row(table)
    combined.add_row(Text(""))
    combined.add_row(legend)

    total_curs = details.get("total_curs_found", len(visible_curs))
    healthy_curs = details.get("healthy_curs_count", 0)

    return Panel(
        combined, title=f"[cyan]BILLING DATA COMPARISON ({healthy_curs}/{total_curs} healthy)[/]", border_style="cyan"
    )


def create_connectivity_issues_panel(connectivity_check: dict[str, Any]) -> Panel | None:
    """Create the connectivity issues panel (only shown when problems exist).

    Shows role chain details and error information when connectivity fails.

    Args:
        connectivity_check: The provider_connectivity check dictionary

    Returns:
        Rich Panel with error details, or None if no issues
    """
    status = connectivity_check.get("status", "unknown")
    if status.lower() == "healthy":
        return None

    details = connectivity_check.get("details", {})
    if not isinstance(details, dict):
        details = {}

    message = connectivity_check.get("message", "")

    table = Table.grid(padding=0)
    table.add_column(style="red", overflow="fold")

    # Show warning/error message
    if message:
        table.add_row(Text(f"WARNING: {message}", style="bold red"))
        table.add_row(Text(""))

    # Show role chain details
    role_chain = details.get("role_chain", {})
    if isinstance(role_chain, dict):
        initial = role_chain.get("initial_account", "?")
        reactor = role_chain.get("reactor_account", "?")
        customer = role_chain.get("customer_account", "?")

        chain_text = Text("Chain: ")
        chain_text.append(str(initial), style="dim")
        chain_text.append(" -> ", style="dim")
        chain_text.append(str(reactor), style="dim")
        chain_text.append(" -> ", style="dim")

        if status.lower() in ["unhealthy", "degraded"]:
            chain_text.append(f"[FAILED: {customer}]", style="bold red")
        else:
            chain_text.append(str(customer), style="dim")

        table.add_row(chain_text)

        # Show customer role ARN
        customer_role = role_chain.get("customer_role_arn")
        if customer_role:
            table.add_row(Text(f"Role: {customer_role}", style="dim", overflow="fold"))

    icon, color = get_status_icon(status)
    return Panel(table, title=f"[{color}]{icon} CONNECTIVITY ISSUES[/]", border_style=color)


# =============================================================================
# Main Display Function
# =============================================================================


def display_healthcheck(data: dict[str, Any], connection: dict[str, Any] | None = None) -> None:
    """Display healthcheck results in the new panel layout.

    Panel order (priority):
    1. Header - Connection identifiers and status
    2. Active Roles - Role ARNs and billing data path
    3. Permissions - Service-categorized permissions
    4. Billing Config - Active billing data details (cost connections)
    5. Billing Comparison - Side-by-side CUR comparison (if multiple)
    6. Connectivity Issues - Only shown when problems detected

    Args:
        data: Full healthcheck response data
        connection: Optional connection data with org/account info
    """
    console.print()

    # Get all checks
    checks_list = data.get("checks", [])
    checks: dict[str, dict] = {}
    for check in checks_list:
        if isinstance(check, dict) and "name" in check:
            checks[check["name"]] = check

    # Merge connection data into metadata if provided
    # Connection object has org/account info that API response may not include
    metadata = data.get("metadata")
    if not isinstance(metadata, dict):
        metadata = {}
        data["metadata"] = metadata  # Store back so create_header_panel can access it

    if connection:
        # Add connection fields to metadata if not already present
        if "connection_name" not in metadata:
            metadata["connection_name"] = connection.get("connection_name") or connection.get("cz_account_name", "")
        if "cz_organization_id" not in metadata:
            metadata["cz_organization_id"] = connection.get("cz_organization_id", "")
        if "cz_organization_name" not in metadata:
            metadata["cz_organization_name"] = connection.get("cz_organization_name", "")
        if "cloud_provider" not in metadata:
            metadata["cloud_provider"] = connection.get("provider") or connection.get("cloud_provider", "aws")

        # Add connection_details fields
        conn_details = connection.get("connection_details", {})
        if conn_details:
            if "connection_details" not in metadata:
                metadata["connection_details"] = conn_details
            # Extract key fields for easy access
            if "auto_link_enabled" not in metadata:
                metadata["auto_link_enabled"] = conn_details.get("auto_link_enabled", False)
            if "auto_link" not in metadata:
                metadata["auto_link"] = conn_details.get("auto_link", {})
            if "last_30_days_billed_spend" not in metadata:
                metadata["last_30_days_billed_spend"] = conn_details.get("last_30_days_billed_spend")

        if "connection_types" not in metadata:
            # Determine connection types from connection data
            conn_type = connection.get("connection_type", "")
            if conn_type:
                metadata["connection_types"] = [conn_type]
            else:
                # Infer from flags
                types = []
                if conn_details.get("is_cost_connection") or connection.get("is_cost_connection"):
                    types.append("COST")
                if conn_details.get("is_resource_connection") or connection.get("is_resource_collection_enabled"):
                    types.append("RESOURCE")
                metadata["connection_types"] = types if types else ["UNKNOWN"]

    provider = metadata.get("cloud_provider", "aws")
    conn_types = metadata.get("connection_types", [])
    if not isinstance(conn_types, list):
        conn_types = [conn_types] if conn_types else []

    # 1. Header Panel (always shown)
    console.print(create_header_panel(data))
    console.print()

    # 2. Checks Summary Panel (always shown)
    if checks_list:
        console.print(create_checks_summary_panel(checks_list))
        console.print()

    # 3. Active Roles Panel (always shown)
    connectivity_check = checks.get("provider_connectivity", {})
    console.print(create_roles_panel(connectivity_check, data))
    console.print()

    # 4. Permissions Panel (always shown)
    permissions_check = checks.get("permissions_check", {})
    console.print(create_permissions_panel(permissions_check, provider))
    console.print()

    # 5. Billing Config Panel (cost connections only)
    cur_check = checks.get("cur_and_data_collection", {})
    if "COST" in conn_types:
        billing_panel = create_billing_config_panel(cur_check)
        if billing_panel:
            console.print(billing_panel)
            console.print()

    # 6. Billing Comparison Panel (if multiple CURs)
    if "COST" in conn_types:
        comparison_panel = create_billing_comparison_panel(cur_check)
        if comparison_panel:
            console.print(comparison_panel)
            console.print()

    # 7. Connectivity Issues Panel (only if problems)
    issues_panel = create_connectivity_issues_panel(connectivity_check)
    if issues_panel:
        console.print(issues_panel)
        console.print()
