"""CLI commands for health checks."""

from __future__ import annotations

import json
import sys
from pathlib import Path

import click

from oclawma.cli_ui import (
    accent,
    header,
    highlight,
    key_value,
    print_error,
    print_info,
    print_success,
    print_warning,
    progress_spinner,
    subheader,
)
from oclawma.config import DEFAULT_CONFIG_PATH
from oclawma.health import HealthCheckConfig, HealthReporter, HealthStatus


def get_db_path(config_path: Path | None = None) -> str:
    """Get the database path from config or use default."""
    cfg_path = config_path or DEFAULT_CONFIG_PATH

    # Default to ~/.oclawma/data/queue.db
    data_dir = cfg_path.parent / "data"
    data_dir.mkdir(parents=True, exist_ok=True)
    return str(data_dir / "queue.db")


@click.group(name="health")
def health_cli() -> None:
    """Health check commands for OCLAWMA.

    Monitor the health of your OCLAWMA instance including:
    - Database connectivity
    - Queue operations
    - Disk space
    - Memory usage
    """
    pass


@health_cli.command(name="check")
@click.option(
    "--db-path",
    type=click.Path(),
    help="Path to the queue database (default: ~/.oclawma/data/queue.db)",
)
@click.option(
    "--format",
    "output_format",
    type=click.Choice(["text", "json"], case_sensitive=False),
    default="text",
    help="Output format",
    show_default=True,
)
@click.option(
    "--webhook",
    help="Webhook URL for notifications",
)
@click.pass_context
def health_check_cmd(
    ctx: click.Context,
    db_path: str | None,
    output_format: str,
    webhook: str | None,
) -> None:
    """Run a health check and display results.

    Performs health checks on all subsystems and reports the status.

    Examples:
        oclawma health check              # Run health check
        oclawma health check --format json # Output as JSON
    """
    db = db_path or get_db_path()

    config = HealthCheckConfig(
        webhook_url=webhook,
    )

    with progress_spinner("Running health checks..."):
        reporter = HealthReporter(db_path=db, config=config)
        result = reporter.check_now()

    if output_format == "json":
        click.echo(json.dumps(result.to_dict(), indent=2))
    else:
        # Text output
        click.echo()
        click.echo(header("HEALTH CHECK RESULTS", width=58))
        click.echo()

        # Overall status
        status_color = {
            HealthStatus.HEALTHY: "green",
            HealthStatus.DEGRADED: "yellow",
            HealthStatus.UNHEALTHY: "red",
        }.get(result.status, "white")

        click.echo(
            key_value(
                "Overall Status",
                click.style(result.status.value.upper(), fg=status_color, bold=True),
            )
        )
        click.echo(key_value("Timestamp", result.timestamp.isoformat()))
        click.echo()

        # Subsystem details
        click.echo(subheader("SUBSYSTEMS"))

        for subsystem in result.subsystems:
            sub_status_color = {
                HealthStatus.HEALTHY: "green",
                HealthStatus.DEGRADED: "yellow",
                HealthStatus.UNHEALTHY: "red",
            }.get(subsystem.status, "white")

            click.echo()
            click.echo(f"  {accent(subsystem.name.upper(), bold=True)}")
            click.echo(f"    Status: {click.style(subsystem.status.value, fg=sub_status_color)}")
            click.echo(f"    Message: {subsystem.message}")
            click.echo(f"    Response: {subsystem.response_time_ms:.2f}ms")

            if subsystem.details:
                click.echo("    Details:")
                for key, value in subsystem.details.items():
                    if "bytes" in key.lower():
                        # Format bytes nicely
                        value_str = _format_bytes(value)
                    elif isinstance(value, float):
                        value_str = f"{value:.2f}"
                    else:
                        value_str = str(value)
                    click.echo(f"      {key}: {value_str}")

        click.echo()

        # Summary
        if result.status == HealthStatus.HEALTHY:
            print_success("All systems operational!")
        elif result.status == HealthStatus.DEGRADED:
            print_warning("Some systems are degraded. Review details above.")
        else:
            print_error("System unhealthy! Immediate attention required.")
            sys.exit(1)


@health_cli.command(name="watch")
@click.option(
    "--db-path",
    type=click.Path(),
    help="Path to the queue database",
)
@click.option(
    "--interval",
    default=60,
    help="Seconds between checks",
    show_default=True,
)
@click.option(
    "--webhook",
    help="Webhook URL for notifications",
)
@click.option(
    "--once",
    is_flag=True,
    help="Run once and exit (don't loop)",
)
def health_watch_cmd(
    db_path: str | None,
    interval: int,
    webhook: str | None,
    once: bool,
) -> None:
    """Continuously monitor health status.

    Runs health checks at regular intervals and reports changes.

    Examples:
        oclawma health watch              # Watch with default interval (60s)
        oclawma health watch --interval 30 # Check every 30 seconds
    """
    db = db_path or get_db_path()

    config = HealthCheckConfig(
        check_interval_seconds=interval,
        webhook_url=webhook,
    )

    reporter = HealthReporter(db_path=db, config=config)

    click.echo(header("HEALTH WATCH", width=58))
    click.echo()
    click.echo(f"Checking every {highlight(f'{interval}s')}...")
    click.echo(f"Database: {db}")
    if webhook:
        click.echo(f"Webhook: {webhook}")
    click.echo()
    click.echo("Press Ctrl+C to stop")
    click.echo()

    last_status: HealthStatus | None = None

    try:
        while True:
            result = reporter.check_now()

            timestamp = result.timestamp.strftime("%H:%M:%S")
            status_symbol = {
                HealthStatus.HEALTHY: "✓",
                HealthStatus.DEGRADED: "⚠",
                HealthStatus.UNHEALTHY: "✗",
            }.get(result.status, "?")

            # Only show details on status change or first run
            if result.status != last_status:
                status_color = {
                    HealthStatus.HEALTHY: "green",
                    HealthStatus.DEGRADED: "yellow",
                    HealthStatus.UNHEALTHY: "red",
                }.get(result.status, "white")

                click.echo(
                    f"[{timestamp}] {click.style(status_symbol, fg=status_color, bold=True)} "
                    f"{click.style(result.status.value.upper(), fg=status_color)} - "
                    f"{len(result.subsystems)} subsystems checked"
                )

                # Show failing subsystems
                for subsystem in result.subsystems:
                    if subsystem.status != HealthStatus.HEALTHY:
                        click.echo(
                            f"         {click.style('•', fg='yellow')} {subsystem.name}: "
                            f"{subsystem.message}"
                        )

                last_status = result.status
            else:
                click.echo(f"[{timestamp}] {status_symbol} {result.status.value}", nl=False)
                click.echo("\r", nl=False)

            if once:
                break

            import time

            time.sleep(interval)

    except KeyboardInterrupt:
        click.echo()
        print_info("Health watch stopped.")


@health_cli.command(name="status")
@click.option(
    "--db-path",
    type=click.Path(),
    help="Path to the queue database",
)
@click.option(
    "--format",
    "output_format",
    type=click.Choice(["text", "json"], case_sensitive=False),
    default="text",
    help="Output format",
    show_default=True,
)
def health_status_cmd(
    db_path: str | None,
    output_format: str,
) -> None:
    """Show current health status from last check.

    Displays the most recent health check results.

    Examples:
        oclawma health status              # Show status
        oclawma health status --format json # JSON output
    """
    db = db_path or get_db_path()

    reporter = HealthReporter(db_path=db)

    # Run a check to get current status
    result = reporter.get_endpoint_response()

    if output_format == "json":
        click.echo(json.dumps(result, indent=2))
    else:
        click.echo()
        click.echo(header("HEALTH STATUS", width=58))
        click.echo()

        status_value = result.get("status", "unknown")
        status_color = {
            "healthy": "green",
            "degraded": "yellow",
            "unhealthy": "red",
        }.get(status_value, "white")

        click.echo(
            key_value("Status", click.style(status_value.upper(), fg=status_color, bold=True))
        )
        click.echo(key_value("Timestamp", result.get("timestamp", "N/A")))
        click.echo()

        click.echo(subheader("SUBSYSTEMS"))

        for subsystem in result.get("subsystems", []):
            sub_status = subsystem.get("status", "unknown")
            sub_status_color = {
                "healthy": "green",
                "degraded": "yellow",
                "unhealthy": "red",
            }.get(sub_status, "white")

            click.echo()
            click.echo(f"  {accent(subsystem.get('name', 'unknown').upper(), bold=True)}")
            click.echo(f"    Status: {click.style(sub_status, fg=sub_status_color)}")
            click.echo(f"    Message: {subsystem.get('message', 'N/A')}")
            click.echo(f"    Response: {subsystem.get('response_time_ms', 0):.2f}ms")

        click.echo()


def _format_bytes(size_bytes: int) -> str:
    """Format bytes to human-readable string."""
    for unit in ["B", "KB", "MB", "GB", "TB"]:
        if size_bytes < 1024.0:
            return f"{size_bytes:.2f} {unit}"
        size_bytes /= 1024.0
    return f"{size_bytes:.2f} PB"
