"""Notification tool: send alerts via webhooks and control plane."""

from __future__ import annotations

import json
from typing import Any, Awaitable, Callable

import httpx
from loguru import logger

from madpod_agent.agent.tools.base import Tool
from madpod_agent.bus.events import OutboundMessage

_WEBHOOK_TIMEOUT = 10.0


class NotifyTool(Tool):
    """Send notifications and alerts to the user or external webhooks."""

    def __init__(
        self,
        send_callback: Callable[[OutboundMessage], Awaitable[None]] | None = None,
        default_channel: str = "",
        default_chat_id: str = "",
    ):
        self._send_callback = send_callback
        self._default_channel = default_channel
        self._default_chat_id = default_chat_id

    def set_send_callback(self, callback: Callable[[OutboundMessage], Awaitable[None]]) -> None:
        self._send_callback = callback

    def set_context(self, channel: str, chat_id: str) -> None:
        self._default_channel = channel
        self._default_chat_id = chat_id

    @property
    def name(self) -> str:
        return "notify"

    @property
    def description(self) -> str:
        return (
            "Send a notification or alert. Can notify the user via the control plane "
            "or send to an external webhook URL (Slack, Discord, etc.). "
            "Use for monitoring alerts, task completion, or important updates."
        )

    @property
    def parameters(self) -> dict[str, Any]:
        return {
            "type": "object",
            "properties": {
                "title": {
                    "type": "string",
                    "description": "Notification title/subject",
                },
                "message": {
                    "type": "string",
                    "description": "Notification body text",
                },
                "level": {
                    "type": "string",
                    "enum": ["info", "warning", "error", "success"],
                    "description": "Notification severity level (default: info)",
                },
                "webhook_url": {
                    "type": "string",
                    "description": "Optional: external webhook URL to POST to (Slack, Discord, etc.)",
                },
                "webhook_payload": {
                    "type": "object",
                    "description": "Optional: custom JSON payload for webhook (overrides default format)",
                },
            },
            "required": ["title", "message"],
        }

    async def execute(
        self,
        title: str,
        message: str,
        level: str = "info",
        webhook_url: str | None = None,
        webhook_payload: dict[str, Any] | None = None,
        **kwargs: Any,
    ) -> str:
        results: list[dict[str, Any]] = []

        # Send to control plane
        if self._send_callback and self._default_channel and self._default_chat_id:
            try:
                level_emoji = {"info": "ℹ️", "warning": "⚠️", "error": "🚨", "success": "✅"}.get(level, "ℹ️")
                content = f"{level_emoji} **{title}**\n\n{message}"
                msg = OutboundMessage(
                    channel=self._default_channel,
                    chat_id=self._default_chat_id,
                    content=content,
                    media=[],
                    metadata={
                        "message_kind": "activity",
                        "action": "notification",
                        "notification_level": level,
                        "notification_title": title,
                    },
                )
                await self._send_callback(msg)
                results.append({"target": "control_plane", "ok": True})
            except Exception as exc:
                results.append({"target": "control_plane", "ok": False, "error": str(exc)})

        # Send to webhook
        if webhook_url:
            try:
                payload = webhook_payload or self._build_default_webhook_payload(title, message, level)
                async with httpx.AsyncClient(timeout=_WEBHOOK_TIMEOUT) as client:
                    resp = await client.post(webhook_url, json=payload)
                results.append({
                    "target": "webhook",
                    "ok": 200 <= resp.status_code < 400,
                    "status_code": resp.status_code,
                })
                logger.info("Webhook notification sent to {} -> {}", webhook_url, resp.status_code)
            except Exception as exc:
                results.append({"target": "webhook", "ok": False, "error": str(exc)})

        if not results:
            return json.dumps({"error": "No notification target configured (no control plane or webhook_url)"})

        all_ok = all(r.get("ok") for r in results)
        return json.dumps({"ok": all_ok, "results": results})

    def _build_default_webhook_payload(
        self, title: str, message: str, level: str,
    ) -> dict[str, Any]:
        """Build a Slack-compatible webhook payload."""
        return {
            "text": f"[{level.upper()}] {title}",
            "blocks": [
                {
                    "type": "header",
                    "text": {"type": "plain_text", "text": title},
                },
                {
                    "type": "section",
                    "text": {"type": "mrkdwn", "text": message},
                },
            ],
        }
