"""
WeCom (企业微信) robot webhook helpers.

Only text/markdown messages are supported for now.

API:
  POST https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxx
  Content-Type: application/json
  {
    "msgtype": "text",
    "text": {"content": "hello world"}
  }
"""

from __future__ import annotations

import json
from dataclasses import dataclass
from typing import Any
from urllib.error import HTTPError, URLError
from urllib.parse import urlencode
from urllib.request import Request, urlopen

from django.conf import settings


@dataclass(frozen=True)
class WeComWebhookResponse:
    errcode: int
    errmsg: str
    raw: dict[str, Any]

    @property
    def ok(self) -> bool:
        return int(self.errcode) == 0


def send_wecom_webhook_message(
    *,
    content: str,
    msgtype: str = "text",
    key: str | None = None,
    timeout_seconds: float = 10.0,
) -> WeComWebhookResponse:
    """
    Send a message to WeCom robot webhook.

    Supported msgtype:
    - text: {"msgtype":"text","text":{"content": "..."}}
    - markdown: {"msgtype":"markdown","markdown":{"content": "..."}}
    """
    t = (msgtype or "text").strip().lower()
    if t not in {"text", "markdown"}:
        raise ValueError("msgtype 仅支持 text 或 markdown")

    content = (content or "").strip()
    if not content:
        raise ValueError("content 不能为空")

    base_url = getattr(settings, "WECOM_WEBHOOK_BASE_URL", "").strip()
    if not base_url:
        base_url = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send"

    k = (key or getattr(settings, "WECOM_WEBHOOK_KEY", "") or "").strip()
    if not k:
        raise ValueError("WeCom webhook key 未配置（settings.WECOM_WEBHOOK_KEY）")

    url = f"{base_url}?{urlencode({'key': k})}"
    if t == "markdown":
        payload = {"msgtype": "markdown", "markdown": {"content": content}}
    else:
        payload = {"msgtype": "text", "text": {"content": content}}

    data = json.dumps(payload, ensure_ascii=False).encode("utf-8")

    req = Request(
        url=url,
        data=data,
        headers={"Content-Type": "application/json"},
        method="POST",
    )

    try:
        with urlopen(req, timeout=float(timeout_seconds)) as resp:
            body = resp.read().decode("utf-8", errors="replace")
    except HTTPError as exc:
        body = ""
        try:
            body = exc.read().decode("utf-8", errors="replace")
        except Exception:
            pass
        raise RuntimeError(f"WeCom webhook HTTPError: status={exc.code}, body={body}") from exc
    except URLError as exc:
        raise RuntimeError(f"WeCom webhook URLError: {exc}") from exc

    try:
        raw = json.loads(body) if body else {}
    except Exception as exc:
        raise RuntimeError(f"WeCom webhook 响应不是合法 JSON: {body}") from exc

    errcode = int(raw.get("errcode") or 0)
    errmsg = str(raw.get("errmsg") or "")
    return WeComWebhookResponse(errcode=errcode, errmsg=errmsg, raw=raw)


def send_wecom_webhook_text(
    *,
    content: str,
    key: str | None = None,
    timeout_seconds: float = 10.0,
) -> WeComWebhookResponse:
    """
    Backward-compatible wrapper for sending text.
    """
    return send_wecom_webhook_message(content=content, msgtype="text", key=key, timeout_seconds=timeout_seconds)

