"""Independent Telegram transport for the sidecar (D7, FR-8, BR-8).

Reads its OWN ``WATCHDOG_TG_BOT_TOKEN`` / ``WATCHDOG_TG_CHAT_ID`` and POSTs via
``urllib`` to ``api.telegram.org``. It is FORBIDDEN to import
``src/notifications.py`` or to use the orchestrator's token / chat / functions —
otherwise a crash or refactor of the orchestrator would drag down the alert
channel (a direct violation of C-1 / BR-8). Missing token/chat -> log and skip
(fail-safe), never raise (NFR-3).
"""
from __future__ import annotations

import logging
import urllib.parse
import urllib.request

logger = logging.getLogger("watchdog.notify")

_TELEGRAM_API = "https://api.telegram.org"


def send_telegram(
    bot_token: str,
    chat_id: str,
    text: str,
    timeout_s: float = 5.0,
    *,
    api_base: str = _TELEGRAM_API,
    opener=urllib.request.urlopen,
) -> bool:
    """Send one Telegram message over the sidecar's own bot. never-raise (D8).

    Returns ``True`` on a delivered message, ``False`` on any failure (missing
    credentials, network error, non-2xx). ``opener`` / ``api_base`` are injected
    so tests never touch the real network.
    """
    if not bot_token or not chat_id:
        logger.warning("watchdog: telegram token/chat not configured -> skip send")
        return False
    try:
        url = f"{api_base}/bot{bot_token}/sendMessage"
        payload = urllib.parse.urlencode(
            {
                "chat_id": chat_id,
                "text": text,
                "parse_mode": "HTML",
                "disable_web_page_preview": "true",
            }
        ).encode("utf-8")
        req = urllib.request.Request(url, data=payload, method="POST")
        with opener(req, timeout=timeout_s) as resp:
            status = getattr(resp, "status", None) or resp.getcode()
            return 200 <= int(status) < 300
    except Exception as e:  # noqa: BLE001 - delivery is best-effort
        logger.warning("watchdog: telegram send failed: %s", e)
        return False


class Notifier:
    """Thin stateful wrapper binding the sidecar credentials for the tick loop."""

    def __init__(self, bot_token: str, chat_id: str, timeout_s: float = 5.0):
        self._token = bot_token
        self._chat = chat_id
        self._timeout = timeout_s

    def send(self, text: str) -> bool:
        """Best-effort send through the sidecar's own channel (never raises)."""
        return send_telegram(self._token, self._chat, text, self._timeout)
