#!/usr/bin/env python3
# SPDX-FileCopyrightText: 2025 OmniNode.ai Inc.
# SPDX-License-Identifier: MIT

"""
Check System Health - Fast overall system health snapshot

Checks Docker services, infrastructure connectivity, and recent activity
in under 5 seconds.

Usage:
    python3 execute.py [--format json|text|summary] [--verbose]

Exit Codes:
    0 - All systems healthy
    1 - Degraded (warnings found)
    2 - Critical (errors found)
    3 - Execution error

Created: 2025-11-12
"""

import argparse
import json
import sys
import time
from pathlib import Path

# Add _shared to path
sys.path.insert(0, str(Path(__file__).parent.parent.parent / "_shared"))

try:
    from db_helper import execute_query
    from docker_helper import get_service_summary
    from kafka_helper import check_kafka_connection, list_topics
    from qdrant_helper import check_qdrant_connection, get_all_collections_stats
    from status_formatter import format_json, format_status_indicator, format_timestamp
except ImportError as e:
    print(
        json.dumps(
            {
                "success": False,
                "error": f"Failed to import helpers: {e}",
                "hint": "Ensure _shared helpers are installed",
            }
        )
    )
    sys.exit(3)


def check_docker_services(verbose: bool = False) -> dict:
    """Check Docker services status."""
    try:
        # Check all services
        all_services = get_service_summary()

        # Check if Docker is unavailable (CLI not installed, daemon not running, permission denied)
        if not all_services.get("success", False):
            return {
                "success": False,
                "error": all_services.get("error", "Failed to check Docker services"),
                "total": 0,
                "running": 0,
                "stopped": 0,
                "unhealthy": 0,
                "healthy": 0,
                "details": {},
            }

        # Check archon services specifically
        archon_services = get_service_summary("archon-")

        # Check omninode services
        omninode_services = get_service_summary("omninode-")

        # Check app services
        app_services = get_service_summary("app")

        # Extract counts
        total = all_services.get("total", 0)
        running = all_services.get("running", 0)
        stopped = all_services.get("stopped", 0)
        unhealthy = all_services.get("unhealthy", 0)
        healthy = all_services.get("healthy", 0)

        return {
            "success": True,
            "total": total,
            "running": running,
            "stopped": stopped,
            "unhealthy": unhealthy,
            "healthy": healthy,
            "details": {
                "archon": archon_services if verbose else None,
                "omninode": omninode_services if verbose else None,
                "app": app_services if verbose else None,
            },
        }
    except Exception as e:
        return {"success": False, "error": str(e)}


def check_infrastructure(verbose: bool = False) -> dict:
    """Check infrastructure components."""
    infrastructure = {}

    # Check Kafka
    try:
        kafka_conn = check_kafka_connection()
        kafka_topics = list_topics() if verbose else {"count": 0}

        infrastructure["kafka"] = {
            "status": kafka_conn.get("status", "unknown"),
            "broker": kafka_conn.get("broker", "unknown"),
            "reachable": kafka_conn.get("reachable", False),
            "topics": kafka_topics.get("count", 0) if verbose else None,
            "error": kafka_conn.get("error"),
        }
    except Exception as e:
        infrastructure["kafka"] = {"status": "error", "error": str(e)}

    # Check PostgreSQL
    try:
        postgres_result = execute_query(
            "SELECT COUNT(*) as count FROM information_schema.tables WHERE table_schema = %s",
            ("public",),
        )
        if postgres_result["success"] and postgres_result["rows"]:
            table_count = postgres_result["rows"][0]["count"]
            infrastructure["postgres"] = {
                "status": "connected",
                "host": f"{postgres_result.get('host', 'unknown')}:{postgres_result.get('port', 'unknown')}",
                "database": postgres_result.get("database", "unknown"),
                "tables": table_count,
                "error": None,
            }
        else:
            infrastructure["postgres"] = {
                "status": "error",
                "error": postgres_result.get("error", "Unknown error"),
            }
    except Exception as e:
        infrastructure["postgres"] = {"status": "error", "error": str(e)}

    # Check Qdrant
    try:
        qdrant_conn = check_qdrant_connection()
        qdrant_stats = (
            get_all_collections_stats()
            if verbose
            else {"collection_count": 0, "total_vectors": 0}
        )

        infrastructure["qdrant"] = {
            "status": qdrant_conn.get("status", "unknown"),
            "url": qdrant_conn.get("url", "unknown"),
            "reachable": qdrant_conn.get("reachable", False),
            "collections": qdrant_stats.get("collection_count", 0) if verbose else None,
            "total_vectors": qdrant_stats.get("total_vectors", 0) if verbose else None,
            "error": qdrant_conn.get("error"),
        }
    except Exception as e:
        infrastructure["qdrant"] = {"status": "error", "error": str(e)}

    return infrastructure


def check_recent_activity() -> dict:
    """Check recent activity (last 5 minutes)."""
    activity = {
        "timeframe": "5m",
        "agent_executions": 0,
        "routing_decisions": 0,
        "agent_actions": 0,
    }

    try:
        # Check manifest injections
        manifest_result = execute_query(
            "SELECT COUNT(*) as count FROM agent_manifest_injections WHERE created_at > NOW() - INTERVAL '5 minutes'"
        )
        if manifest_result["success"] and manifest_result["rows"]:
            activity["agent_executions"] = manifest_result["rows"][0]["count"]

        # Check routing decisions
        routing_result = execute_query(
            "SELECT COUNT(*) as count FROM agent_routing_decisions WHERE created_at > NOW() - INTERVAL '5 minutes'"
        )
        if routing_result["success"] and routing_result["rows"]:
            activity["routing_decisions"] = routing_result["rows"][0]["count"]

        # Check agent actions
        actions_result = execute_query(
            "SELECT COUNT(*) as count FROM agent_actions WHERE created_at > NOW() - INTERVAL '5 minutes'"
        )
        if actions_result["success"] and actions_result["rows"]:
            activity["agent_actions"] = actions_result["rows"][0]["count"]
    except Exception:
        # Silently fail - activity is optional
        pass

    return activity


def determine_overall_status(services: dict, infrastructure: dict) -> tuple:
    """
    Determine overall system status.

    Returns:
        Tuple of (status_string, issues_list, recommendations_list)
    """
    issues = []
    recommendations = []

    # Check services
    if not services.get("success"):
        issues.append(
            {
                "severity": "critical",
                "component": "docker",
                "issue": "Failed to check Docker services",
                "details": services.get("error", "Unknown error"),
            }
        )
    elif services.get("stopped", 0) > 0:
        issues.append(
            {
                "severity": "critical",
                "component": "docker",
                "issue": f"{services['stopped']} service(s) stopped",
                "details": f"{services['stopped']} containers are not running",
            }
        )
        recommendations.append(
            "Start stopped services with: docker start <container-name>"
        )
    elif services.get("unhealthy", 0) > 0:
        issues.append(
            {
                "severity": "warning",
                "component": "docker",
                "issue": f"{services['unhealthy']} service(s) unhealthy",
                "details": f"{services['unhealthy']} containers are running but unhealthy",
            }
        )
        recommendations.append("Check service logs with: docker logs <container-name>")

    # Check infrastructure
    for component, status in infrastructure.items():
        if status.get("status") in ["error", "unreachable", "timeout"]:
            issues.append(
                {
                    "severity": "critical",
                    "component": component,
                    "issue": f"{component.capitalize()} unreachable",
                    "details": status.get("error", "Connection failed"),
                }
            )
            if component == "kafka":
                recommendations.append(
                    "Check Kafka broker: docker logs omnibase-infra-redpanda"
                )
            elif component == "postgres":
                recommendations.append("Verify PostgreSQL credentials in .env file")
            elif component == "qdrant":
                recommendations.append(
                    "Check Qdrant service: docker logs archon-qdrant"
                )

    # Determine status
    critical_count = sum(1 for issue in issues if issue["severity"] == "critical")
    warning_count = sum(1 for issue in issues if issue["severity"] == "warning")

    if critical_count > 0:
        return ("critical", issues, recommendations)
    elif warning_count > 0:
        return ("degraded", issues, recommendations)
    else:
        return ("healthy", issues, recommendations)


def format_output(data: dict, format_type: str) -> str:
    """Format output based on requested format."""
    if format_type == "json":
        return format_json(data, pretty=True)
    elif format_type == "summary":
        # Brief summary format
        status = data.get("status", "unknown")
        indicator = format_status_indicator(status)
        services = data.get("services", {})
        issues = data.get("issues", [])

        lines = [
            f"{indicator} System Status: {status.upper()}",
            f"  Services: {services.get('running', 0)}/{services.get('total', 0)} running",
            f"  Issues: {len(issues)}",
            f"  Duration: {data.get('check_duration_ms', 0)}ms",
        ]
        return "\n".join(lines)
    else:  # text format
        lines = [
            "=" * 60,
            "SYSTEM HEALTH CHECK",
            "=" * 60,
            f"Status: {data.get('status', 'unknown').upper()}",
            f"Timestamp: {data.get('timestamp', 'unknown')}",
            f"Duration: {data.get('check_duration_ms', 0)}ms",
            "",
            "Services:",
            f"  Running: {data.get('services', {}).get('running', 0)}/{data.get('services', {}).get('total', 0)}",
            f"  Unhealthy: {data.get('services', {}).get('unhealthy', 0)}",
            "",
            "Infrastructure:",
        ]

        for component, status in data.get("infrastructure", {}).items():
            indicator = format_status_indicator(status.get("status", "unknown"))
            lines.append(
                f"  {indicator} {component.capitalize()}: {status.get('status', 'unknown')}"
            )

        if data.get("issues"):
            lines.append("")
            lines.append("Issues:")
            for issue in data["issues"]:
                severity_indicator = "✗" if issue["severity"] == "critical" else "⚠"
                lines.append(
                    f"  {severity_indicator} {issue['component']}: {issue['issue']}"
                )

        return "\n".join(lines)


def main() -> int:
    """Check overall system health.

    Returns:
        Exit code (0=healthy, 1=degraded, 2=critical, 3=error)
    """
    parser = argparse.ArgumentParser(description="Check system health")
    parser.add_argument(
        "--format",
        choices=["json", "text", "summary"],
        default="json",
        help="Output format",
    )
    parser.add_argument(
        "--verbose", action="store_true", help="Include detailed information"
    )
    args = parser.parse_args()

    start_time = time.time()

    try:
        # Perform checks
        services = check_docker_services(verbose=args.verbose)
        infrastructure = check_infrastructure(verbose=args.verbose)
        activity = check_recent_activity()

        # Determine overall status
        status, issues, recommendations = determine_overall_status(
            services, infrastructure
        )

        # Calculate duration
        duration_ms = int((time.time() - start_time) * 1000)

        # Build result
        result = {
            "status": status,
            "timestamp": format_timestamp(),
            "check_duration_ms": duration_ms,
            "services": services,
            "infrastructure": infrastructure,
            "recent_activity": activity,
            "issues": issues,
            "recommendations": recommendations,
        }

        # Output result
        print(format_output(result, args.format))

        # Exit with appropriate code
        if status == "critical":
            return 2
        elif status == "degraded":
            return 1
        else:
            return 0

    except Exception as e:
        error_result = {
            "success": False,
            "error": str(e),
            "timestamp": format_timestamp(),
        }
        print(format_json(error_result))
        return 3


if __name__ == "__main__":
    sys.exit(main())
