"""Resolve named or ad-hoc infrastructure targets from a TOML configuration file."""

from __future__ import annotations

import functools
import tomllib
from dataclasses import dataclass, field
from pathlib import Path

_TOML_PATH = Path(__file__).parent / "infra_targets.toml"

_DEFAULT_WINRM_HOST = "127.0.0.1"
_DEFAULT_WINRM_PORT = 5985
_DEFAULT_TUNNEL_LOCAL_PORT = 15985


@dataclass(frozen=True)
class TargetConfig:
    """Resolved connection parameters for a named or ad-hoc infrastructure target.

    Attributes:
        ssh_host: SSH destination string (e.g. ``user@host``).  Empty string
            means the target is local — no SSH hop is used.
        ssh_port: SSH port number.  ``0`` means use the default port (22).
        ssh_user: SSH login name passed via ``-l``.  Empty string means the
            user is either embedded in *ssh_host* (``user@host``) or defaults
            to the current OS user.
        ssh_identity_file: Path to the SSH private key file.  Empty string
            means no explicit identity file is passed (use SSH agent / default).
        winrm_host: Hostname or IP the WinRM service listens on from the
            perspective of the SSH tunnel endpoint (or localhost for local).
        winrm_port: TCP port the WinRM HTTP listener is bound to.
        tunnel_local_port: Local port to bind when forwarding WinRM through
            an SSH tunnel.  Unused for local targets.
        podman_socket_path: Path to Podman socket on target.
            When empty, uses ``/run/podman/podman.sock`` (root) or rootless
            ``/run/user/1000/podman/podman.sock`` for remote; local uses
            ``unix:///run/podman/podman.sock``.
    """

    ssh_host: str
    ssh_port: int = field(default=0)
    ssh_user: str = field(default="")
    ssh_identity_file: str = field(default="")
    podman_socket_path: str = field(default="")
    winrm_host: str = field(default=_DEFAULT_WINRM_HOST)
    winrm_port: int = field(default=_DEFAULT_WINRM_PORT)
    tunnel_local_port: int = field(default=_DEFAULT_TUNNEL_LOCAL_PORT)

    @property
    def is_remote(self) -> bool:
        """Return True when the target requires an SSH hop."""
        return bool(self.ssh_host)


@functools.cache
def _load_toml(toml_path: Path) -> dict[str, dict[str, str | int]]:
    """Load and cache the targets TOML file for the process lifetime.

    The result is memoised by *toml_path* so the file is only read once per
    unique path per process, regardless of how many tool calls are made.

    Args:
        toml_path: Absolute path to ``infra_targets.toml``.

    Returns:
        The ``[targets]`` table as a dict of name → config-dict pairs.

    Raises:
        FileNotFoundError: If *toml_path* does not exist.
    """
    with toml_path.open("rb") as fh:
        data = tomllib.load(fh)
    named: dict[str, dict[str, str | int]] = data.get("targets", {})
    return named


def resolve_target(target: str, toml_path: Path = _TOML_PATH) -> TargetConfig:
    """Resolve a target string to a :class:`TargetConfig`.

    Resolution order:

    1. Look up *target* in the ``[targets]`` table of *toml_path*.
    2. If not found, treat *target* as a raw SSH string (must contain ``@``).

    Args:
        target: Named target (``"local"``, ``"ci"``) or raw SSH string
            (``"user@host"``).
        toml_path: Path to ``infra_targets.toml``.  Defaults to the file
            bundled alongside this module.

    Returns:
        A fully-populated :class:`TargetConfig`.

    Raises:
        ValueError: If *target* is not a known name and not a raw SSH string.
        FileNotFoundError: If *toml_path* does not exist.
    """
    named = _load_toml(toml_path)

    if target in named:
        cfg = named[target]
        return TargetConfig(
            ssh_host=str(cfg.get("ssh_host", "")),
            ssh_port=int(cfg.get("ssh_port", 0)),
            ssh_user=str(cfg.get("ssh_user", "")),
            ssh_identity_file=str(cfg.get("ssh_identity_file", "")),
            winrm_host=str(cfg.get("winrm_host", _DEFAULT_WINRM_HOST)),
            winrm_port=int(cfg.get("winrm_port", _DEFAULT_WINRM_PORT)),
            tunnel_local_port=int(cfg.get("tunnel_local_port", _DEFAULT_TUNNEL_LOCAL_PORT)),
            podman_socket_path=str(cfg.get("podman_socket_path", "")),
        )

    if "@" in target:
        return TargetConfig(ssh_host=target)

    raise ValueError(f"Unknown target '{target}'. Check infra_targets.toml or pass user@host directly.")
