"""
tools/pushover_tool.py — Pushover push notifications.

Sends to exactly one hard-coded user key (defined in security.py).
Normal priority (0) and below: no confirmation required.
Emergency priority (2): always requires confirmation.
"""
from __future__ import annotations

import httpx

from ..database import credential_store
from .base import BaseTool, ToolResult

PUSHOVER_API_URL = "https://api.pushover.net/1/messages.json"


class PushoverTool(BaseTool):
    name = "pushover"
    description = (
        "Send a push notification to the owner's phone via Pushover. "
        "Use for alerts, reminders, and status updates. "
        "Priority: -2 (silent), -1 (quiet), 0 (normal), 1 (high), 2 (emergency — requires confirmation)."
    )
    input_schema = {
        "type": "object",
        "properties": {
            "title": {
                "type": "string",
                "description": "Notification title (short, shown in bold)",
            },
            "message": {
                "type": "string",
                "description": "Notification body text",
            },
            "priority": {
                "type": "integer",
                "enum": [-2, -1, 0, 1, 2],
                "description": "Priority level (-2 silent to 2 emergency). Default: 0",
            },
            "url": {
                "type": "string",
                "description": "Optional URL to attach to the notification",
            },
            "url_title": {
                "type": "string",
                "description": "Display text for the attached URL",
            },
        },
        "required": ["title", "message"],
    }
    requires_confirmation = False   # overridden dynamically for priority=2
    allowed_in_scheduled_tasks = True

    async def execute(
        self,
        title: str,
        message: str,
        priority: int = 0,
        url: str = "",
        url_title: str = "",
        **kwargs,
    ) -> ToolResult:
        # Validate priority
        if priority not in (-2, -1, 0, 1, 2):
            return ToolResult(success=False, error=f"Invalid priority: {priority}")

        # Emergency always requires confirmation — enforced here as defence-in-depth
        # (the agent loop also checks requires_confirmation before calling execute)
        if priority == 2:
            # The agent loop should have asked for confirmation already.
            # If we got here, it was approved.
            pass

        # Load credentials — per-user key first, then system fallback
        try:
            app_token = await credential_store.require("pushover_app_token")
        except RuntimeError as e:
            return ToolResult(success=False, error=str(e))

        user_key: str | None = None
        try:
            from ..context_vars import current_user as _cu
            u = _cu.get()
            if u:
                from ..database import user_settings_store as _us
                user_key = await _us.get(u.id, "pushover_user_key")
        except Exception:
            pass
        if not user_key:
            user_key = await credential_store.get("pushover_user_key")
        if not user_key:
            return ToolResult(success=False, error="Pushover user key not configured. Set it in Settings → Pushover.")

        payload: dict = {
            "token": app_token,
            "user": user_key,
            "title": title[:250],
            "message": message[:1024],
            "priority": priority,
        }

        if priority == 2:
            # Emergency: retry every 30s for 1 hour until acknowledged
            payload["retry"] = 30
            payload["expire"] = 3600

        if url:
            payload["url"] = url[:512]
        if url_title:
            payload["url_title"] = url_title[:100]

        try:
            async with httpx.AsyncClient(timeout=10) as client:
                resp = await client.post(PUSHOVER_API_URL, data=payload)
                resp.raise_for_status()
                data = resp.json()

            if data.get("status") != 1:
                return ToolResult(
                    success=False,
                    error=f"Pushover API error: {data.get('errors', 'unknown')}",
                )

            return ToolResult(
                success=True,
                data={"sent": True, "request_id": data.get("request", "")},
            )

        except httpx.HTTPStatusError as e:
            return ToolResult(success=False, error=f"Pushover HTTP error: {e.response.status_code}")
        except Exception as e:
            return ToolResult(success=False, error=f"Pushover error: {e}")

    def confirmation_description(self, title: str = "", message: str = "", priority: int = 0, **kwargs) -> str:
        return f"Send emergency Pushover notification: '{title}' — {message[:100]}"

    def get_schema(self) -> dict:
        """Override to make requires_confirmation dynamic for priority 2."""
        schema = super().get_schema()
        # The tool itself handles emergency confirmation — marked as requiring it always
        # so the agent loop treats it consistently. For non-emergency, the agent loop
        # still calls execute(), which works fine without confirmation.
        return schema
