"""Клиент webhook статусов обучения в 3PL API."""

from __future__ import annotations

import json
import logging
import os
import urllib.error
import urllib.request
from typing import Any, Dict, Optional

logger = logging.getLogger(__name__)


def _truncate_message(message: str, max_len: int = 280) -> str:
    text = (message or "").replace("\n", " ").strip()
    if len(text) > max_len:
        return text[: max_len - 1] + "…"
    return text


class TrainingWebhookClient:
    """
    Отправляет статусы обучения в 3PL.

    POST {SIZE_MODEL_3PL_URL}/api/v1/size-model/training-status
    Header Token: SIZE_MODEL_WEBHOOK_TOKEN
    """

    def __init__(
        self,
        base_url: Optional[str] = None,
        token: Optional[str] = None,
        timeout_sec: Optional[float] = None,
    ):
        self.base_url = (base_url if base_url is not None else os.getenv("SIZE_MODEL_3PL_URL", "")).rstrip("/")
        self.token = token if token is not None else os.getenv("SIZE_MODEL_WEBHOOK_TOKEN", "")
        raw_timeout = timeout_sec if timeout_sec is not None else os.getenv("SIZE_MODEL_WEBHOOK_TIMEOUT_SEC", "10")
        try:
            self.timeout_sec = float(raw_timeout)
        except (TypeError, ValueError):
            self.timeout_sec = 10.0
        self.enabled = bool(self.base_url and self.token)

    def notify(
        self,
        status: str,
        message: str,
        progress: Optional[int] = None,
    ) -> bool:
        """
        Отправляет событие в 3PL. Ошибки не пробрасываются.

        :param status: started | progress | completed | failed
        :param message: Короткий текст для Битрикс24.
        :param progress: Опциональный процент 0–100.
        :return: True при HTTP 200, иначе False.
        """
        if not self.enabled:
            logger.debug("Training webhook disabled (URL or token empty)")
            return False
        if status not in {"started", "progress", "completed", "failed", "cancelled"}:
            logger.warning("Invalid webhook status: %s", status)
            return False
        body: Dict[str, Any] = {
            "status": status,
            "message": _truncate_message(message),
        }
        if progress is not None:
            body["progress"] = int(max(0, min(100, progress)))
        url = f"{self.base_url}/api/v1/size-model/training-status"
        payload = json.dumps(body, ensure_ascii=False).encode("utf-8")
        request = urllib.request.Request(
            url,
            data=payload,
            method="POST",
            headers={
                "Token": self.token,
                "Content-Type": "application/json",
                "Accept": "application/json",
            },
        )
        try:
            with urllib.request.urlopen(request, timeout=self.timeout_sec) as response:
                code = getattr(response, "status", None) or response.getcode()
                if code != 200:
                    logger.warning("3PL training webhook HTTP %s", code)
                    return False
                return True
        except urllib.error.HTTPError as e:
            logger.warning("3PL training webhook HTTPError %s: %s", e.code, e.reason)
            return False
        except Exception as e:
            logger.warning("3PL training webhook failed: %s", e)
            return False
