from __future__ import annotations

import html as _html
from pathlib import Path
from typing import Any

import requests

from . import Alert

_BASE = "https://api.telegram.org/bot{token}/{method}"


class TelegramNotifier:
    name = "telegram"

    def __init__(self, bot_token: str, chat_id: str, session: Any = None) -> None:
        self._token = bot_token
        self._chat_id = chat_id
        self._session = session or requests.Session()

    def _url(self, method: str) -> str:
        return _BASE.format(token=self._token, method=method)

    def send(self, alert: Alert) -> None:
        text = f"<b>{_html.escape(alert.title)}</b>\n{_html.escape(alert.body)}"

        if alert.image_path and Path(alert.image_path).exists():
            with open(alert.image_path, "rb") as fh:
                resp = self._session.post(
                    self._url("sendPhoto"),
                    data={
                        "chat_id": self._chat_id,
                        "caption": text,
                        "parse_mode": "HTML",
                        "disable_notification": str(alert.silent).lower(),
                    },
                    files={"photo": fh},
                    timeout=10,
                )
        else:
            resp = self._session.post(
                self._url("sendMessage"),
                json={
                    "chat_id": self._chat_id,
                    "text": text,
                    "parse_mode": "HTML",
                    "disable_notification": alert.silent,
                },
                timeout=10,
            )

        if resp.status_code == 429:
            raise RuntimeError(f"Telegram rate-limited (429): {resp.text}")
        if resp.status_code >= 500:
            raise RuntimeError(f"Telegram server error ({resp.status_code}): {resp.text}")
        if resp.status_code != 200:
            raise RuntimeError(f"Telegram unexpected status ({resp.status_code}): {resp.text}")

        # Telegram Bot API returns 200 OK with {"ok": false, ...} for several
        # logical failures (bot blocked, invalid chat_id, parse_mode errors).
        # Parse body and raise on ok:false so Fanout retries + DLQs + stats count it.
        try:
            body = resp.json()
        except ValueError:
            return  # non-JSON body — treat as success (shouldn't happen in practice)
        if isinstance(body, dict) and body.get("ok") is False:
            code = body.get("error_code", "?")
            desc = body.get("description", "unknown")
            raise RuntimeError(f"Telegram logical failure ({code}): {desc}")
