"""SalmAlm Reaction Tools — Send emoji reactions across channels."""

from __future__ import annotations

import json
import urllib.request
from typing import Any, Dict, Optional

from salmalm import log


def send_reaction(
    channel: str,
    message_id: str,
    emoji: str,
    *,
    chat_id: Optional[str] = None,
    channel_id: Optional[str] = None,
    config: Optional[Dict[str, Any]] = None,
) -> Dict[str, Any]:
    """Send an emoji reaction to a message.

    Args:
        channel: Channel type ('telegram', 'discord', 'slack', 'web')
        message_id: Message identifier
        emoji: Emoji to react with (e.g. '👍', ':thumbsup:')
        chat_id: Telegram chat ID
        channel_id: Discord/Slack channel ID
        config: Channel-specific config (tokens etc)

    Returns:
        Result dict with 'ok' status.
    """
    config = config or {}

    if channel == "telegram":
        return _react_telegram(chat_id or "", message_id, emoji, config)
    elif channel == "discord":
        return _react_discord(channel_id or "", message_id, emoji, config)
    elif channel == "slack":
        return _react_slack(channel_id or "", message_id, emoji, config)
    elif channel == "web":
        return _react_web(message_id, emoji, config)
    else:
        return {"ok": False, "error": f"Unsupported channel: {channel}"}


def _react_telegram(chat_id: str, message_id: str, emoji: str, config: Dict[str, Any]) -> Dict[str, Any]:
    """Send reaction via Telegram setMessageReaction API."""
    token = config.get("token", "")
    if not token:
        return {"ok": False, "error": "No Telegram token"}

    url = f"https://api.telegram.org/bot{token}/setMessageReaction"
    data = json.dumps(
        {
            "chat_id": chat_id,
            "message_id": int(message_id),
            "reaction": [{"type": "emoji", "emoji": emoji}],
            "is_big": False,
        }
    ).encode()
    req = urllib.request.Request(url, data=data, method="POST")
    req.add_header("Content-Type", "application/json")
    try:
        with urllib.request.urlopen(req, timeout=10) as resp:
            result = json.loads(resp.read().decode())
            return {"ok": result.get("ok", False), "result": result}
    except Exception as e:
        log.error(f"Telegram reaction error: {e}")
        return {"ok": False, "error": str(e)}


def _react_discord(channel_id: str, message_id: str, emoji: str, config: Dict[str, Any]) -> Dict[str, Any]:
    """Send reaction via Discord addReaction API."""
    token = config.get("token", "")
    if not token:
        return {"ok": False, "error": "No Discord token"}

    import urllib.parse

    encoded_emoji = urllib.parse.quote(emoji)
    url = f"https://discord.com/api/v10/channels/{channel_id}/messages/{message_id}/reactions/{encoded_emoji}/@me"
    req = urllib.request.Request(url, method="PUT")
    req.add_header("Authorization", f"Bot {token}")
    req.add_header("Content-Length", "0")
    try:
        with urllib.request.urlopen(req, timeout=10) as _resp:  # noqa: F841
            return {"ok": True}
    except urllib.error.HTTPError as e:
        err = e.read().decode("utf-8", errors="replace")
        log.error(f"Discord reaction error: {e.code} {err[:200]}")
        return {"ok": False, "error": f"{e.code}: {err[:200]}"}
    except Exception as e:
        log.error(f"Discord reaction error: {e}")
        return {"ok": False, "error": str(e)}


def _react_slack(channel_id: str, timestamp: str, emoji: str, config: Dict[str, Any]) -> Dict[str, Any]:
    """Send reaction via Slack reactions.add API."""
    token = config.get("token", "")
    if not token:
        return {"ok": False, "error": "No Slack token"}

    url = "https://slack.com/api/reactions.add"
    data = json.dumps(
        {
            "channel": channel_id,
            "timestamp": timestamp,
            "name": emoji.strip(":"),
        }
    ).encode()
    req = urllib.request.Request(url, data=data, method="POST")
    req.add_header("Authorization", f"Bearer {token}")
    req.add_header("Content-Type", "application/json")
    try:
        with urllib.request.urlopen(req, timeout=10) as resp:
            result = json.loads(resp.read().decode())
            return {"ok": result.get("ok", False), "error": result.get("error")}
    except Exception as e:
        log.error(f"Slack reaction error: {e}")
        return {"ok": False, "error": str(e)}


def _react_web(message_id: str, emoji: str, config: Dict[str, Any]) -> Dict[str, Any]:
    """Queue a reaction event for WebSocket delivery."""
    # Web reactions are dispatched via WS broadcast
    ws_broadcast = config.get("ws_broadcast")
    if ws_broadcast and callable(ws_broadcast):
        ws_broadcast(
            {
                "type": "reaction",
                "messageId": message_id,
                "emoji": emoji,
            }
        )
        return {"ok": True}
    return {"ok": True, "queued": True}


# ── Tool definition for engine registration ──

REACTION_TOOL = {
    "type": "function",
    "function": {
        "name": "send_reaction",
        "description": "React to a message with an emoji. Works across Telegram, Discord, Slack, and web.",
        "parameters": {
            "type": "object",
            "properties": {
                "emoji": {
                    "type": "string",
                    "description": "Emoji to react with (e.g. 👍, ❤️, 😂)",
                },
                "message_id": {
                    "type": "string",
                    "description": "ID of the message to react to",
                },
                "channel": {
                    "type": "string",
                    "description": "Channel type (telegram, discord, slack, web)",
                    "enum": ["telegram", "discord", "slack", "web"],
                },
            },
            "required": ["emoji"],
        },
    },
}
