"""``ilum exec`` command — shell into a module pod."""

from __future__ import annotations

import os
import sys

import typer

from ilum.cli.defaults import resolve_profile_defaults
from ilum.core.kubernetes import KubeClient, PodStatus
from ilum.core.modules import ModuleResolver
from ilum.errors import IlumError
from ilum.wizard.deps import ensure_tools


def _build_exec_command(
    pod_name: str,
    namespace: str,
    context: str,
    shell: str,
    container: str | None,
    command: str | None,
) -> list[str]:
    """Build the ``kubectl exec`` command list. Pure function for testability."""
    cmd = ["kubectl", "exec", "-it", pod_name, "-n", namespace]
    if context:
        cmd += ["--context", context]
    if container:
        cmd += ["-c", container]
    cmd += ["--"]
    if command:
        cmd += ["sh", "-c", command]
    else:
        cmd.append(shell)
    return cmd


def exec_cmd(
    module: str = typer.Argument(help="Module name to exec into (e.g. core, jupyter, sql)."),
    release: str | None = typer.Option(
        None, "--release", "-r", show_default="from profile", help="Helm release name."
    ),
    namespace: str | None = typer.Option(
        None, "--namespace", "-n", show_default="from profile", help="Kubernetes namespace."
    ),
    context: str | None = typer.Option(
        None, "--context", show_default="from profile", help="Kubernetes context."
    ),
    shell: str = typer.Option("/bin/bash", "--shell", "-s", help="Shell to use."),
    container: str | None = typer.Option(None, "--container", "-c", help="Container name."),
    pod: str | None = typer.Option(None, "--pod", "-p", help="Pod name (skip auto-detection)."),
    command: str | None = typer.Option(
        None, "--command", help="Command to execute instead of a shell."
    ),
) -> None:
    """Open an interactive shell in a module pod."""
    release, namespace, context = resolve_profile_defaults(release, namespace, context)
    import ilum.cli.output as output_mod

    console = output_mod.console

    try:
        ensure_tools(["kubectl"], console)
        resolver = ModuleResolver()
        k8s = KubeClient(kubecontext=context)

        # Resolve module -> pod_label
        mod = resolver.get(module)
        if not mod.pod_label:
            console.error(f"Module '{module}' has no pod_label configured.")
            raise typer.Exit(code=1)

        # Get target pod
        if pod:
            target_pod = pod
        else:
            pods = k8s.list_pods_by_label(namespace, mod.pod_label)
            running: list[PodStatus] = [p for p in pods if p.phase == "Running"]

            if not running:
                console.error(f"No running pods found for module '{module}'.")
                raise typer.Exit(code=1)

            if len(running) == 1:
                target_pod = running[0].name
            else:
                # Multiple pods — check if TTY available
                if sys.stdin.isatty():
                    try:
                        import questionary

                        choices = [p.name for p in running]
                        target_pod = questionary.select(
                            f"Multiple pods for '{module}'. Select one:",
                            choices=choices,
                        ).ask()
                        if target_pod is None:
                            raise typer.Exit(code=0)
                    except ImportError:
                        console.info(
                            f"Multiple pods found for '{module}': "
                            + ", ".join(p.name for p in running)
                        )
                        console.info(
                            "Install 'questionary' for interactive selection, "
                            "or use --pod to specify."
                        )
                        target_pod = running[0].name
                else:
                    console.error(
                        f"Multiple pods found for '{module}'. Use --pod to specify which one."
                    )
                    raise typer.Exit(code=1)

        # Health warning
        target_pods = [p for p in (pods if not pod else []) if p.name == target_pod]
        if target_pods and target_pods[0].restart_count > 5:
            console.warning(
                f"Pod '{target_pod}' has {target_pods[0].restart_count} restarts. "
                "It may be unstable."
            )

        # Build and execute
        cmd = _build_exec_command(target_pod, namespace, context, shell, container, command)
        console.debug(f"Executing: {' '.join(cmd)}")

        # Use os.execvp for proper PTY handling
        if command:
            # Non-interactive — use subprocess so we can capture exit code
            import subprocess

            result = subprocess.run(cmd)
            raise typer.Exit(code=result.returncode)

        # Interactive shell — replace process
        try:
            os.execvp(cmd[0], cmd)
        except FileNotFoundError:
            console.error("kubectl not found on PATH.")
            raise typer.Exit(code=1) from None
        except OSError as exc:
            # Shell not found in container — try fallback
            if shell == "/bin/bash":
                console.warning("bash not available, falling back to /bin/sh")
                cmd = _build_exec_command(
                    target_pod, namespace, context, "/bin/sh", container, None
                )
                os.execvp(cmd[0], cmd)
            else:
                console.error(f"Failed to exec: {exc}")
                raise typer.Exit(code=1) from exc

    except IlumError as exc:
        console.handle_error(exc)
        raise typer.Exit(code=1) from exc
