"""Keiro infrastructure defaults — single source of truth.

Values are read from ``defaults.yaml`` (bundled inside the wheel).
Override at runtime via ``~/.keiro/credentials``, environment variables,
or explicit function arguments.

Missing keys cause immediate ``KeyError`` with a clear traceback —
no silent fallbacks.
"""

from __future__ import annotations

from pathlib import Path
from typing import Dict

import yaml

_DEFAULTS_PATH = Path(__file__).parent / "defaults.yaml"
_DEFAULTS = yaml.safe_load(_DEFAULTS_PATH.read_text())

DEFAULT_GATEWAY_URL: str = _DEFAULTS["gateway"]["url"]
DEFAULT_MODEL: str = _DEFAULTS["gateway"]["model"]
DEFAULT_API_KEY: str = _DEFAULTS["gateway"]["api_key"]

# Derived constants parsed from DEFAULT_GATEWAY_URL.
_parsed_url = __import__("urllib.parse", fromlist=["urlparse"]).urlparse(
    DEFAULT_GATEWAY_URL
)
DEFAULT_GATEWAY_HOST: str = _parsed_url.hostname or "localhost"
DEFAULT_GATEWAY_PORT: int = _parsed_url.port or 8080
del _parsed_url

# --- Timeout defaults (seconds) ---
_TIMEOUTS: Dict[str, object] = _DEFAULTS["timeouts"]

CONNECT_TIMEOUT: float = float(_TIMEOUTS["connect"])
READ_TIMEOUT_STANDARD: float = float(_TIMEOUTS["read_standard"])
READ_TIMEOUT_REASONING: float = float(_TIMEOUTS["read_reasoning"])

EB1_PER_STAGE_TIMEOUT: Dict[str, float] = {
    k: float(v) for k, v in _TIMEOUTS["eb1_per_stage"].items()  # type: ignore[union-attr]
}
EB1_VARIANT_STAGES: Dict[str, int] = {
    k: int(v) for k, v in _TIMEOUTS["eb1_stages"].items()  # type: ignore[union-attr]
}

# Models requiring GNN server routing (not local ensemble).
# Generated from catalog at import time — no manual maintenance.
def _build_gnn_routed_prefixes() -> frozenset[str]:
    try:
        from keiro.ensemble.catalog import all_variants
        return frozenset(
            v.key for v in all_variants() if v.route_kind == "gnn"
        )
    except (ImportError, ModuleNotFoundError):
        # Fallback for minimal installs without the catalog.
        return frozenset((
            "eb1-preview",
            "eb1-fast-preview",
            "eb1-frontier-preview",
            "eb1-delta-preview",
        ))

EB1_GNN_ROUTED_PREFIXES: frozenset[str] = _build_gnn_routed_prefixes()


# ---------------------------------------------------------------------------
# Gateway URL resolution helpers
# ---------------------------------------------------------------------------


def get_gateway_url() -> str:
    """Return the default gateway URL, respecting env var override.

    Resolution order:
        1. EB1_GATEWAY_URL environment variable (full URL).
        2. EB1_GATEWAY_HOST environment variable (composed with default port).
        3. defaults.yaml gateway.url.
    """
    import os

    env_url = os.environ.get("EB1_GATEWAY_URL")
    if env_url:
        return env_url.rstrip("/")
    env_host = os.environ.get("EB1_GATEWAY_HOST")
    if env_host:
        return f"http://{env_host}:{DEFAULT_GATEWAY_PORT}"
    return DEFAULT_GATEWAY_URL


def get_gateway_host() -> str:
    """Return just the hostname/IP from the gateway URL."""
    import os

    env_host = os.environ.get("EB1_GATEWAY_HOST")
    if env_host:
        return env_host
    from urllib.parse import urlparse

    return urlparse(DEFAULT_GATEWAY_URL).hostname or "localhost"


def get_gateway_port() -> int:
    """Return the port number from the default gateway URL."""
    from urllib.parse import urlparse

    return urlparse(DEFAULT_GATEWAY_URL).port or 8080
