"""Thin subprocess wrapper for the ``rdctl`` CLI (Rancher Desktop).

Provides typed access to Rancher Desktop's control plane:
configure K3s settings, execute commands inside the VM, and manage
the application lifecycle.
"""

from __future__ import annotations

import json
import logging
import subprocess
from dataclasses import dataclass
from pathlib import Path

logger = logging.getLogger(__name__)

_DEFAULT_RDCTL_BIN = str(Path.home() / ".rd" / "bin" / "rdctl")


@dataclass(frozen=True)
class RdctlSettings:
    """Subset of ``rdctl list-settings`` relevant to Citadel."""

    kubernetes_version: str
    flannel_enabled: bool
    traefik_enabled: bool
    container_engine: str  # "containerd" | "moby"


class Rdctl:
    """Typed wrapper around the ``rdctl`` binary."""

    def __init__(self, rdctl_bin: str = _DEFAULT_RDCTL_BIN) -> None:
        self._bin = rdctl_bin

    # ------------------------------------------------------------------
    # Public API
    # ------------------------------------------------------------------

    def set(self, **kwargs: str | bool) -> subprocess.CompletedProcess[str]:
        """``rdctl set --key=value ...``"""
        args: list[str] = []
        for key, value in kwargs.items():
            flag = f"--{key.replace('_', '.')}"
            if isinstance(value, bool):
                args.append(f"{flag}={'true' if value else 'false'}")
            else:
                args.append(f"{flag}={value}")
        return self._run([self._bin, "set", *args])

    def shell(self, *cmd: str) -> subprocess.CompletedProcess[str]:
        """``rdctl shell -- <cmd>``"""
        return self._run([self._bin, "shell", "--", *cmd])

    def list_settings(self) -> RdctlSettings:
        """Parse ``rdctl list-settings`` JSON into :class:`RdctlSettings`."""
        result = self._run([self._bin, "list-settings"])
        if result.returncode != 0:
            raise RuntimeError(f"rdctl list-settings failed: {result.stderr}")
        data = json.loads(result.stdout)
        k8s = data.get("kubernetes", {})
        options = k8s.get("options", {})
        return RdctlSettings(
            kubernetes_version=k8s.get("version", ""),
            flannel_enabled=options.get("flannel", True),
            traefik_enabled=options.get("traefik", True),
            container_engine=data.get("containerEngine", {}).get("name", "containerd"),
        )

    def shutdown(self) -> subprocess.CompletedProcess[str]:
        """``rdctl shutdown``"""
        return self._run([self._bin, "shutdown"])

    def start(self, **kwargs: str | bool) -> subprocess.CompletedProcess[str]:
        """``rdctl start [--key=value ...]``"""
        args: list[str] = []
        for key, value in kwargs.items():
            flag = f"--{key.replace('_', '.')}"
            if isinstance(value, bool):
                args.append(f"{flag}={'true' if value else 'false'}")
            else:
                args.append(f"{flag}={value}")
        return self._run([self._bin, "start", *args])

    def factory_reset(self) -> subprocess.CompletedProcess[str]:
        """``rdctl factory-reset``"""
        return self._run([self._bin, "factory-reset"])

    def version(self) -> str:
        """Return the ``rdctl`` version string."""
        result = self._run([self._bin, "version"])
        if result.returncode != 0:
            raise RuntimeError(f"rdctl version failed: {result.stderr}")
        return result.stdout.strip()

    # ------------------------------------------------------------------
    # Internal
    # ------------------------------------------------------------------

    @staticmethod
    def _run(
        cmd: list[str], timeout: int = 60
    ) -> subprocess.CompletedProcess[str]:
        """Run a subprocess command."""
        return subprocess.run(
            cmd,
            capture_output=True,
            text=True,
            timeout=timeout,
            check=False,
        )
