"""Check command - Installation verification."""

from __future__ import annotations

import logging
import sys

import click

from ..utils.console import get_console

logger = logging.getLogger(__name__)


@click.command(hidden=True)
@click.option(
    "--backend",
    type=click.Choice(["cuda", "ascend", "all"]),
    default="all",
    help="Backend to check",
)
@click.option("--model", type=str, default=None, help="Model to use for inference test")
@click.option("--quick", is_flag=True, help="Skip inference test, only check dependencies")
@click.option("--verbose", "-v", is_flag=True, help="Verbose output")
@click.option("--full-chain", is_flag=True, help="Test full call chain via sagellm-core")
@click.option("--refresh", is_flag=True, help="Force refresh hardware profile cache")
def check(
    backend: str, model: str | None, quick: bool, verbose: bool, full_chain: bool, refresh: bool
) -> None:
    """Verify installation and run backend tests (cache-aware).

    This command uses cached hardware profiles for fast verification when available.
    Use --refresh to force a new hardware detection and update the cache.

    \b
    Examples:
    sagellm check                     # Check all backends (use cache)
    sagellm check --backend cuda      # Check CUDA only
    sagellm check --refresh           # Force refresh hardware profiles
    sagellm check --quick             # Skip inference test
    sagellm check --full-chain        # Test via sagellm-core
    sagellm check --model Qwen/Qwen2.5-0.5B-Instruct

    \b
    This command verifies:
      1. Required packages are installed
      2. Backend hardware is available
      3. Model can be loaded (unless --quick)
      4. Inference works correctly (unless --quick)
    """
    console = get_console()
    from rich.panel import Panel

    console.print()
    console.print(
        Panel.fit("[bold blue]sageLLM Installation Check[/bold blue]", border_style="blue")
    )
    console.print()

    # Handle cache-based detection
    backends_to_check = []
    if backend == "all":
        backends_to_check = ["cuda", "ascend"]
    else:
        backends_to_check = [backend]

    # If refresh requested, run detection and update cache
    if refresh:
        try:
            from sagellm_backend.hardware import ProfileCache
            from sagellm_backend.hardware.inspectors import get_inspector

            console.print("[cyan]🔄 Refreshing hardware profiles...[/cyan]\n")
            cache = ProfileCache()

            for backend_name in backends_to_check:
                hw_type = backend_name  # cuda/ascend
                try:
                    inspector = get_inspector(hw_type)
                    console.print(f"  Detecting {hw_type}...", end=" ")
                    # Include functional tests if not quick
                    profile = inspector.get_profile(include_functional=not quick)
                    cache.update(hw_type, profile)

                    if profile.is_usable():
                        console.print(f"[green]✅ {profile.max_level.value}[/green]")
                    else:
                        console.print(f"[yellow]⚠️  {profile.max_level.value}[/yellow]")
                except Exception as e:
                    console.print(f"[red]❌ {e}[/red]")
                    if verbose:
                        import traceback

                        console.print(f"[dim]{traceback.format_exc()}[/dim]")

            console.print(f"\n[green]Profile saved to {cache.cache_path}[/green]\n")
        except Exception as e:
            console.print(f"[yellow]⚠️  Cache refresh failed: {e}[/yellow]")
            if verbose:
                import traceback

                console.print(f"[dim]{traceback.format_exc()}[/dim]")

    all_passed = True

    # Check CUDA
    if backend in ("cuda", "all"):
        cuda_ok = _check_cuda_backend(console, model, quick, verbose, full_chain)
        all_passed = all_passed and cuda_ok

    # Check Ascend
    if backend in ("ascend", "all"):
        ascend_ok = _check_ascend_backend(console, quick, verbose)
        all_passed = all_passed and ascend_ok

    # Summary
    console.print()
    if all_passed:
        console.print("[bold green]✅ All checks passed![/bold green]")
        console.print()
        console.print("[dim]You can now run:[/dim]")
        console.print("  [cyan]sagellm serve[/cyan]      Start inference server")
        console.print("  [cyan]sagellm run -p 'Hi'[/cyan]   Run inference")
        console.print()
    else:
        console.print("[bold yellow]⚠️  Some checks failed.[/bold yellow]")
        console.print("[dim]Use --verbose for more details.[/dim]")
        console.print()
        sys.exit(1)


def _check_cuda_backend(
    console, model: str | None, quick: bool, verbose: bool, full_chain: bool = False
) -> bool:
    """Check CUDA backend installation and functionality."""
    console.print("[bold cyan]🔍 Checking CUDA Backend...[/bold cyan]")

    # Step 1: Check torch installation
    console.print("  [1/4] Checking PyTorch...", end=" ")
    try:
        import torch

        console.print(f"[green]✅ torch {torch.__version__}[/green]")
    except ImportError:
        console.print("[red]❌ torch not installed[/red]")
        console.print("       [dim]Fix: pip install torch[/dim]")
        return False

    # Step 2: Check CUDA availability
    console.print("  [2/4] Checking CUDA...", end=" ")
    if not torch.cuda.is_available():
        console.print("[yellow]⚠️  No CUDA GPU detected[/yellow]")
        console.print("       [dim]This is OK if you're using CPU or Ascend[/dim]")
        return True  # Not a failure, just no CUDA

    device_name = torch.cuda.get_device_name(0)
    cuda_version = torch.version.cuda
    console.print(f"[green]✅ {device_name} (CUDA {cuda_version})[/green]")

    # Step 3: Check sagellm-backend
    console.print("  [3/4] Checking sagellm-backend...", end=" ")
    try:
        from sagellm_backend import get_provider

        provider = get_provider("cuda")
        cap = provider.capability()
        console.print(f"[green]✅ backend: {cap.device_type}[/green]")
    except ImportError as e:
        console.print(f"[red]❌ Import error: {e}[/red]")
        console.print("       [dim]Fix: pip install isagellm-backend[/dim]")
        return False
    except Exception as e:
        console.print(f"[yellow]⚠️  {e}[/yellow]")
        # Not a failure - CUDA backend might not be available

    # Step 4: Inference test (optional)
    if quick:
        console.print("  [4/4] Inference test...", end=" ")
        console.print("[dim]skipped (--quick)[/dim]")
        return True

    console.print("  [4/4] Running inference test...")
    return _run_cuda_inference_test(console, model, verbose, full_chain)


def _run_cuda_inference_test(
    console, model: str | None, verbose: bool, full_chain: bool = False
) -> bool:
    """Run a quick CUDA inference test."""
    import asyncio

    test_model = model or "Qwen/Qwen2.5-0.5B-Instruct"

    async def _test():
        from sagellm_protocol import Request

        console.print(f"       Model: [cyan]{test_model}[/cyan]")

        if full_chain:
            console.print("       [dim]Mode: full-chain (via sagellm-core)[/dim]")
        else:
            console.print("       [dim]Mode: direct (sagellm-backend only)[/dim]")

        try:
            if full_chain:
                # Full chain: sagellm-core -> sagellm-backend
                from sagellm_core import EngineConfig, create_engine

                cfg = EngineConfig(
                    kind="cuda",
                    model=test_model,
                    model_path=test_model,
                    max_batch_size=1,
                    max_output_tokens=32,
                    device="cuda:0",
                )

                console.print("       Creating via sagellm-core...", end=" ")
                engine = create_engine(cfg, backend=None)
                console.print("[green]✅[/green]")

                console.print("       Loading model...", end=" ")
                await engine.start()
                console.print("[green]✅[/green]")
            else:
                # Direct: use LLMEngine
                from sagellm_core import LLMEngine, LLMEngineConfig

                llm_config = LLMEngineConfig(
                    model_path=test_model,
                    backend_type="cuda",
                    max_new_tokens=32,
                    trust_remote_code=True,
                )
                engine = LLMEngine(llm_config)

                console.print("       Loading model...", end=" ")
                await engine.start()
                console.print("[green]✅[/green]")

            # Run inference
            request = Request(
                request_id="check-001",
                trace_id="trace-check",
                model=test_model,
                prompt="Hello, sageLLM!",
                max_tokens=16,
                stream=False,
            )

            console.print("       Running inference...", end=" ")
            response = await engine.execute(request)
            console.print("[green]✅[/green]")

            # Show results
            console.print(f"       Output: [green]{response.output_text[:50]}...[/green]")
            console.print(f"       TTFT: [cyan]{response.metrics.ttft_ms:.1f}ms[/cyan]")

            # Show component trace (验证调用链)
            if response.metrics.component_trace:
                trace = " → ".join(response.metrics.component_trace)
                console.print(f"       Call chain: [magenta]{trace}[/magenta]")
            else:
                console.print("       Call chain: [yellow]not available[/yellow]")

            await engine.stop()
            return True

        except Exception as e:
            console.print(f"[red]❌ {e}[/red]")
            if verbose:
                import traceback

                console.print(f"[dim]{traceback.format_exc()}[/dim]")
            return False

    return asyncio.run(_test())


def _check_ascend_backend(console, quick: bool, verbose: bool) -> bool:
    """Check Ascend backend installation."""
    console.print("[bold cyan]🔍 Checking Ascend Backend...[/bold cyan]")

    # Check torch_npu
    console.print("  [1/2] Checking torch_npu...", end=" ")
    try:
        import torch_npu

        if torch_npu.npu.is_available():
            device_count = torch_npu.npu.device_count()
            console.print(f"[green]✅ {device_count} NPU(s) available[/green]")
        else:
            console.print("[yellow]⚠️  torch_npu installed, no NPU detected[/yellow]")
            return True  # Not a failure
    except ImportError:
        console.print("[dim]○ torch_npu not installed (optional)[/dim]")
        return True  # Ascend is optional

    # Check Ascend engine registration
    console.print("  [2/2] Checking Ascend engine...", end=" ")
    try:
        from sagellm_backend import get_provider

        provider = get_provider("ascend")
        cap = provider.capability()
        console.print(f"[green]✅ {cap.device_type}[/green]")
    except Exception as e:
        console.print(f"[yellow]⚠️  {e}[/yellow]")

    return True


# ============================================================================
# Architecture Command - Architecture Conformance Check
# ============================================================================
