"""
Module: sandbox.lifecycle
Description: Shared sandbox setup logic extracted from the dev command.

Implements:
    - docs/cli/reference.md#huitzo-sandbox
    - docs/cli/agent-integration.md#sandbox-lifecycle

See Also:
    - docs/guides/developer-environment.md#development-session-flow
"""

from __future__ import annotations

import logging
import site
import subprocess
import sys
from typing import TYPE_CHECKING, Any

import typer

from huitzo_cli.validator import PackValidator

if TYPE_CHECKING:
    from huitzo_cli.output import OutputContext
    from huitzo_cli.sandbox.proxy import LocalSandbox

logger = logging.getLogger(__name__)


def validate_pack(output: OutputContext, *, strict: bool = False) -> None:
    """Validate the pack structure. Raises typer.Exit(1) on failure."""
    output.print("[bold]Validating pack...[/bold]")
    validator = PackValidator()
    result = validator.validate(strict=strict)

    if not result.valid:
        output.print("[red]Pack validation failed[/red]")
        for error in result.errors:
            output.print(f"  {error}")
        raise typer.Exit(1)

    output.print("[green]Pack validation passed[/green]")


def install_editable(output: OutputContext) -> None:
    """Install the current pack in editable mode. Raises typer.Exit(1) on failure."""
    output.print("[bold]Installing pack in editable mode...[/bold]")
    install_result = subprocess.run(
        [sys.executable, "-m", "pip", "install", "-e", "."],
        capture_output=True,
        text=True,
        check=False,
    )
    if install_result.returncode != 0:
        stderr_text = install_result.stderr or ""
        logger.debug("Full pip stderr:\n%s", stderr_text)
        truncated = "\n".join(stderr_text.splitlines()[-10:])
        output.print(f"[red]Editable install failed:[/red]\n{truncated}")
        raise typer.Exit(1)

    output.print("[green]Pack installed[/green]")

    # Re-process .pth files so the parent process sees paths added by
    # `pip install -e .` (which wrote .pth files that only take effect at
    # interpreter startup).
    for sp in site.getsitepackages():
        site.addsitedir(sp)
    user_sp = site.getusersitepackages()
    if user_sp:
        site.addsitedir(user_sp)


def create_and_start_sandbox(
    output: OutputContext,
    token: str,
    port: int = 8080,
    use_tls: bool = True,
    use_platform: bool = False,
) -> tuple[LocalSandbox, str, dict[str, dict[str, Any]]]:
    """Create a LocalSandbox, discover commands, and start it.

    Returns:
        (sandbox, base_url, commands_metadata)

    Raises:
        typer.Exit(1) on startup failure.
    """
    from huitzo_cli.sandbox.proxy import LocalSandbox

    sandbox = LocalSandbox(auth_token=token, use_platform=use_platform)
    commands = sandbox.discover_commands()

    # Surface discovery failures
    failures = sandbox.get_discovery_failures()
    if failures:
        output.print(f"[yellow]Warning: {len(failures)} command(s) failed to load:[/yellow]")
        for failure in failures:
            output.print(f"  [yellow]{failure}[/yellow]")

    if not commands:
        output.print(
            "[yellow]No commands found. Check your entry_points in pyproject.toml.[/yellow]"
        )
    else:
        output.print(f"[bold]Discovered {len(commands)} command(s):[/bold]")
        for name, meta in commands.items():
            output.print(f"  {meta.get('namespace', name)} - {meta.get('description', '')[:60]}")

    try:
        base_url = sandbox.start(port=port, use_tls=use_tls)
    except RuntimeError as exc:
        msg = str(exc)
        if "crashed during startup" in msg or "did not start" in msg:
            output.print(
                f"\n[red]Could not start sandbox on port {port}.[/red]\n"
                f"The port may already be in use. Try a different port."
            )
        else:
            output.print(f"\n[red]Sandbox failed to start: {msg}[/red]")
        raise typer.Exit(1)

    return sandbox, base_url, commands
