# rye:signed:2026-04-01T06:49:05Z:d9f51d386deda66215ef9730c73a390b12a181b1215cc04a6660d58504bdae33:Du8O3aySI-D585UTD8AJOi9AAccTbQhZggHI0Hqi7Wdq1belLBt6MQ_6VmWGkhE9AaTqLDQ6-L3ZxFZvy2yxBw:6ea18199041a1ea8
"""Named remote resolution for multi-remote execution.

Resolves remote connection details (URL + API key) via 3-tier config
resolution (system → user → project).

Config path: .ai/config/cas/remote.yaml
"""

__version__ = "1.0.0"
__tool_type__ = "python"
__category__ = "rye/core/remote"
__tool_description__ = "Named remote config resolution library"

import logging
import os
from dataclasses import dataclass
from pathlib import Path
from typing import Dict, Optional

logger = logging.getLogger(__name__)

_CONFIG_REL_PATH = "cas/remote.yaml"


@dataclass(frozen=True)
class RemoteConfig:
    """Resolved remote connection details."""

    name: str
    url: str
    node_id: str = ""  # fp:<fingerprint> of the remote node (audience for request signing)


def _load_remote_config(project_path: Optional[Path] = None) -> Dict:
    """Load remote.yaml via 3-tier resolution."""
    from rye.cas.manifest import _load_config_3tier
    return _load_config_3tier(_CONFIG_REL_PATH, project_path)


def resolve_remote(
    name: Optional[str] = None,
    project_path: Optional[Path] = None,
) -> RemoteConfig:
    """Resolve a named remote to connection details.

    Looks up *name* (default: ``"default"``) in the merged ``remotes:``
    map from ``cas/remote.yaml``.

    Raises:
        ValueError: If remote cannot be resolved.
    """
    name = name or "default"
    config = _load_remote_config(project_path)
    remotes = config.get("remotes", {})
    if not isinstance(remotes, dict):
        remotes = {}

    if name not in remotes:
        raise ValueError(
            f"Remote '{name}' not found in cas/remote.yaml. "
            f"Available remotes: {list(remotes.keys()) or ['(none)']}"
        )

    entry = remotes[name]
    if not isinstance(entry, dict):
        raise ValueError(
            f"Remote '{name}' must be a mapping (url + key_env), "
            f"got {type(entry).__name__}"
        )
    url = entry.get("url", "")
    if not url:
        raise ValueError(
            f"Remote '{name}' has no url configured in cas/remote.yaml"
        )
    node_id = entry.get("node_id", "")
    return RemoteConfig(name=name, url=url, node_id=node_id)


def get_project_path(project_path: Optional[Path] = None) -> str:
    """Get stable project path identifier from config, falling back to dir basename."""
    config = _load_remote_config(project_path)
    name = config.get("project_path")
    if name and isinstance(name, str):
        return name
    if project_path:
        return project_path.resolve().name
    return "unknown"


def list_remotes(project_path: Optional[Path] = None) -> Dict[str, Dict]:
    """List all configured remotes with their URLs (keys redacted)."""
    config = _load_remote_config(project_path)
    remotes = config.get("remotes", {})
    if not isinstance(remotes, dict):
        remotes = {}
    result = {}
    for rname, entry in remotes.items():
        if not isinstance(entry, dict):
            continue
        result[rname] = {
            "url": entry.get("url", ""),
            "node_id": entry.get("node_id", ""),
        }
    return result
