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

"""
System command utilities for CloudZero Operations CLI.

This module provides hidden system commands for:
- metadata: Display CLI and services version information
- refresh-cache: Refresh backend cache and show statistics
- health: Check system health status
- reset-database: ⚠️ Reset backend cache - clears all cached data (auto-regenerates)
"""

import json
import sys

from rich.console import Console
from rich.json import JSON
from rich.pretty import pprint

from src.api.v4_system import drop_system_database, get_system_health, get_system_metadata, get_system_refresh
from src.exceptions import APIError
from src.utils.console import eprint, print_info

# Initialize console for full-width output
console = Console(width=None)


def display_metadata(arguments: dict):
    """Display system metadata including CLI and services version information."""
    debug_mode = arguments.get("--debug", False)

    try:
        print_info("Fetching system metadata...")
        metadata = get_system_metadata(debug=debug_mode)

        # Convert SystemMetadata object to dict for compatibility
        metadata = metadata.model_dump()

        if debug_mode:
            console.print("\n[cyan]Raw API Response:[/]")
            console.print(JSON(json.dumps(metadata)))

        # Display comprehensive summary
        console.print("\n[bold cyan]═══ CloudZero System Metadata ═══[/]\n")

        # Add CLI version from local import
        from src import __version__ as cli_version

        # Group and display all data by category
        # Version Information
        console.print("[bold yellow]Version Information:[/]")
        console.print(f"  • CZ-OPS CLI: [green]{cli_version}[/]")

        # Display all version-related fields
        version_fields = ["cz_ops_services", "version", "services_version", "api_version", "build", "build_date"]
        for field in version_fields:
            if field in metadata:
                display_name = field.replace("_", " ").title()
                console.print(f"  • {display_name}: [green]{metadata[field]}[/]")

        # Service Information
        service_fields = ["service", "service_name", "application", "component"]
        service_data = {k: v for k, v in metadata.items() if k in service_fields}
        if service_data:
            console.print("\n[bold yellow]Service Information:[/]")
            for key, value in service_data.items():
                display_name = key.replace("_", " ").title()
                console.print(f"  • {display_name}: [cyan]{value}[/]")

        # Environment Information
        env_fields = ["environment", "region", "deployment", "stage", "account", "account_id", "aws_region"]
        env_data = {k: v for k, v in metadata.items() if k in env_fields}
        if env_data:
            console.print("\n[bold yellow]Environment Information:[/]")
            for key, value in env_data.items():
                display_name = key.replace("_", " ").title()
                console.print(f"  • {display_name}: [magenta]{value}[/]")

        # Time Information
        time_fields = ["timestamp", "last_updated", "created_at", "modified_at", "deployed_at"]
        time_data = {k: v for k, v in metadata.items() if k in time_fields}
        if time_data:
            console.print("\n[bold yellow]Time Information:[/]")
            for key, value in time_data.items():
                display_name = key.replace("_", " ").title()
                console.print(f"  • {display_name}: [blue]{value}[/]")

        # Status Information
        status_fields = ["status", "health", "state", "ready", "available"]
        status_data = {k: v for k, v in metadata.items() if k in status_fields}
        if status_data:
            console.print("\n[bold yellow]Status Information:[/]")
            for key, value in status_data.items():
                display_name = key.replace("_", " ").title()
                color = "green" if str(value).lower() in ["healthy", "ready", "available", "true", "ok"] else "yellow"
                console.print(f"  • {display_name}: [{color}]{value}[/]")

        # Configuration Information
        config_fields = ["config", "configuration", "settings", "features", "capabilities"]
        config_data = {k: v for k, v in metadata.items() if k in config_fields and isinstance(v, dict | list)}
        if config_data:
            console.print("\n[bold yellow]Configuration:[/]")
            for key, value in config_data.items():
                display_name = key.replace("_", " ").title()
                console.print(f"  • {display_name}:")
                if isinstance(value, dict):
                    for sub_key, sub_value in value.items():
                        console.print(f"    - {sub_key}: {sub_value}")
                elif isinstance(value, list):
                    for item in value:
                        console.print(f"    - {item}")

        # All remaining fields
        displayed_fields = set()
        for field_group in [version_fields, service_fields, env_fields, time_fields, status_fields, config_fields]:
            displayed_fields.update(field_group)
        displayed_fields.add("success")  # Don't show success field in additional

        remaining_fields = {k: v for k, v in metadata.items() if k not in displayed_fields}
        if remaining_fields:
            console.print("\n[bold yellow]Additional Information:[/]")
            for key, value in remaining_fields.items():
                display_name = key.replace("_", " ").title()
                if isinstance(value, dict | list):
                    console.print(f"  • {display_name}:")
                    console.print(JSON(json.dumps(value)))
                else:
                    console.print(f"  • {display_name}: {value}")

    except Exception as e:
        eprint(f"❌ Error fetching system metadata: {str(e)}")
        if debug_mode:
            import traceback

            traceback.print_exc()
        sys.exit(1)


def refresh_cache(arguments: dict):
    """Refresh backend cache and display statistics."""
    debug_mode = arguments.get("--debug", False)

    try:
        print_info("Refreshing backend cache...")
        result = get_system_refresh(debug=debug_mode)

        # Display comprehensive summary
        console.print("\n[bold cyan]═══ Cache Refresh Results ═══[/]\n")
        console.print("\n[cyan]Raw API Response:[/]")
        console.print(JSON(json.dumps(result)))

    except Exception as e:
        eprint(f"❌ Error refreshing cache: {str(e)}")
        sys.exit(1)


def check_health(arguments: dict):
    """Check system health status and display results."""
    debug_mode = arguments.get("--debug", False)
    raw_output = arguments.get("--raw", False)

    try:
        print_info("Checking system health...")
        health_data = get_system_health(debug=debug_mode)

        # Convert HealthStatusResponse object to dict for compatibility
        health_data = health_data.model_dump()

        if debug_mode:
            console.print("\n[cyan]Raw API Response:[/]")
            console.print(JSON(json.dumps(health_data)))

        if raw_output:
            # Just output the raw JSON data
            pprint(health_data)
            return

        # Display health status in a clean grid layout

        # Overall health status
        status = health_data.get("status", "unknown").lower()
        is_healthy = status == "healthy"

        # Create status indicator
        if is_healthy:
            status_icon = "🟢"
            status_text = "HEALTHY"
        else:
            status_icon = "🔴"
            status_text = "UNHEALTHY"

        # Build content for left box (Basic System Info)
        basic_info_lines = []
        basic_info_lines.append(f"{status_icon} System Status: {status_text}")

        if "service" in health_data:
            basic_info_lines.append(f"Service: {health_data['service']}")

        if "version" in health_data:
            basic_info_lines.append(f"Version: {health_data['version']}")

        if "timestamp" in health_data:
            basic_info_lines.append(f"Timestamp: {health_data['timestamp']}")

        basic_info_content = "\n".join(basic_info_lines)

        # Build content for right box (Health Checks as a list)
        checks_lines = []
        if "checks" in health_data:
            checks = health_data["checks"]

            # Handle both list and dict formats for checks
            if isinstance(checks, list):
                # Handle checks as a list of check objects
                for check in checks:
                    if isinstance(check, dict):
                        check_name = check.get("name", "Unknown Check")
                        check_status = check.get("status", "unknown")
                        check_message = check.get("message", "")
                        duration = check.get("duration_ms", 0)

                        # Determine if check is healthy
                        check_healthy = check_status.lower() in ["healthy", "ok", "pass", "true"]

                        # Status icon
                        check_icon = "✅" if check_healthy else "❌"

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

                        # Include timing info if available
                        timing_info = f" ({duration}ms)" if duration > 0 else ""
                        message_info = f": {check_message}" if check_message else ""

                        checks_lines.append(f"{check_icon} {display_name}: {check_status}{timing_info}{message_info}")
                    else:
                        checks_lines.append(f"❓ Unknown check format: {check}")
            elif isinstance(checks, dict):
                # Handle checks as a dictionary (legacy format)
                for check_name, check_status in checks.items():
                    # Handle different check status formats
                    if isinstance(check_status, str):
                        if check_name == "environment":
                            check_healthy = bool(check_status)
                            status_value = check_status
                        else:
                            check_healthy = check_status.lower() in ["healthy", "ok", "pass", "true"]
                            status_value = check_status
                    elif isinstance(check_status, dict):
                        check_healthy = check_status.get("status", "").lower() in ["healthy", "ok", "pass", "true"]
                        status_value = check_status.get("status", "Unknown")
                    else:
                        check_healthy = False
                        status_value = str(check_status)

                    # Status icon
                    check_icon = "✅" if check_healthy else "❌"

                    # Format as a simple list item
                    display_name = check_name.replace("_", " ").title()
                    checks_lines.append(f"{check_icon} {display_name}: {status_value}")
            else:
                checks_lines.append(f"❓ Unsupported checks format: {type(checks)}")

        checks_content = "\n".join(checks_lines) if checks_lines else "No health checks available"

        # Create side-by-side panels using columns
        from rich.columns import Columns
        from rich.panel import Panel

        left_panel = Panel(basic_info_content, title="System Info", border_style="cyan", padding=(1, 2), expand=True)

        right_panel = Panel(checks_content, title="Health Checks", border_style="cyan", padding=(1, 2), expand=True)

        columns = Columns([left_panel, right_panel], equal=True, expand=True)
        console.print(columns)

        # Display all metrics if available
        if "metrics" in health_data:
            metrics = health_data["metrics"]
            console.print("\n[bold yellow]System Metrics:[/]")

            for key, value in metrics.items():
                display_name = key.replace("_", " ").title()
                if isinstance(value, int | float):
                    if "uptime" in key or "seconds" in key:
                        # Already displayed uptime in basic info
                        if key != "uptime_seconds":
                            console.print(f"  • {display_name}: {value}")
                    elif "rate" in key or "percent" in key:
                        console.print(f"  • {display_name}: {value:.2f}%")
                    elif "time" in key and "ms" in key:
                        console.print(f"  • {display_name}: {value:.0f}ms")
                    else:
                        console.print(f"  • {display_name}: {value:,}")
                else:
                    console.print(f"  • {display_name}: {value}")

        # Display performance data if available
        perf_fields = ["performance", "latency", "throughput", "capacity"]
        perf_data = {k: v for k, v in health_data.items() if k in perf_fields}
        if perf_data:
            console.print("\n[bold yellow]Performance Data:[/]")
            for key, value in perf_data.items():
                display_name = key.replace("_", " ").title()
                if isinstance(value, dict):
                    console.print(f"  • {display_name}:")
                    for sub_key, sub_value in value.items():
                        console.print(f"    - {sub_key}: {sub_value}")
                else:
                    console.print(f"  • {display_name}: {value}")

        # Display any issues, warnings, or alerts
        if "issues" in health_data and health_data["issues"]:
            console.print("\n[bold red]Active Issues:[/]")
            issues = health_data["issues"] if isinstance(health_data["issues"], list) else [health_data["issues"]]
            for issue in issues:
                if isinstance(issue, dict):
                    severity = issue.get("severity", "WARNING")
                    message = issue.get("message", "Unknown issue")
                    timestamp = issue.get("timestamp", "")

                    severity_color = "red" if severity == "ERROR" else "yellow"
                    console.print(f"  • [{severity_color}]{severity}[/]: {message}")
                    if timestamp:
                        console.print(f"    [dim]Detected: {timestamp}[/]")
                else:
                    console.print(f"  • {issue}")

        if "warnings" in health_data and health_data["warnings"]:
            console.print("\n[bold yellow]Warnings:[/]")
            warnings = (
                health_data["warnings"] if isinstance(health_data["warnings"], list) else [health_data["warnings"]]
            )
            for warning in warnings:
                console.print(f"  • [yellow]{warning}[/]")

        if "alerts" in health_data and health_data["alerts"]:
            console.print("\n[bold magenta]Alerts:[/]")
            alerts = health_data["alerts"] if isinstance(health_data["alerts"], list) else [health_data["alerts"]]
            for alert in alerts:
                console.print(f"  • [magenta]{alert}[/]")

        # Display dependencies if available
        if "dependencies" in health_data:
            console.print("\n[bold yellow]Dependencies:[/]")
            deps = health_data["dependencies"]
            if isinstance(deps, dict):
                for dep_name, dep_status in deps.items():
                    if isinstance(dep_status, dict):
                        status = dep_status.get("status", "unknown")
                        color = "green" if status.lower() in ["healthy", "ok"] else "red"
                        console.print(f"  • {dep_name}: [{color}]{status}[/]")
                    else:
                        color = "green" if str(dep_status).lower() in ["healthy", "ok", "true"] else "red"
                        console.print(f"  • {dep_name}: [{color}]{dep_status}[/]")
            else:
                console.print(f"  {deps}")

        # Display any remaining fields not yet shown
        displayed_fields = {
            "status",
            "service",
            "version",
            "timestamp",
            "checks",
            "metrics",
            "issues",
            "warnings",
            "alerts",
            "dependencies",
            "success",
            "uptime",
            "environment",
            "region",
            "deployment",
            "stage",
            "performance",
            "latency",
            "throughput",
            "capacity",
        }

        remaining_fields = {k: v for k, v in health_data.items() if k not in displayed_fields}
        if remaining_fields:
            console.print("\n[bold yellow]Additional Health Information:[/]")
            for key, value in remaining_fields.items():
                display_name = key.replace("_", " ").title()
                if isinstance(value, dict | list):
                    console.print(f"  • {display_name}:")
                    console.print(JSON(json.dumps(value)))
                else:
                    console.print(f"  • {display_name}: {value}")

        # Display last check time
        last_check_fields = ["last_check", "last_checked", "checked_at", "last_update"]
        for field in last_check_fields:
            if field in health_data:
                console.print(f"\n[dim]Last health check: {health_data[field]}[/]")
                break

    except Exception as e:
        eprint(f"❌ Error checking system health: {str(e)}")
        if debug_mode:
            import traceback

            traceback.print_exc()
        sys.exit(1)


def reset_database(arguments: dict):
    """⚠️ Reset the backend database cache by dropping all cached data.

    This function clears all cached data from the system database, which acts as a cache
    for CloudZero operations. The data will automatically regenerate within 1 hour or
    can be manually refreshed if needed. This operation affects all users temporarily.

    Use when schema changes require cache clearing or when a complete cache reset is needed.
    """
    debug_mode = arguments.get("--debug", False)
    confirm = arguments.get("--confirm", False)
    force = arguments.get("--force", False)

    try:
        # Show informational warning
        console.print("\n[bold yellow]⚠️  BACKEND CACHE RESET OPERATION ⚠️[/]\n")
        console.print("[cyan]This will clear all cached data from the system database:[/]")
        console.print("[yellow]• Organization cache data[/]")
        console.print("[yellow]• Connection cache information[/]")
        console.print("[yellow]• Historical cache records[/]")
        console.print("[yellow]• Configuration cache settings[/]")
        console.print("[yellow]• All cached database entries[/]")
        console.print("\n[bold cyan]📋 IMPORTANT NOTES:[/]")
        console.print("[green]✓ Data will automatically regenerate within 1 hour[/]")
        console.print("[green]✓ Manual refresh can be triggered if needed[/]")
        console.print("[yellow]⚠ This affects ALL users temporarily[/]")
        console.print("[yellow]⚠ Some czops commands may timeout or run slower until cache rebuilds[/]")
        console.print("[blue]ℹ️  This operation is typically needed for schema changes or complete cache refresh[/]\n")

        # If no confirmation flag, require interactive confirmation
        if not confirm:
            console.print("[yellow]To proceed, you must:[/]")
            console.print("[yellow]1. Add --confirm flag to your command[/]")
            console.print("[yellow]2. Optionally add --force to bypass additional confirmation[/]")
            console.print("\n[dim]Example: czops system reset-database --confirm --force[/]")
            console.print("\n[red]Cache reset cancelled - confirmation required[/]")
            sys.exit(1)

        # Additional interactive confirmation for extra safety
        if not force:
            try:
                user_input = input("\nType 'RESET CACHE' to confirm this operation affects all users: ")
                if user_input != "RESET CACHE":
                    console.print("[red]Cache reset cancelled - confirmation text did not match[/]")
                    sys.exit(1)
            except KeyboardInterrupt:
                console.print("\n[red]Cache reset cancelled by user[/]")
                sys.exit(1)

        console.print("\n[yellow]Initiating cache reset operation...[/]")

        # Call the V4 API to drop the database
        result = drop_system_database(confirm=True, force=force, debug=debug_mode)

        # Convert DropDatabaseResponse object to dict for display
        result_dict = result.model_dump()

        if debug_mode:
            console.print("\n[cyan]Raw API Response:[/]")
            console.print(JSON(json.dumps(result_dict)))

        # Display comprehensive results
        console.print("\n[bold cyan]═══ Cache Reset Results ═══[/]\n")

        # Operation status
        dropped = result_dict.get("dropped", False)
        if dropped:
            console.print("[bold green]Status: SUCCESSFUL[/]")
        else:
            console.print("[bold red]Status: FAILED[/]")

        # Statistics
        items_deleted = result_dict.get("items_deleted", 0)
        items_failed = result_dict.get("items_failed", 0)
        total_items = result_dict.get("total_items", 0)
        success_rate = result_dict.get("success_rate_percent", 0.0)

        console.print("[bold yellow]Items Statistics:[/]")
        console.print(f"  • Total Items: [cyan]{total_items:,}[/]")
        console.print(f"  • Successfully Deleted: [green]{items_deleted:,}[/]")
        console.print(f"  • Failed to Delete: [red]{items_failed:,}[/]")
        if success_rate is not None:
            color = "green" if success_rate >= 99.0 else "yellow" if success_rate >= 90.0 else "red"
            console.print(f"  • Success Rate: [{color}]{success_rate:.2f}%[/]")

        # Performance information
        duration_ms = result_dict.get("duration_ms")
        batches_processed = result_dict.get("batches_processed", 0)
        if duration_ms is not None:
            console.print("\n[bold yellow]Performance:[/]")
            console.print(f"  • Duration: [blue]{duration_ms:.1f}ms ({duration_ms / 1000:.2f}s)[/]")
            console.print(f"  • Batches Processed: [cyan]{batches_processed:,}[/]")
            if items_deleted > 0 and duration_ms > 0:
                rate = items_deleted / (duration_ms / 1000)
                console.print(f"  • Processing Rate: [magenta]{rate:.0f} items/second[/]")

        # Operation details
        operation_id = result_dict.get("operation_id")
        table_name = result_dict.get("table_name")
        namespace = result_dict.get("namespace")

        if operation_id or table_name or namespace:
            console.print("\n[bold yellow]Operation Details:[/]")
            if operation_id:
                console.print(f"  • Operation ID: [cyan]{operation_id}[/]")
            if table_name:
                console.print(f"  • Table Name: [cyan]{table_name}[/]")
            if namespace:
                console.print(f"  • Namespace: [cyan]{namespace}[/]")

        # Messages
        message = result_dict.get("message")
        warning = result_dict.get("warning")

        if message:
            console.print(f"\n[bold cyan]Message:[/] {message}")

        if warning:
            console.print(f"\n[bold yellow]Warning:[/] {warning}")

        # Failed items details (if any)
        failed_items = result_dict.get("failed_items", [])
        if failed_items:
            console.print(f"\n[bold red]Failed Items ({len(failed_items)}):[/]")
            for i, item in enumerate(failed_items[:10]):  # Show only first 10 to avoid overwhelming output
                pk = item.get("PK", "Unknown")
                sk = item.get("SK", "Unknown")
                console.print(f"  • [red]{i + 1}. PK: {pk}, SK: {sk}[/]")

            if len(failed_items) > 10:
                remaining = len(failed_items) - 10
                console.print(f"  • [dim]... and {remaining} more failed items[/]")

        # Final status
        if dropped and items_failed == 0:
            console.print("\n[bold green]✅ Cache reset completed successfully![/]")
            console.print(f"[green]All {items_deleted:,} cache items were cleared from the database.[/]")
            console.print("[cyan]📋 Cache will automatically regenerate within 1 hour or can be manually refreshed.[/]")
        elif dropped and items_failed > 0:
            console.print("\n[bold yellow]⚠️  Cache reset completed with warnings![/]")
            console.print(f"[yellow]{items_deleted:,} items cleared successfully, {items_failed:,} items failed.[/]")
            console.print("[cyan]📋 Cache will automatically regenerate within 1 hour or can be manually refreshed.[/]")
        else:
            console.print("\n[bold red]❌ Cache reset failed![/]")
            console.print("[red]Operation was not completed successfully.[/]")
            sys.exit(1)

    except KeyboardInterrupt:
        console.print("\n[red]Cache reset cancelled by user[/]")
        sys.exit(1)
    except APIError as e:
        # Check for the specific AWS API Gateway signature error that indicates the endpoint isn't implemented
        server_resp_str = str(e.server_response) if e.server_response else ""
        if e.status_code == 403 and (
            "IncompleteSignatureException" in server_resp_str
            or "Invalid key=value pair (missing equal-sign)" in server_resp_str
        ):
            console.print("\n[bold red]❌ Backend endpoint not available[/]")
            console.print("[yellow]The /system/data DELETE endpoint appears to be unimplemented or misconfigured.[/]")
            if debug_mode:
                console.print(
                    "\n[dim]DEBUG: Server returned IncompleteSignatureException, suggesting the endpoint doesn't exist or isn't configured for JWT authentication.[/]"
                )
                console.print(f"[dim]DEBUG: Status: {e.status_code}[/]")
                console.print(f"[dim]DEBUG: Server response: {e.server_response}[/]")
            console.print("\n[blue]💡 This command requires backend infrastructure changes to be fully functional.[/]")
            console.print("[blue]💡 Please contact the platform team to implement the /system/data DELETE endpoint.[/]")
        else:
            console.print(f"\n[red]❌ Error during cache reset: {str(e)}[/]")
            if debug_mode:
                console.print(f"[dim]Status: {e.status_code}[/]")
                console.print(f"[dim]Server response: {e.server_response}[/]")
        sys.exit(1)
    except Exception as e:
        console.print(f"\n[red]❌ Unexpected error during cache reset: {str(e)}[/]")
        if debug_mode:
            import traceback

            traceback.print_exc()
        sys.exit(1)


def handle_command(arguments: dict):
    """Main entry point for system commands."""
    if arguments.get("metadata"):
        display_metadata(arguments)
    elif arguments.get("refresh-cache"):
        refresh_cache(arguments)
    elif arguments.get("health"):
        check_health(arguments)
    elif arguments.get("reset-database"):
        reset_database(arguments)
    else:
        eprint("Unknown system command. Available commands: metadata, refresh-cache, health, reset-database")
        sys.exit(1)
