from __future__ import annotations

from typing import Any


_STALE_SUBSTRINGS = (
    # Common DA error string when a cached SPCS endpoint has been rotated.
    "could not find the service associated with endpoint",
    "service associated with endpoint",
)

_STALE_DNS_SUBSTRINGS = (
    # Conservative set of DNS-ish failures that strongly suggest the host is gone.
    "name or service not known",
    "nodename nor servname provided",
    "temporary failure in name resolution",
    "no address associated with hostname",
    "could not resolve host",
    "dns resolution failed",
    "dns lookup failed",
    "encoding with 'idna' codec failed",
    "label empty or too long",
)

_ALL_STALE_SUBSTRINGS = _STALE_SUBSTRINGS + _STALE_DNS_SUBSTRINGS


def _norm(s: object) -> str:
    try:
        return str(s).strip().lower()
    except Exception:
        return ""


def _contains_stale_indicator(value: object) -> bool:
    s = _norm(value)
    return bool(s) and any(x in s for x in _ALL_STALE_SUBSTRINGS)


def is_endpoint_stale_message(msg: object) -> bool:
    return _contains_stale_indicator(msg)


def is_endpoint_stale_exception(exc: BaseException) -> bool:
    return _contains_stale_indicator(exc)


def is_endpoint_stale_payload(payload: Any) -> bool:
    if isinstance(payload, dict):
        msg = payload.get("message") or payload.get("error") or payload.get("detail") or payload.get("details")
        return is_endpoint_stale_message(msg) or is_endpoint_stale_message(payload)
    if isinstance(payload, str):
        return is_endpoint_stale_message(payload)
    return is_endpoint_stale_message(payload)


__all__ = [
    "is_endpoint_stale_exception",
    "is_endpoint_stale_message",
    "is_endpoint_stale_payload",
]

