"""WinRM client for executing PowerShell commands on Windows VMs."""

from __future__ import annotations

import winrm

_DEFAULT_PASSWORD = "vagrant"  # noqa: S105


def _decode_winrm(b: bytes) -> str:
    return b.decode("utf-8", errors="replace").strip().replace("\r\n", "\n")


class WinRMClient:
    """Executes PowerShell commands on a Windows VM via WinRM."""

    def __init__(
        self, host: str, username: str = "vagrant", password: str = _DEFAULT_PASSWORD, port: int = 5985
    ) -> None:
        """Initialise a WinRM session.

        Args:
            host: Hostname or IP address of the WinRM endpoint.
            username: Windows account username.
            password: Windows account password.
            port: TCP port the WinRM HTTP listener is bound to.
        """
        self._session = winrm.Session(f"http://{host}:{port}/wsman", auth=(username, password), transport="ntlm")

    def run_ps(self, script: str) -> str:
        """Execute a PowerShell script and return stdout as a string.

        Args:
            script: PowerShell script text to execute.

        Returns:
            Decoded stdout with Windows line-endings normalised to LF.

        Raises:
            RuntimeError: If PowerShell exits with a non-zero status code.
        """
        result = self._session.run_ps(script)
        stdout: str = _decode_winrm(result.std_out)
        if result.status_code != 0:
            stderr = _decode_winrm(result.std_err)
            raise RuntimeError(f"PowerShell exited {result.status_code}: {stderr}")
        return stdout

    def run_ps_raw(self, script: str) -> tuple[str, str, int]:
        r"""Execute a PowerShell script and return (stdout, stderr, exit_code).

        Unlike run_ps(), this method never raises on non-zero exit code.
        Use this for verification checks where failure is expected and must be reported.

        Args:
            script: PowerShell script text to execute.

        Returns:
            Tuple of (stdout, stderr, exit_code). Strings have \\r\\n normalised to \\n.
        """
        result = self._session.run_ps(script)
        return (_decode_winrm(result.std_out), _decode_winrm(result.std_err), result.status_code)

    def read_file(self, guest_path: str) -> str:
        """Read the full contents of a file on the guest VM.

        Args:
            guest_path: Absolute path to the file on the Windows guest.

        Returns:
            File contents as a string.
        """
        escaped = guest_path.replace("\\", "\\\\")
        return self.run_ps(f"Get-Content '{escaped}' -Raw")


class WinRMPool:
    """Process-level WinRM handle for MCP lifespan context (pooling TBD).

    Tools receive this from lifespan until connection pooling is implemented.
    """

    def close(self) -> None:
        """Release pooled WinRM sessions (no-op until pooling is implemented)."""
