from __future__ import annotations

import os
from dataclasses import dataclass
from pathlib import Path
from typing import Any, Callable

import requests

from alerting import AlertPlan


def _parse_env_file(path: Path) -> dict[str, str]:
    values: dict[str, str] = {}
    if not path.exists():
        return values
    for line in path.read_text(encoding="utf-8", errors="replace").splitlines():
        stripped = line.strip()
        if not stripped or stripped.startswith("#") or "=" not in stripped:
            continue
        key, value = stripped.split("=", 1)
        values[key.strip()] = value.strip().strip('"').strip("'")
    return values


def _env_value(key: str, file_values: dict[str, str]) -> str | None:
    return os.getenv(key) or file_values.get(key)


@dataclass(frozen=True)
class TelegramAlertConfig:
    enabled: bool = False
    bot_token: str | None = None
    chat_id: str | None = None
    thread_id: int | None = None
    timeout_seconds: int = 10

    @classmethod
    def from_env(cls) -> "TelegramAlertConfig":
        env_file = Path(os.getenv("CTB_TELEGRAM_ENV_FILE", str(Path.home() / ".hermes" / "secrets" / "crypto_agent_telegram.env")))
        file_values = _parse_env_file(env_file)
        enabled_raw = _env_value("CTB_TELEGRAM_ALERTS", file_values) or "false"
        enabled = enabled_raw.strip().lower() in {"1", "true", "yes", "on", "y"}
        thread_raw = _env_value("CTB_TELEGRAM_THREAD_ID", file_values)
        timeout_raw = _env_value("CTB_TELEGRAM_TIMEOUT", file_values) or "10"
        return cls(
            enabled=enabled,
            bot_token=_env_value("CTB_TELEGRAM_BOT_TOKEN", file_values),
            chat_id=_env_value("CTB_TELEGRAM_CHAT_ID", file_values),
            thread_id=int(thread_raw) if thread_raw else None,
            timeout_seconds=int(timeout_raw),
        )


@dataclass(frozen=True)
class TelegramSendResult:
    sent: bool
    reason: str
    message_id: int | None = None


def _default_sender(url: str, payload: dict[str, Any], timeout: int) -> dict[str, Any]:
    response = requests.post(url, json=payload, timeout=timeout)
    response.raise_for_status()
    return response.json()


def send_telegram_alert(
    alert: AlertPlan,
    config: TelegramAlertConfig,
    *,
    sender: Callable[[str, dict[str, Any], int], dict[str, Any]] | None = None,
) -> TelegramSendResult:
    if not config.enabled:
        return TelegramSendResult(False, "disabled")
    if not config.bot_token or not config.chat_id:
        return TelegramSendResult(False, "missing_credentials")
    if config.thread_id is None:
        return TelegramSendResult(False, "missing_thread_id")

    payload = {
        "chat_id": config.chat_id,
        "message_thread_id": config.thread_id,
        "text": alert.text,
        "disable_web_page_preview": True,
    }
    send = sender or _default_sender
    url = f"https://api.telegram.org/bot{config.bot_token}/sendMessage"
    result = send(url, payload, config.timeout_seconds)
    if not result.get("ok"):
        return TelegramSendResult(False, str(result.get("description") or "telegram_error"))
    message_id = result.get("result", {}).get("message_id")
    return TelegramSendResult(True, "ok", message_id=message_id)
