# 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
#

import csv
import json
import sys
from typing import Any

from rich.console import Console
from rich.panel import Panel
from rich.pretty import pprint
from rich.progress import Progress, SpinnerColumn, TextColumn
from rich.table import Table, box
from rich.text import Text

from src.api.v4_connections import get_connection, get_connections_for_org
from src.api.v4_healthcheck import get_connection_healthcheck, post_bulk_healthcheck
from src.api.v4_organizations import get_organizations
from src.constants import HEALTHCHECK_SUPPORTED_PROVIDERS
from src.utils.connections import ConnectionUtils
from src.utils.console import eprint
from src.utils.time import pretty_datetime_local
from src.utils.ui import HealthStatus, PanelFactory, TableFactory

# Initialize Rich console using terminal width, with a fallback minimum width
console = Console(width=None)  # Use full terminal width
CONSOLE_WIDTH = console.width or 150  # Default to 150 if terminal width can't be detected
TABLE_WIDTH = CONSOLE_WIDTH - 4  # Account for panel borders/padding


# ------------------------------------------------------------------------------------------------
# DATA MODELS AND PROCESSING
# ------------------------------------------------------------------------------------------------


class HealthcheckData:
    """Class for processing and enriching healthcheck data."""

    @staticmethod
    def fetch_healthcheck(connection_id: str) -> dict[str, Any]:
        """Fetch healthcheck data for a connection using v4 API single connection endpoint."""
        try:
            # Use the single connection healthcheck endpoint
            response = get_connection_healthcheck(connection_id, include_details=True, debug=False)

            # Return the complete healthcheck data
            return response.model_dump()
        except Exception as e:
            eprint(f"[red]Error fetching healthcheck for {connection_id}: {e}[/]")
            return {}

    @staticmethod
    def enrich_connection(connection: dict[str, Any]) -> dict[str, Any]:
        """Enrich connection data with healthcheck information."""
        if not connection:
            return {}

        # Get the connection ID
        # Note: Backend API field 'cloud_account_id' still uses 'account' terminology
        # This should be renamed to 'cloud_connection_id' when backend is updated
        connection_id = connection.get("cloud_account_id")
        if not connection_id:
            # Log warning for debugging purposes
            if "__debug" in connection:
                eprint(f"Warning: Missing cloud_account_id in connection: {connection}")
            return connection

        # Fetch the healthcheck data
        healthcheck_result = HealthcheckData.fetch_healthcheck(connection_id)

        # Attach the healthcheck data to the connection
        connection["healthcheck_result"] = healthcheck_result

        return connection

    @staticmethod
    def process_connection_batch(
        connections: dict[str, dict[str, Any]], progress_callback=None, use_batch_api: bool = True, progress_task=None, progress_obj=None
    ) -> dict[str, dict[str, Any]]:
        """Process a batch of connections, adding healthcheck data to each."""
        results = {}

        if use_batch_api:
            # Collect all connection IDs for batch processing
            all_connection_ids = []
            connection_map = {}  # Map to track which connection belongs to which org

            for org_id, org_connections in connections.items():
                results[org_id] = {}
                for conn_id, connection in org_connections.items():
                    connection_id = connection.get("cloud_account_id")
                    if connection_id:
                        all_connection_ids.append(connection_id)
                        connection_map[connection_id] = (org_id, conn_id, connection)

            # Decide whether to use single or bulk API based on number of connections
            if len(all_connection_ids) == 1:
                # Use single connection healthcheck API for a single connection
                connection_id = all_connection_ids[0]
                org_id, conn_id, connection = connection_map[connection_id]

                try:
                    if progress_obj and progress_task is not None:
                        progress_obj.update(progress_task, description=f"Checking health of {connection_id}...")

                    # Call single connection healthcheck API
                    is_debug = connection.get("__debug", False)
                    if is_debug:
                        eprint(f"[cyan]DEBUG: Using single connection healthcheck API for {connection_id}[/]")
                    healthcheck_response = get_connection_healthcheck(connection_id, include_details=True, debug=is_debug)

                    # Convert to dict and store all fields
                    healthcheck_dict = healthcheck_response.model_dump()
                    connection["healthcheck_result"] = healthcheck_dict

                    # Also update connection-level fields
                    connection["is_healthy"] = healthcheck_dict.get("is_healthy", False)
                    connection["health_status"] = healthcheck_dict.get("status", "unknown")
                    connection["health_score"] = healthcheck_dict.get("overall_score")

                    results[org_id][conn_id] = connection

                    if progress_callback:
                        progress_callback()

                except Exception as e:
                    eprint(f"[yellow]Single healthcheck failed: {e}. Falling back to individual calls.[/]")
                    return HealthcheckData.process_connection_batch(
                        connections, progress_callback, use_batch_api=False, progress_task=progress_task, progress_obj=progress_obj
                    )

            elif all_connection_ids:
                # Use bulk API for multiple connections
                try:
                    # Update progress description
                    if progress_obj and progress_task is not None:
                        progress_obj.update(progress_task, description=f"Fetching healthcheck data for {len(all_connection_ids)} connections...")

                    # Call v4 bulk healthcheck API for multiple connections
                    # Check if any connection has debug flag
                    is_debug = any(conn.get("__debug", False) for _, _, conn in connection_map.values())
                    if is_debug:
                        eprint(f"[cyan]DEBUG: Using bulk healthcheck API for {len(all_connection_ids)} connections[/]")
                    healthcheck_response = post_bulk_healthcheck(
                        entity_type="connection", entity_ids=all_connection_ids, include_details=True, debug=is_debug
                    )

                    # Update progress description
                    if progress_obj and progress_task is not None:
                        progress_obj.update(progress_task, description="Processing healthcheck results...")

                    # Process results
                    successful_count = 0

                    # The v4 API returns connections in the response
                    for healthcheck_result in healthcheck_response.connections:
                        # Try connection_id first, then entity_id (API returns entity_id)
                        connection_id = getattr(healthcheck_result, "connection_id", None) or getattr(healthcheck_result, "entity_id", None)
                        if connection_id in connection_map:
                            org_id, conn_id, connection = connection_map[connection_id]
                            # Convert V4 Pydantic model to dict - keep ALL fields from API
                            healthcheck_dict = healthcheck_result.model_dump()

                            # Store the complete healthcheck result with all fields
                            connection["healthcheck_result"] = healthcheck_dict

                            # Also update connection-level fields for compatibility
                            connection["is_healthy"] = healthcheck_dict.get("is_healthy", False)
                            connection["health_status"] = healthcheck_dict.get("status", "unknown")
                            connection["health_score"] = healthcheck_dict.get("overall_score")
                            results[org_id][conn_id] = connection
                            successful_count += 1

                            if progress_callback:
                                progress_callback()

                    # Log if some connections didn't get results
                    missing_count = len(all_connection_ids) - successful_count
                    if missing_count > 0:
                        eprint(f"[yellow]Warning: {missing_count} connections did not return healthcheck data[/]")

                except Exception as e:
                    # Fall back to individual calls if batch fails
                    eprint(f"[yellow]Batch healthcheck failed: {e}. Falling back to individual calls.[/]")
                    return HealthcheckData.process_connection_batch(
                        connections, progress_callback, use_batch_api=False, progress_task=progress_task, progress_obj=progress_obj
                    )

            # Add any connections that didn't get results
            for org_id, org_connections in connections.items():
                for conn_id, connection in org_connections.items():
                    if conn_id not in results.get(org_id, {}):
                        results[org_id][conn_id] = connection

        else:
            # Original implementation - process individually
            for org_id, org_connections in connections.items():
                results[org_id] = {}

                for conn_id, connection in org_connections.items():
                    # Update progress description with current connection
                    connection_name = connection.get("cz_account_name", conn_id)
                    if progress_obj and progress_task is not None:
                        progress_obj.update(progress_task, description=f"Checking {connection_name}...")

                    # Enrich the connection with healthcheck data
                    enriched_connection = HealthcheckData.enrich_connection(connection)
                    results[org_id][conn_id] = enriched_connection

                    # Update progress if callback is provided
                    if progress_callback:
                        progress_callback()

        return results


# ------------------------------------------------------------------------------------------------
# HEALTHCHECK FORMATTERS
# ------------------------------------------------------------------------------------------------


class DateFormatter:
    """Helper for formatting dates consistently."""

    @staticmethod
    def format_datetime(datetime_str: str | None) -> str:
        """Format datetime string for display with local timezone."""
        if not datetime_str:
            return "Not available"

        try:
            # Handle very large dates that might cause overflow
            if datetime_str.startswith("9999") or datetime_str.endswith("9999"):
                return datetime_str
            return pretty_datetime_local(datetime_str)
        except (ValueError, AttributeError, OverflowError):
            return datetime_str


class HealthcheckFormatter:
    """Base class for formatting healthcheck data."""

    @staticmethod
    def get_health_icon(is_healthy: bool) -> str:
        """Return health icon based on status."""
        return HealthStatus.get_icon(is_healthy)


class HealthcheckDetailsFormatter(HealthcheckFormatter):
    """Formats healthcheck API response details including checks."""

    @staticmethod
    def _format_permissions_details(details: dict[str, Any]) -> Text:
        """Format permissions check details with visual indicators."""
        result = Text()

        verified = details.get("verified_permissions", [])
        missing = details.get("missing_permissions", [])

        if missing:
            result.append("\n⚠️  Missing Permissions:\n", style="bold yellow")
            for perm in missing:
                result.append(f"  ✗ {perm}\n", style="red")
        else:
            result.append("\n✓ All required permissions verified\n", style="green")

        if verified and len(verified) <= 5:
            result.append("\n📋 Verified Permissions:\n", style="dim cyan")
            for perm in verified:
                result.append(f"  • {perm}\n", style="dim")
        elif verified:
            result.append(f"\n✓ {len(verified)} permissions verified\n", style="dim green")

        return result

    @staticmethod
    def _format_data_collection_details(details: dict[str, Any]) -> Text:
        """Format data collection details with metrics."""
        result = Text()

        last_collection = details.get("last_collection", "Unknown")
        resources = details.get("resources_discovered", 0)
        errors = details.get("collection_errors", 0)

        result.append("\n📊 Collection Metrics:\n", style="dim cyan")
        result.append("  • Resources Discovered: ", style="dim")
        result.append(f"{resources:,}\n", style="bright_white")

        if errors > 0:
            result.append("  • Collection Errors: ", style="dim")
            result.append(f"{errors}\n", style="yellow")
        else:
            result.append("  • Collection Errors: ", style="dim")
            result.append("0\n", style="green")

        result.append("  • Last Collection: ", style="dim")
        result.append(f"{last_collection}\n", style="dim white")

        return result

    @staticmethod
    def _format_cur_health_details(details: dict[str, Any]) -> Text:
        """Format CUR health details with structured report information."""
        result = Text()

        if not details:
            result.append("\nℹ️  No CUR configuration details available\n", style="dim")
            return result

        result.append("\n📦 CUR Report Status:\n", style="dim cyan")

        for report_name, report_details in details.items():
            if not isinstance(report_details, dict):
                continue

            is_healthy = report_details.get("healthy", False)
            reason = report_details.get("reason", "Unknown")
            bucket_healthy = report_details.get("bucket_healthy", False)
            time_unit = report_details.get("time_unit", "Unknown")
            format_type = report_details.get("format", "Unknown")
            compression = report_details.get("compression", "Unknown")

            # Report name with status icon
            icon = "✓" if is_healthy else "✗"
            color = "green" if is_healthy else "red"
            result.append(f"\n  {icon} {report_name}\n", style=f"bold {color}")

            # Status details
            if not is_healthy and reason:
                result.append(f"    Issue: {reason}\n", style="yellow")

            # Configuration summary
            result.append(f"    Format: {format_type} | ", style="dim")
            result.append(f"Compression: {compression} | ", style="dim")
            result.append(f"Frequency: {time_unit}\n", style="dim")

            # Bucket status
            bucket_icon = "✓" if bucket_healthy else "✗"
            bucket_color = "green" if bucket_healthy else "red"
            result.append(f"    Bucket Access: {bucket_icon}\n", style=bucket_color)

        return result

    @staticmethod
    def _format_generic_details(details: dict[str, Any]) -> Text:
        """Format generic details as a fallback."""
        result = Text()

        for key, value in details.items():
            display_key = key.replace("_", " ").title()

            if isinstance(value, list):
                if not value:
                    result.append(f"\n  • {display_key}: None\n", style="dim")
                elif len(value) <= 3:
                    result.append(f"\n  • {display_key}: {', '.join(str(v) for v in value)}\n", style="dim")
                else:
                    result.append(f"\n  • {display_key}: {len(value)} items\n", style="dim")
            elif isinstance(value, dict):
                result.append(f"\n  • {display_key}:\n", style="dim")
                for sub_key, sub_value in value.items():
                    result.append(f"      {sub_key}: {sub_value}\n", style="dim")
            else:
                result.append(f"\n  • {display_key}: {value}\n", style="dim")

        return result

    @staticmethod
    def create(healthcheck_result: dict[str, Any]) -> Panel | None:
        """Create enhanced panels showing healthcheck details from API response."""
        if not healthcheck_result or not healthcheck_result.get("checks"):
            return None

        from rich.console import Group

        checks = healthcheck_result.get("checks", [])
        check_panels = []

        # Create individual panels for each check
        for check in checks:
            name = check.get("name", "unknown")
            status = check.get("status", "unknown")
            message = check.get("message", "")
            duration = check.get("duration_ms", 0)
            details = check.get("details", {})

            # Determine status icon and color
            if status == "healthy":
                icon = "✓"
                status_color = "green"
                border_style = "green"
            elif status == "degraded":
                icon = "⚠"
                status_color = "yellow"
                border_style = "yellow"
            elif status == "unknown":
                icon = "?"
                status_color = "dim"
                border_style = "dim"
            else:
                icon = "✗"
                status_color = "red"
                border_style = "red"

            # Build check content
            content = Text()
            content.append(f"{icon} ", style=f"bold {status_color}")
            content.append(f"{status.upper()}\n", style=f"bold {status_color}")
            content.append(f"{message}\n", style="white")

            # Format details based on check type
            if details:
                if name == "permissions_check":
                    content.append(HealthcheckDetailsFormatter._format_permissions_details(details))
                elif name == "data_collection":
                    content.append(HealthcheckDetailsFormatter._format_data_collection_details(details))
                elif name == "cur_health":
                    content.append(HealthcheckDetailsFormatter._format_cur_health_details(details))
                else:
                    content.append(HealthcheckDetailsFormatter._format_generic_details(details))

            # Add duration if available
            if duration:
                content.append(f"\n⏱️  {duration:.1f}ms", style="dim")

            # Create panel for this check
            check_panel = Panel(
                content,
                title=f"[cyan]{name.replace('_', ' ').title()}[/]",
                border_style=border_style,
                padding=(1, 2),
            )
            check_panels.append(check_panel)

        # Create summary if available
        summary_text = Text()
        if healthcheck_result.get("summary"):
            summary = healthcheck_result["summary"]
            summary_text.append("📊 Summary: ", style="bold cyan")
            summary_text.append(f"{summary.get('total_checks', 0)} checks | ", style="dim")
            summary_text.append(f"✓ {summary.get('healthy_count', 0)} ", style="green")
            if summary.get("degraded_count", 0) > 0:
                summary_text.append(f"⚠ {summary.get('degraded_count', 0)} ", style="yellow")
            if summary.get("unhealthy_count", 0) > 0:
                summary_text.append(f"✗ {summary.get('unhealthy_count', 0)} ", style="red")

        # Group all panels
        group = Group(*check_panels, summary_text if summary_text else Text())

        return Panel(group, title="[bold cyan]🔍 Healthcheck Results[/]", border_style="cyan", padding=(1, 2))


class ConnectionHeader(HealthcheckFormatter):
    """Formats connection header information."""

    @staticmethod
    def create(connection: dict[str, Any], healthcheck_result: dict[str, Any]) -> Panel:
        """Create a header panel for a connection."""
        org_id, org_name = ConnectionUtils.get_organization_info(connection)
        connection_id = ConnectionUtils.get_connection_id(connection) or "Unknown"
        account_name = ConnectionUtils.get_connection_name(connection)
        provider = connection.get("cloud_provider", "Unknown")
        is_connected = connection.get("is_connected", False)
        last_updated = connection.get("last_updated", "Unknown")
        last_seen = connection.get("last_seen", "Unknown")
        created = connection.get("created", "Unknown")

        # Organization info
        org_text = Text()
        org_text.append("Organization: ", style="cyan")
        org_text.append(f"{org_name} ", style="bright_white")
        org_text.append(f"({org_id})", style="dim")

        # Connection info
        conn_text = Text()
        conn_text.append("Connection: ", style="cyan")
        conn_text.append(f"{account_name} ", style="bright_white")
        conn_text.append(f"({connection_id})", style="yellow")

        # Provider info
        provider_text = Text()
        provider_text.append("Provider: ", style="cyan")
        provider_text.append(provider, style="bright_white")

        # Status with health score if available
        status_text = Text()
        status_text.append("Status: ", style="cyan")
        health_status = healthcheck_result.get("status", connection.get("health_status", "unknown"))
        health_score = healthcheck_result.get("overall_score", connection.get("health_score"))

        if health_status == "healthy":
            status_text.append("Healthy", style="green")
        elif health_status == "degraded":
            status_text.append("Degraded", style="yellow")
        elif health_status == "unhealthy":
            status_text.append("Unhealthy", style="red")
        else:
            status_text.append(health_status.title(), style="dim")

        # Add health score if available
        if health_score is not None:
            if health_score >= 90:
                score_style = "green"
            elif health_score >= 70:
                score_style = "yellow"
            else:
                score_style = "red"
            status_text.append(f" ({health_score:.1f}%)", style=score_style)

        # Connected status
        connected_text = Text()
        connected_text.append("Connected: ", style="cyan")
        if is_connected:
            connected_text.append("Yes", style="green")
        else:
            connected_text.append("No", style="red")

        # Management account status removed - deprecated in v4 API

        # Timestamps
        created_text = Text()
        created_text.append("Created: ", style="cyan")
        created_text.append(DateFormatter.format_datetime(created), style="bright_white")

        updated_text = Text()
        updated_text.append("Last Updated: ", style="cyan")
        updated_text.append(DateFormatter.format_datetime(last_updated), style="bright_white")

        seen_text = Text()
        seen_text.append("Last Seen: ", style="cyan")
        seen_text.append(DateFormatter.format_datetime(last_seen), style="bright_white")

        # 30-Day spend info
        spend_text = Text()
        spend_text.append("30-Day Cloud Spend: ", style="cyan")
        # Extract data from healthcheck result
        details = healthcheck_result.get("details", {})
        spend_data = details.get("30_day_spend", healthcheck_result.get("30_day_spend", {}))

        connection_spend, total_spend, percentage = ConnectionUtils.calculate_spend_percentage(connection_id, spend_data)

        if spend_data:
            if connection_spend > 0:
                spend_text.append(f"${connection_spend:,.2f}", style="green")
                if len(spend_data) > 1:
                    # Show percentage if there are multiple accounts
                    spend_text.append(f" ({percentage:.1f}% of total)", style="dim")
            else:
                spend_text.append("$0.00", style="dim")
        else:
            spend_text.append("Not available", style="dim")

        # Create grid for header info
        header_grid = TableFactory.create_grid_table(padding=0)  # Note: padding is handled differently
        header_grid.add_column()
        header_grid.add_column()

        header_grid.add_row(org_text, provider_text)
        header_grid.add_row(conn_text, status_text)
        header_grid.add_row(connected_text, None)
        header_grid.add_row(spend_text, None)
        header_grid.add_row(created_text, updated_text)
        header_grid.add_row(seen_text, None)

        return PanelFactory.create_header_panel(
            header_grid,
            title="Connection Summary",
            width=CONSOLE_WIDTH,
        )


class ConnectionTypeFormatter(HealthcheckFormatter):
    """Formats connection configuration with type, CUR stats, and regions."""

    @staticmethod
    def create(connection: dict[str, Any], healthcheck_result: dict[str, Any]) -> Table:
        """Create a table showing connection configuration overview."""
        # Determine connection type
        connection_type, type_description, type_icon = HealthStatus.get_connection_type_info(connection)
        is_master_payer = ConnectionUtils.is_payer_connection(connection)

        # Create main table with a cleaner structure
        config_table = TableFactory.create_standard_table(
            title="Connection Configuration",
            columns=[("Content", {"ratio": 1})],
            width=TABLE_WIDTH,
            show_header=False,
        )

        # Section 1: Connection Type and Details (full width)
        type_section = TableFactory.create_grid_table(padding=0)
        type_section.add_column(ratio=1)
        type_section.add_column(ratio=2)

        # Connection type with icon
        type_header = Text()
        type_header.append(f"{type_icon} ", style="bright_white")
        type_header.append(connection_type, style="bold bright_white")

        type_section.add_row(type_header, Text(type_description, style="dim"))

        config_table.add_row(type_section)
        config_table.add_row("")  # Spacer

        # Section 2: Three-column layout for stats
        stats_section = TableFactory.create_grid_table(padding=1)
        stats_section.add_column("CUR Statistics", ratio=1)
        stats_section.add_column("", width=6)  # Spacer column
        stats_section.add_column("Link Health", ratio=1)
        stats_section.add_column("", width=6)  # Spacer column
        stats_section.add_column("Active Regions", ratio=1)

        # CUR Stats Column
        # Extract data from healthcheck result
        details = healthcheck_result.get("details", {})
        cur_stats = details.get("cur_stats", healthcheck_result.get("cur_stats", {}))
        cur_content = TableFactory.create_grid_table(padding=0)
        cur_content.add_column()

        # Add CUR header
        cur_content.add_row(Text("📊 CUR Statistics", style="cyan bold"))
        cur_content.add_row("")  # Spacer

        cur_details = TableFactory.create_grid_table(padding=0)
        cur_details.add_column(style="dim", justify="left")
        cur_details.add_column(style="bright_white", justify="left")

        if cur_stats and is_master_payer:
            # Show all CUR metrics available
            metrics = [
                ("Last Drop", DateFormatter.format_datetime(cur_stats.get("cur_drop_datetime", ""))),
                ("Last Manifest", DateFormatter.format_datetime(cur_stats.get("manifest_datetime", ""))),
                ("Avg Frequency", f"{cur_stats.get('avg_cur_drop_time_current', 'N/A')} hrs"),
                ("Report Count", str(cur_stats.get("cur_report_count", 0))),
            ]

            # Add each metric if it has a meaningful value
            has_data = False
            for label, value in metrics:
                if value and value not in ["N/A", "Not available", "0", "N/A hrs"]:
                    cur_details.add_row(f"{label}:", value)
                    has_data = True

            # If we have cur_stats but no meaningful data, show that
            if not has_data:
                cur_details.add_row("", Text("No recent CUR data", style="dim italic"))
        else:
            if not is_master_payer:
                cur_details.add_row("", Text("Not applicable", style="dim italic"))
                cur_details.add_row("", Text("(Resource account)", style="dim italic"))
            else:
                cur_details.add_row("", Text("No CUR data available", style="dim italic"))

        cur_content.add_row(cur_details)

        # Link Health Column
        link_health = details.get("link_health", healthcheck_result.get("link_health", {}))
        link_content = TableFactory.create_grid_table(padding=0)
        link_content.add_column()

        # Add link health header
        link_content.add_row(Text("🔗 Link Health", style="cyan bold"))
        link_content.add_row("")  # Spacer

        if link_health:
            for link_type, link_data in link_health.items():
                if link_data:
                    is_healthy = link_data.get("is_healthy", False)
                    link_name = link_type.replace("_", " ").title()
                    status_icon = "✓" if is_healthy else "✗"
                    status_color = "green" if is_healthy else "red"

                    link_text = Text()
                    link_text.append(f"{status_icon} ", style=status_color)
                    link_text.append(link_name, style="bright_white")
                    link_content.add_row(link_text)
        else:
            link_content.add_row(Text("No link data", style="dim italic"))

        # Active Regions Column
        active_regions = connection.get("active_regions", [])
        primary_region = connection.get("connection_region")
        regions_content = TableFactory.create_grid_table(padding=0)
        regions_content.add_column(no_wrap=False)

        # Add regions header
        regions_content.add_row(Text("🌍 Active Regions", style="cyan bold"))
        regions_content.add_row("")  # Spacer

        if active_regions:
            # Show count and primary region
            region_summary = Text()
            region_summary.append(f"{len(active_regions)} regions", style="bright_white")
            if primary_region:
                region_summary.append(" | Primary: ", style="dim")
                region_summary.append(primary_region, style="green")
            regions_content.add_row(region_summary)

            # Show all regions
            sorted_regions = sorted(active_regions)

            regions_list = Text()
            for i, region in enumerate(sorted_regions):
                if i > 0:
                    regions_list.append(", ", style="dim")
                if region == primary_region:
                    regions_list.append(region, style="green")
                else:
                    regions_list.append(region, style="bright_white")

            regions_content.add_row(regions_list)
        else:
            regions_content.add_row(Text("No active regions", style="dim italic"))

        # Add the three-column section with spacers
        stats_section.add_row(cur_content, "", link_content, "", regions_content)
        config_table.add_row(stats_section)

        # Section 3: S3 Configuration (if applicable)
        if is_master_payer:
            bucket_name = connection.get("master_payer_billing_bucket_name")
            bucket_path = connection.get("master_payer_billing_bucket_path", "")

            if bucket_name:
                config_table.add_row("")  # Spacer

                # Create S3 section
                s3_section = TableFactory.create_grid_table(padding=0)
                s3_section.add_column()

                # Header
                s3_section.add_row(Text("💾 S3 Configuration", style="cyan bold"))
                s3_section.add_row("")  # Spacer

                # S3 details grid
                s3_details = TableFactory.create_grid_table(padding=0)
                s3_details.add_column(style="dim", justify="left", width=10)
                s3_details.add_column(style="bright_white", justify="left")

                s3_details.add_row("Bucket:", bucket_name)
                if bucket_path:
                    s3_details.add_row("Path:", bucket_path)

                # Add full S3 URI
                full_uri = f"s3://{bucket_name}/{bucket_path}" if bucket_path else f"s3://{bucket_name}/"
                s3_details.add_row("URI:", Text(full_uri, style="blue"))

                s3_section.add_row(s3_details)
                config_table.add_row(s3_section)

        return config_table


class PermissionsFormatter(HealthcheckFormatter):
    """Formats permission information."""

    @staticmethod
    def create(connection: dict[str, Any]) -> Panel | None:
        """Create a panel showing permission issues if any exist."""
        permission_errors = connection.get("permission_errors", [])

        if not permission_errors:
            return None

        # Convert to list if it's a string or other type
        if not isinstance(permission_errors, list):
            permission_errors = [str(permission_errors)]

        return PanelFactory.create_info_panel(
            "\n".join(permission_errors),
            title="Permission Warnings",
            style="yellow",
        )


class LinkHealthFormatter(HealthcheckFormatter):
    """Formats link health information for unhealthy links only."""

    @staticmethod
    def create(healthcheck_result: dict[str, Any]) -> Panel | None:
        """Create a panel showing details for unhealthy links."""
        # Extract data from healthcheck result
        details = healthcheck_result.get("details", {})
        link_health = details.get("link_health", healthcheck_result.get("link_health", {}))
        if not link_health:
            return None

        # Collect unhealthy links
        unhealthy_links = []
        for link_type, link_data in link_health.items():
            if link_data and not link_data.get("is_healthy", False):
                link_name = link_type.replace("_", " ").title()

                # Get detailed messages
                messages = link_data.get("messages", {})
                details = []
                for _msg_type, msg in messages.items():
                    if msg and msg != "Access role verified":  # Skip generic messages
                        details.append(msg)

                if details:
                    unhealthy_links.append(f"🔴 {link_name}:\n   {chr(10).join(f'   {d}' for d in details)}")

        # Only create panel if there are unhealthy links
        if not unhealthy_links:
            return None

        return PanelFactory.create_info_panel(
            "\n\n".join(unhealthy_links),
            title="Link Health Issues",
            style="red",
            width=CONSOLE_WIDTH,
        )


class InfrastructureFormatter(HealthcheckFormatter):
    """Formats AWS infrastructure information (CUR stats and regions)."""

    @staticmethod
    def _is_cost_connection(connection: dict[str, Any]) -> bool:
        """Check if connection is a cost connection, handling both V4 and legacy API formats."""
        connection_details = connection.get("connection_details", {})
        return connection_details.get("is_cost_connection") or connection.get("is_cost_connection", False)

    @staticmethod
    def create_cur_stats_table(cur_stats: dict[str, Any]) -> Table | Text:
        """Create a table showing CUR statistics."""
        if not cur_stats:
            return Text("No CUR statistics available", style="dim")

        cur_stats_table = Table(show_header=True, header_style="bright_white", box=None)

        cur_stats_table.add_column("Metric", style="cyan", justify="left")
        cur_stats_table.add_column("Value", style="bright_white", justify="left")

        metrics = [
            ("Last CUR Drop", DateFormatter.format_datetime(cur_stats.get("cur_drop_datetime", ""))),
            ("Last Manifest Update", DateFormatter.format_datetime(cur_stats.get("manifest_datetime", ""))),
            ("Avg Drop (Current Month)", f"Every {cur_stats.get('avg_cur_drop_time_current', 'N/A')} hours"),
            ("Avg Drop (Previous Month)", f"Every {cur_stats.get('avg_cur_drop_time_previous', 'N/A')} hours"),
            ("CUR Report Count", str(cur_stats.get("cur_report_count", 0))),
            ("Current Manifest", cur_stats.get("cur_current_manifest", "N/A")),
        ]

        for label, value in metrics:
            cur_stats_table.add_row(label, value)

        return cur_stats_table

    @staticmethod
    def create_regions_table(active_regions: list[str], inactive_regions: list[str]) -> Table | Text:
        """Create a table showing active and inactive regions."""
        if not active_regions and not inactive_regions:
            return Text("No region information available", style="dim")

        region_table = Table(show_header=True, header_style="bright_white", box=None)

        region_table.add_column("Status", justify="center", width=8)
        region_table.add_column("Region", style="bright_white", justify="left")

        # Add active regions first (limited to top 10 for space)
        active_count = len(active_regions)
        for region in sorted(active_regions)[:10]:
            region_table.add_row("🟢", region)

        # Show count if we have more than can display
        if active_count > 10:
            region_table.add_row("", f"+ {active_count - 10} more active regions")

        # Add separator if we have both active and inactive regions
        if active_regions and inactive_regions:
            region_table.add_row("", "")

        # Add inactive regions (limited to top 5 for space)
        inactive_count = len(inactive_regions)
        for region in sorted(inactive_regions)[:5]:
            region_table.add_row("⚫", region)

        # Show count if we have more than can display
        if inactive_count > 5:
            region_table.add_row("", f"+ {inactive_count - 5} more inactive regions")

        return region_table

    @staticmethod
    def create(connection: dict[str, Any], healthcheck_result: dict[str, Any]) -> Table | None:
        """Create a combined table showing AWS infrastructure overview."""
        cur_stats = healthcheck_result.get("cur_stats")
        active_regions = connection.get("active_regions", [])
        inactive_regions = connection.get("inactive_regions", [])

        # Skip if we don't have data
        if not ((cur_stats and InfrastructureFormatter._is_cost_connection(connection)) or active_regions or inactive_regions):
            return None

        # Create main combined table
        combined_table = Table(
            title="AWS Infrastructure Overview",
            title_justify="left",
            box=box.ROUNDED,
            title_style="cyan",
            show_header=False,
            width=TABLE_WIDTH,
        )

        # Create two columns with appropriate ratios
        combined_table.add_column("CUR Stats", ratio=1)
        combined_table.add_column("Regions", ratio=1)

        # Create CUR stats content
        cur_content = InfrastructureFormatter.create_cur_stats_table(cur_stats if InfrastructureFormatter._is_cost_connection(connection) else None)

        # Create regions content
        region_content = InfrastructureFormatter.create_regions_table(active_regions, inactive_regions)

        # Add both components to the combined table
        combined_table.add_row(cur_content, region_content)
        return combined_table


class RoleInfoFormatter(HealthcheckFormatter):
    """Formats IAM role information."""

    @staticmethod
    def format_role_details(role_data: dict[str, Any], role_name: str) -> Table | None:
        """Format role details into a table."""
        if not role_data:
            return None

        role_info = role_data.get("role_data", {})
        if not role_info:
            return None

        # Get policy information
        policies = role_data.get("role_policies", {})
        inline_policies = role_data.get("inline_policies", {})

        # Create a combined table for role details and policies
        combined_table = Table(
            title=f"{role_name}",
            title_justify="left",
            box=box.ROUNDED,
            title_style="cyan",
            show_header=False,
            width=TABLE_WIDTH,
        )

        # Create two columns for the layout
        combined_table.add_column("Details", ratio=1)
        combined_table.add_column("Policies", ratio=1)

        # Create role details grid
        details_grid = TableFactory.create_grid_table()
        details_grid.add_column(style="cyan", justify="right")
        details_grid.add_column(style="bright_white", justify="left")

        # Add role details
        details = [
            ("Role Name:", role_info.get("RoleName", "N/A")),
            ("ARN:", role_info.get("Arn", "N/A")),
            ("Role ID:", role_info.get("RoleId", "N/A")),
            ("Path:", role_info.get("Path", "N/A")),
            ("Created:", DateFormatter.format_datetime(role_info.get("CreateDate", ""))),
            ("Max Session Duration:", f"{role_info.get('MaxSessionDuration', 0) // 60} minutes"),
        ]

        # Add last used info if available
        role_last_used = role_info.get("RoleLastUsed", {})
        if role_last_used:
            details.append(("Last Used Date:", DateFormatter.format_datetime(role_last_used.get("LastUsedDate", ""))))
            details.append(("Last Used Region:", role_last_used.get("Region", "N/A")))

        # Add all details to the grid
        for label, value in details:
            details_grid.add_row(label, value)

        # Create policies table
        policy_table = Table(width=None, show_header=True, header_style="bright_white", box=None)

        policy_table.add_column("Policy Name", style="bright_white", justify="left")
        policy_table.add_column("Type", style="cyan", justify="center", width=12)
        policy_table.add_column("ARN / Details", style="green", justify="left")

        # Add AWS managed policies
        for policy_name, policy_data in policies.items():
            policy_table.add_row(policy_name, "AWS Managed", policy_data.get("arn", "N/A"))

        # Add inline policies
        for policy_name, policy_data in inline_policies.items():
            policy_table.add_row(policy_name, "Inline", f"Attached to {policy_data.get('role_name', 'unknown role')}")

        # If no policies, add a message
        if not policies and not inline_policies:
            policy_table = Text("No policies attached to this role", style="dim")

        # Add the details and policies to the combined table
        combined_table.add_row(details_grid, policy_table)
        return combined_table

    @staticmethod
    def create(healthcheck_result: dict[str, Any]) -> list[Table]:
        """Create tables showing IAM role information."""
        # Extract data from healthcheck result
        details = healthcheck_result.get("details", {})
        role_metadata = details.get("role_metadata", healthcheck_result.get("role_metadata", {}))
        if not role_metadata:
            return []

        tables = []

        # Process resource owner role if present
        resource_role = role_metadata.get("resource_role", {})
        resource_table = RoleInfoFormatter.format_role_details(resource_role, "Resource Owner Role")
        if resource_table:
            tables.append(resource_table)

        # Process master payer role if present
        master_payer = role_metadata.get("master_payer", {})
        master_table = RoleInfoFormatter.format_role_details(master_payer, "Master Payer Role")
        if master_table:
            tables.append(master_table)

        return tables


class CURFormatter(HealthcheckFormatter):
    """Formats CUR (Cost and Usage Report) information."""

    @staticmethod
    def create_cur_table(connection: dict[str, Any], healthcheck_result: dict[str, Any]) -> Table | None:
        """Create a table showing CUR configurations."""
        # V4 API stores CUR data in connection_details.cur_configurations
        # Legacy API used cur_metadata at the top level
        connection_details = connection.get("connection_details", {})

        # Check if this is a cost connection (payer account)
        # V4 API stores this in connection_details, legacy at top level
        is_cost_connection = connection_details.get("is_cost_connection") or connection.get("is_cost_connection", False)
        if not is_cost_connection:
            return None

        cur_metadata = connection_details.get("cur_configurations") or connection.get("cur_metadata", {})
        if not cur_metadata:
            return None

        # Get CUR health data
        # Extract data from healthcheck result
        details = healthcheck_result.get("details", {})
        cur_health = details.get("cur_health", healthcheck_result.get("cur_health", {}))

        # Create CUR table
        cur_table = Table(
            title="Cost and Usage Reports",
            title_justify="left",
            box=box.ROUNDED,
            title_style="cyan",
            show_header=True,
            header_style="bright_white",
            width=TABLE_WIDTH,
        )

        cur_table.add_column("Report Name", style="bright_white", justify="left", ratio=2)
        cur_table.add_column("Compatible", justify="center", width=10)
        cur_table.add_column("S3", justify="center", width=8)
        cur_table.add_column("Time Unit", style="bright_white", justify="left", width=10)
        cur_table.add_column("Format", style="bright_white", justify="left", width=10)
        cur_table.add_column("Features", style="bright_white", justify="left", ratio=3, overflow="fold")
        cur_table.add_column("S3 Location", style="bright_white", justify="left", ratio=3, overflow="fold")

        # Get connected report name
        connected_report = connection.get("master_payer_billing_report_name")

        # Add each CUR report
        for report_name, report_data in cur_metadata.items():
            # Skip if it's not a dictionary (e.g., cur_stats)
            if not isinstance(report_data, dict):
                continue

            is_connected = report_name == connected_report
            name_style = "green" if is_connected else "bright_white"

            # Determine health status
            is_healthy = cur_health.get(report_name, {}).get("healthy", False)
            bucket_healthy = cur_health.get(report_name, {}).get("bucket_healthy", False)

            # Format schema elements - use full names
            schema_elements = report_data.get("AdditionalSchemaElements", [])
            features = ConnectionUtils.format_cur_features(schema_elements)

            # Format S3 location
            s3_bucket = report_data.get("S3Bucket", "")
            s3_prefix = report_data.get("S3Prefix", "")
            s3_location = f"{s3_bucket}/{s3_prefix}" if s3_bucket and s3_prefix else "Unknown"

            # Format the format column with color coding
            format_value = report_data.get("Format", "Unknown")
            if format_value == "Parquet":
                format_text = Text(format_value, style="bright_cyan")
            elif format_value == "textORcsv":
                format_text = Text(format_value, style="bright_green")
            else:
                format_text = Text(format_value, style="bright_white")

            cur_table.add_row(
                Text(f"{report_name}{' (CONNECTED)' if is_connected else ''}", style=name_style),
                CURFormatter.get_health_icon(is_healthy),
                CURFormatter.get_health_icon(bucket_healthy),
                report_data.get("TimeUnit", "Unknown"),
                format_text,
                features,
                s3_location,
            )

        return cur_table

    @staticmethod
    def create_cur_health_table(healthcheck_result: dict[str, Any]) -> Table | None:
        """Create a table showing CUR health details."""
        cur_health = healthcheck_result.get("cur_health", {})
        if not cur_health:
            return None

        cur_health_table = Table(
            title="Cost and Usage Report Health",
            title_justify="left",
            box=box.ROUNDED,
            title_style="cyan",
            show_header=True,
            header_style="bright_white",
            width=TABLE_WIDTH,
        )

        cur_health_table.add_column("Report Name", style="bright_white", justify="left")
        cur_health_table.add_column("Status", justify="center", width=8)
        cur_health_table.add_column("S3 Bucket", justify="center", width=8)
        cur_health_table.add_column("Details", style="bright_white", justify="left")

        for report_name, health_data in cur_health.items():
            is_healthy = health_data.get("healthy", False)
            bucket_healthy = health_data.get("bucket_healthy", False)

            reason = health_data.get("reason", "No details available")
            bucket_reason = health_data.get("bucket_reason", "")

            details = []
            if reason and reason != "Cost and usage report correctly configured":
                details.append(reason)
            if bucket_reason and "verified" not in bucket_reason:
                details.append(bucket_reason)

            detail_text = "\n".join(details) if details else "No issues found"

            cur_health_table.add_row(
                report_name,
                CURFormatter.get_health_icon(is_healthy),
                CURFormatter.get_health_icon(bucket_healthy),
                detail_text,
            )

        return cur_health_table

    @staticmethod
    def create_s3_config_panel(connection: dict[str, Any]) -> Panel | None:
        """Create a panel showing S3 bucket configuration for CUR."""
        bucket_name = connection.get("master_payer_billing_bucket_name")
        if not bucket_name:
            return None

        bucket_path = connection.get("master_payer_billing_bucket_path", "")

        # Create a more informative S3 location panel
        s3_details = []
        s3_details.append(f"[cyan]Bucket:[/] {bucket_name}")
        s3_details.append(f"[cyan]Path:[/] {bucket_path}")
        s3_details.append(f"[cyan]Full URI:[/] s3://{bucket_name}/{bucket_path}")

        # Add information about compression and formats if available
        compression_types = set()
        additional_artifacts = set()
        schema_elements = set()

        # V4 API stores CUR data in connection_details.cur_configurations
        # Legacy API used cur_metadata at the top level
        connection_details = connection.get("connection_details", {})
        cur_metadata = connection_details.get("cur_configurations") or connection.get("cur_metadata", {})
        for report_data in cur_metadata.values():
            if isinstance(report_data, dict):
                if compression := report_data.get("Compression"):
                    compression_types.add(compression)
                if artifacts := report_data.get("AdditionalArtifacts"):
                    additional_artifacts.update(artifacts)
                if elements := report_data.get("AdditionalSchemaElements"):
                    schema_elements.update(elements)

        if compression_types:
            s3_details.append(f"[cyan]Compression:[/] {', '.join(compression_types)}")
        if additional_artifacts:
            s3_details.append(f"[cyan]Additional Artifacts:[/] {', '.join(additional_artifacts)}")
        if schema_elements:
            s3_details.append(f"[cyan]Schema Elements:[/] {', '.join(schema_elements)}")

        return PanelFactory.create_info_panel(
            "\n".join(s3_details),
            title="CUR S3 Configuration",
            style="blue",
            width=CONSOLE_WIDTH,
        )

    @staticmethod
    def create_spend_table(healthcheck_result: dict[str, Any]) -> Table | None:
        """Create a table showing 30-day spend summary."""
        # Extract data from healthcheck result
        details = healthcheck_result.get("details", {})
        spend_data = details.get("30_day_spend", healthcheck_result.get("30_day_spend"))
        if not spend_data or len(spend_data) <= 1:
            return None

        # Sort accounts by spend amount (highest first)
        sorted_accounts = sorted([(account_id, amount) for account_id, amount in spend_data.items()], key=lambda x: x[1], reverse=True)

        # Calculate total spend
        total_spend = sum(amount for _, amount in sorted_accounts)

        # Get top accounts (at most 10)
        top_accounts = sorted_accounts[:10]

        spend_table = Table(
            title=f"30-Day AWS Spend Summary (Total: ${total_spend:,.2f})",
            title_justify="left",
            box=box.ROUNDED,
            title_style="cyan",
            show_header=True,
            header_style="bright_white",
            width=TABLE_WIDTH,
        )

        spend_table.add_column("Account ID", style="bright_white", justify="left")
        spend_table.add_column("Spend (USD)", style="green", justify="right")
        spend_table.add_column("% of Total", style="cyan", justify="right")

        # Add rows for top accounts
        for account_id, amount in top_accounts:
            percentage = (amount / total_spend) * 100
            spend_table.add_row(account_id, f"${amount:,.2f}", f"{percentage:.1f}%")

        if len(sorted_accounts) > 10:
            # Add a row for "Other" accounts
            other_accounts = sorted_accounts[10:]
            other_sum = sum(amount for _, amount in other_accounts)
            other_percentage = (other_sum / total_spend) * 100

            spend_table.add_row(f"Other ({len(other_accounts)} accounts)", f"${other_sum:,.2f}", f"{other_percentage:.1f}%")

        return spend_table

    @staticmethod
    def create(connection: dict[str, Any], healthcheck_result: dict[str, Any]) -> list[Table | Panel]:
        """Create all CUR-related tables and panels."""
        result = []

        # CUR reports table
        cur_table = CURFormatter.create_cur_table(connection, healthcheck_result)
        if cur_table:
            result.append(cur_table)

        # Spend summary table
        spend_table = CURFormatter.create_spend_table(healthcheck_result)
        if spend_table:
            result.append(spend_table)

        return result


# ------------------------------------------------------------------------------------------------
# HEALTHCHECK COMPONENTS
# ------------------------------------------------------------------------------------------------


class HealthcheckRenderer:
    """Renders healthcheck information to the console."""

    def __init__(self, connection: dict[str, Any], healthcheck_result: dict[str, Any]):
        """Initialize with connection and healthcheck data."""
        self.connection = connection
        self.healthcheck_result = healthcheck_result

    def render_all(self, show_roles: bool = False) -> None:
        """Render all healthcheck information to the console."""
        # Add extra spacing
        console.print()

        # 1. Connection header with basic information
        header = ConnectionHeader.create(self.connection, self.healthcheck_result)
        console.print(header)

        # 2. Healthcheck details from API (if available)
        healthcheck_details = HealthcheckDetailsFormatter.create(self.healthcheck_result)
        if healthcheck_details:
            console.print(healthcheck_details)

        # 3. Connection type and configuration
        type_table = ConnectionTypeFormatter.create(self.connection, self.healthcheck_result)
        console.print(type_table)

        # 4. Link health issues (if any unhealthy links)
        link_health_panel = LinkHealthFormatter.create(self.healthcheck_result)
        if link_health_panel:
            console.print(link_health_panel)

        # 5. Permission warnings (if any)
        permissions_panel = PermissionsFormatter.create(self.connection)
        if permissions_panel:
            console.print(permissions_panel)

        # 6. CUR information (if applicable)
        cur_components = CURFormatter.create(self.connection, self.healthcheck_result)
        for component in cur_components:
            console.print(component)

        # 7. IAM role information (only if --show-roles flag is provided)
        if show_roles:
            role_tables = RoleInfoFormatter.create(self.healthcheck_result)
            for table in role_tables:
                console.print(table)

        # Add extra spacing
        console.print()


class HealthcheckManager:
    """Manages the overall healthcheck process."""

    @staticmethod
    def fetch_connections(arguments: dict[str, Any], organization_data: dict[str, Any] = None) -> dict[str, dict[str, dict[str, Any]]]:
        """Fetch connections based on arguments and organization data."""
        connections_to_check = {}

        # Create welcome panel
        console.print(
            PanelFactory.create_header_panel(
                "[bold]CloudZero Connection Healthcheck[/bold]\nChecking connection health, permissions, and configuration",
                title="Connection Healthcheck",
                width=CONSOLE_WIDTH,
                border_style="green",
            )
        )

        # Debug flag will add extra debugging info to connection objects
        is_debug = arguments.get("--debug", False)

        # Case 1: Specific connection ID provided
        if connection_id := arguments.get("<ID-or-NAME>"):
            try:
                connection_v4 = get_connection(connection_id, debug=is_debug)
                # Convert to legacy format for backward compatibility
                if connection_v4:
                    connection_response = {
                        "cz_organization_ids": [connection_v4.cz_organization_id],
                        "data": {connection_v4.cz_organization_id: {connection_id: connection_v4.model_dump()}},
                    }
                else:
                    connection_response = {}
            except Exception:
                connection_response = {}

            # If no connection found, try to interpret input as an organization ID or name
            if not connection_response.get("cz_organization_ids"):
                if is_debug:
                    eprint(f"Debug - Connection response: {connection_response}")
                    eprint(f"Debug - No connection found with ID: {connection_id}. Trying as organization ID/name.")

                # Try to find organization by the provided ID or name
                # Use direct API call to avoid the error handler that exits the program
                try:
                    from src.utils.core import is_valid_uuid

                    if is_valid_uuid(connection_id):
                        # Try to get specific org by ID
                        org_response = get_organizations(organization_query=connection_id, debug=is_debug, enabled_only=False)
                        if org_response and connection_id in org_response:
                            org_data = {connection_id: org_response[connection_id].model_dump()}
                        else:
                            org_data = None
                    else:
                        # Search by name - use API server-side search (same as org info command)
                        org_response = get_organizations(organization_query=connection_id, debug=is_debug, enabled_only=False)
                        if org_response:
                            # Convert to dict format
                            org_data = {}
                            for org_id, org_details in org_response.items():
                                org_data[org_id] = org_details.model_dump()
                        else:
                            org_data = None
                except Exception as e:
                    if is_debug:
                        eprint(f"[yellow]Debug: Failed to load organization data: {e}[/]")
                        eprint("[yellow]Debug: Continuing healthcheck without organization data[/]")
                    org_data = None

                if org_data:
                    # Get the first/only organization ID
                    org_id = list(org_data.keys())[0]
                    # V4 API uses cz_organization_name, legacy uses organization_name
                    org_name = org_data[org_id].get("cz_organization_name") or org_data[org_id].get("organization_name", "Unknown")

                    # Fetch all connections for this organization
                    try:
                        connections_list = get_connections_for_org(org_id, debug=is_debug)

                        # Convert ConnectionDetails objects to dictionary format
                        # Use composite key (connection_id|connection_type) to handle connections with multiple types
                        # This prevents COST and RESOURCE records for the same account from overwriting each other
                        org_connections_data = {}
                        for conn in connections_list:
                            composite_key = f"{conn.connection_id}|{conn.connection_type}"
                            org_connections_data[composite_key] = conn.model_dump()
                    except Exception as e:
                        # Don't silently swallow errors - show them to the user
                        console.print(f"[red]Error fetching connections for organization: {e}[/]")
                        if is_debug:
                            console.print_exception()
                        org_connections_data = {}

                    # Filter only AWS payer connections
                    payer_connections = {}
                    for conn_id, conn in org_connections_data.items():
                        # V4 API uses 'provider', legacy uses 'cloud_provider'
                        provider = conn.get("provider") or conn.get("cloud_provider", "")

                        # Check multiple indicators for cost/payer connection:
                        # 1. connection_type == 'COST' (V4 API - primary indicator)
                        # 2. is_cost_connection == True (legacy or connection_details)
                        # 3. account_type == 'payer' (legacy)
                        connection_type = conn.get("connection_type", "")
                        connection_details = conn.get("connection_details", {})
                        is_cost = (
                            connection_type == "COST"
                            or connection_details.get("is_cost_connection")
                            or conn.get("is_cost_connection", False)
                            or conn.get("account_type") == "payer"
                        )

                        if provider in HEALTHCHECK_SUPPORTED_PROVIDERS and is_cost:
                            payer_connections[conn_id] = conn

                    payer_count = len(payer_connections)

                    if payer_count == 0:
                        console.print(f"[yellow]Organization '{org_name}' found, but it has no AWS payer connections that support healthchecking.[/]")
                        console.print("[yellow]Only AWS payer accounts can be healthchecked at this time.[/]")
                        sys.exit(1)
                    elif payer_count == 1:
                        # Exactly one payer - use it
                        payer_id = list(payer_connections.keys())[0]
                        payer_conn = payer_connections[payer_id]
                        payer_name = payer_conn.get("connection_name") or payer_conn.get("cz_account_name", "Unknown")
                        console.print(f"[green]Found single AWS payer connection '{payer_name}' for organization '{org_name}'.[/]")

                        # Set up data to use the single payer connection
                        connection_response = {"cz_organization_ids": [org_id], "data": {org_id: payer_connections}}
                    else:
                        # Multiple payers - show list and exit
                        console.print(f"[yellow]Organization '{org_name}' has multiple payer connections. Please specify which one to check:[/]")

                        # Create table to display payer options
                        payer_table = Table(
                            title=f"Payer Connections for {org_name}",
                            box=box.ROUNDED,
                            header_style="bright_white",
                            title_style="cyan",
                        )

                        payer_table.add_column("Connection ID", style="yellow")
                        payer_table.add_column("Connection Name", style="bright_white")
                        payer_table.add_column("Provider", style="cyan")

                        for conn_id, conn in payer_connections.items():
                            conn_name = conn.get("connection_name") or conn.get("cz_account_name", "Unknown")
                            provider = conn.get("provider") or conn.get("cloud_provider", "Unknown")
                            payer_table.add_row(conn_id, conn_name, provider)

                        console.print(payer_table)
                        console.print("[yellow]Run:[/] [cyan]czops connection healthcheck [yellow]<CONNECTION_ID>[/]")
                        sys.exit(1)
                else:
                    console.print(f"[red]Error: Could not find connection '{connection_id}' or any organization with that name/ID[/]")
                    console.print(
                        f"[yellow]Hint: If '{connection_id}' is a valid AWS account ID, verify the connection exists and you have permissions to access it[/]"
                    )
                    sys.exit(1)

            org_id = connection_response.get("cz_organization_ids")[0]
            connections_data = connection_response.get("data", {})

            # Ensure that the connection in connections_data has the cloud_account_id field
            # The get_connection API may return the data with the connection ID as the key
            # This ensures we have the connection data with proper structure
            for org_connections in connections_data.values():
                for conn_id, conn_data in org_connections.items():
                    # Add cloud_account_id if it doesn't exist
                    if "cloud_account_id" not in conn_data:
                        conn_data["cloud_account_id"] = conn_id
                    # Add debug flag if debugging
                    if is_debug:
                        conn_data["__debug"] = True

            connections_to_check[org_id] = connections_data.get(org_id, {})

            # Get organization data if not provided (but continue if it fails)
            # Use direct API call to avoid the error handler that exits the program
            if not organization_data:
                try:
                    org_response = get_organizations(organization_query=org_id, debug=arguments.get("--debug"), enabled_only=False)
                    organization_data = {org_id: org_response[org_id].model_dump()} if org_response and org_id in org_response else {}
                except Exception as e:
                    if arguments.get("--debug"):
                        eprint(f"[yellow]Debug: Failed to load organization data: {e}[/]")
                        eprint("[yellow]Debug: Continuing with healthcheck without organization data[/]")
                    # Set to empty dict so we don't try again
                    organization_data = {}

        # Case 2: Use existing organization data
        elif organization_data:
            for org_id in organization_data:
                try:
                    connections_list = get_connections_for_org(org_id, debug=is_debug)
                    # Convert to legacy format
                    connections_data = {org_id: {conn["connection_id"]: conn for conn in connections_list}}
                except Exception as e:
                    # Don't silently swallow errors - show them to the user
                    console.print(f"[red]Error fetching connections for organization {org_id}: {e}[/]")
                    if is_debug:
                        console.print_exception()
                    connections_data = {}

                # Ensure all connections have cloud_account_id
                if org_id in connections_data:
                    for conn_id, conn_data in connections_data[org_id].items():
                        if "cloud_account_id" not in conn_data:
                            conn_data["cloud_account_id"] = conn_id
                        # Add debug flag if debugging
                        if is_debug:
                            conn_data["__debug"] = True

                connections_to_check[org_id] = connections_data.get(org_id, {})

        # Case 3: No data provided
        else:
            console.print("[red]Error: No organization or connection provided[/]")
            sys.exit(1)

        return connections_to_check

    @staticmethod
    def process_connections(connections: dict[str, dict[str, dict[str, Any]]], arguments: dict[str, Any]) -> dict[str, dict[str, dict[str, Any]]]:
        """Process connections by adding healthcheck data."""
        # Count connections to check
        connection_count = sum(len(connections_data) for connections_data in connections.values())
        processed_connections = {}

        # Check if batch API is disabled
        use_batch = not arguments.get("--no-batch", False)

        # Check health with progress indicator
        with Progress(
            SpinnerColumn(),
            TextColumn("[cyan]Running healthcheck... [bright_white]{task.completed}/{task.total}[/]"),
            TextColumn("[dim]|[/]"),
            TextColumn("[yellow]{task.description}[/]"),
            console=console,
        ) as progress:
            task = progress.add_task("Checking connections...", total=connection_count)

            # Define progress callback
            def update_progress():
                progress.advance(task)

            # Use batch processing
            processed_connections = HealthcheckData.process_connection_batch(
                connections, progress_callback=update_progress, use_batch_api=use_batch, progress_task=task, progress_obj=progress
            )

        return processed_connections

    @staticmethod
    def display_connections(connections: dict[str, dict[str, dict[str, Any]]], arguments: dict[str, Any]) -> None:
        """Display healthcheck information for connections."""
        # Check for export options
        export_file = arguments.get("-o") or arguments.get("--output")

        if export_file:
            # Determine export format from file extension
            if export_file.endswith(".json"):
                HealthcheckManager.export_json(connections, export_file)
            elif export_file.endswith(".csv"):
                HealthcheckManager.export_csv(connections, export_file)
            else:
                console.print("[red]Unsupported export format. Use .json or .csv extension.[/]")
                sys.exit(1)
            return

        # Display raw results if requested
        if arguments.get("--raw"):
            pprint(connections)
            return

        # Use new compact display
        from src.features.connections.healthcheck_display import display_healthcheck

        # Process each connection and display results
        for _org_id, org_connections in connections.items():
            for _conn_id, connection in org_connections.items():
                # Get healthcheck_result
                healthcheck_result = connection.get("healthcheck_result", {})

                if healthcheck_result:
                    display_healthcheck(healthcheck_result)
                else:
                    console.print("[yellow]No healthcheck data available for this connection[/]")

    @staticmethod
    def export_json(connections: dict[str, dict[str, dict[str, Any]]], filename: str) -> None:
        """Export healthcheck results to JSON file."""
        try:
            with open(filename, "w") as f:
                json.dump(connections, f, indent=2, default=str)
            console.print(f"[green]✅ Healthcheck results exported to {filename}[/]")
        except Exception as e:
            console.print(f"[red]Error exporting to JSON: {e}[/]")
            sys.exit(1)

    @staticmethod
    def export_csv(connections: dict[str, dict[str, dict[str, Any]]], filename: str) -> None:
        """Export healthcheck results to CSV file."""
        try:
            # Flatten the nested data structure for CSV
            rows = []
            for org_id, org_connections in connections.items():
                for conn_id, connection in org_connections.items():
                    row = {
                        "organization_id": org_id,
                        "organization_name": connection.get("cz_organization_name", "Unknown"),
                        "connection_id": conn_id,
                        "connection_name": connection.get("cz_account_name", "Unknown"),
                        "cloud_provider": connection.get("cloud_provider", "Unknown"),
                        "is_connected": connection.get("is_connected", False),
                        "is_healthy": connection.get("is_healthy", False),
                        "account_type": connection.get("account_type", "Unknown"),
                        "last_updated": connection.get("last_updated", ""),
                        "created": connection.get("created", ""),
                    }

                    # Add healthcheck result data if available
                    healthcheck = connection.get("healthcheck_result", {})
                    if healthcheck:
                        row["has_permission_errors"] = bool(healthcheck.get("permission_errors"))
                        row["link_health_status"] = healthcheck.get("link_health", {}).get("status", "Unknown")

                        # CUR stats
                        cur_stats = healthcheck.get("cur_stats", {})
                        if cur_stats:
                            row["last_cur_drop"] = cur_stats.get("cur_drop_datetime", "")
                            row["avg_cur_drop_time"] = cur_stats.get("avg_cur_drop_time_current", "")

                    rows.append(row)

            if not rows:
                console.print("[yellow]No data to export[/]")
                return

            # Write CSV file
            with open(filename, "w", newline="") as f:
                writer = csv.DictWriter(f, fieldnames=rows[0].keys())
                writer.writeheader()
                writer.writerows(rows)

            console.print(f"[green]✅ Healthcheck results exported to {filename}[/]")
        except Exception as e:
            console.print(f"[red]Error exporting to CSV: {e}[/]")
            sys.exit(1)


# ------------------------------------------------------------------------------------------------
# COMMAND FUNCTION
# ------------------------------------------------------------------------------------------------


def functions(arguments: dict[str, Any], organization_data: dict[str, Any] = None) -> None:
    """Main function for the healthcheck command."""
    # Get current terminal width for responsive display
    global CONSOLE_WIDTH, TABLE_WIDTH
    current_width = console.width
    if current_width:
        CONSOLE_WIDTH = current_width
        TABLE_WIDTH = CONSOLE_WIDTH - 4  # Account for panel borders/padding

    # If organization_data is None, initialize it to an empty dict to prevent issues
    # Organization data is helpful but not essential for healthcheck
    if organization_data is None:
        organization_data = {}

    try:
        # 1. Fetch connections based on arguments
        connections = HealthcheckManager.fetch_connections(arguments, organization_data)

        # Debug the connections object
        if arguments.get("--debug"):
            # Print the structure of the connections dictionary
            eprint("\nConnections structure after fetch:")
            for org_id, org_connections in connections.items():
                eprint(f"Organization ID: {org_id}")
                if isinstance(org_connections, dict):
                    eprint(f"  Connection count: {len(org_connections)}")
                    for conn_id, conn_data in org_connections.items():
                        eprint(f"  Connection ID: {conn_id}")
                        if isinstance(conn_data, dict) and "cloud_account_id" in conn_data:
                            eprint(f"    cloud_account_id: {conn_data['cloud_account_id']}")
                        else:
                            eprint("    Missing cloud_account_id field")
                else:
                    eprint(f"  Org connections not a dictionary: {type(org_connections)}")

        # Check if connections is empty or all empty organizations
        has_connections = False
        for org_id, org_connections in connections.items():
            if org_connections:
                has_connections = True
                break

        if not has_connections:
            from src.utils.console import print_error_image

            print_error_image(
                context=f"No valid connections found for ID: {arguments.get('<ID-or-NAME>')}\n\n"
                f"Please verify the connection ID and try again.\n"
                f"If the issue persists, please report this to #cz-tools.",
                error_type="healthcheck",
            )
            sys.exit(1)

        # 2. Process connections by adding healthcheck data
        processed_connections = HealthcheckManager.process_connections(connections, arguments)

        # 3. Display results
        HealthcheckManager.display_connections(processed_connections, arguments)

        # Summary metrics functionality has been removed

    except Exception as error:
        from src.utils.console import print_error_image

        print_error_image(
            context=f"An error occurred during healthcheck: {str(error)}\n\n"
            f"Try running your command again with --debug for more information.\n"
            f"If the issue persists, please report this to #cz-tools.",
            error_type="healthcheck",
        )
        if arguments.get("--debug"):
            console.print_exception()
        sys.exit(1)
