"""Message and alert admin tools."""

from __future__ import annotations

from typing import Any

from fastmcp.exceptions import ToolError
from mcp.types import ToolAnnotations

from mcp_eregistrations_ds.ds_client import (
    DSClient,
    DSClientError,
    translate_error,
)
from mcp_eregistrations_ds.server import mcp


def _summarize_message(item: dict[str, Any]) -> dict[str, Any]:
    """Build a summary dict for a message list item."""
    return {
        "id": item.get("id"),
        "username": item.get("username"),
        "subject": item.get("subject"),
        "is_seen": item.get("is_seen"),
        "message_from": item.get("message_from"),
        "is_alert": item.get("is_alert"),
        "file_id": item.get("file_id"),
        "created_at": item.get("created_at"),
    }


@mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
async def message_list_admin(
    username: str | None = None,
    is_seen: bool | None = None,
    process_id: str | None = None,
    file_id: str | None = None,
    page: int = 1,
    instance: str | None = None,
) -> dict[str, Any]:
    """List user messages (admin). Use message_get for full content.

    Args:
        username: Filter by recipient username.
        is_seen: Filter by read status.
        process_id: Filter by process ID.
        file_id: Filter by file UUID.
        page: Page number (default: 1).
        instance: Instance profile name.

    Returns:
        dict with items (summary fields only), count, page, page_size, has_next.
    """
    params: dict[str, Any] = {"page": page}
    if username:
        params["user__username"] = username
    if is_seen is not None:
        params["is_seen"] = str(is_seen).lower()
    if process_id:
        params["process_id"] = process_id
    if file_id:
        params["file__file_id"] = file_id

    try:
        async with DSClient.for_instance(instance) as client:
            data = await client.get_paginated(
                "/backend/admin/user/messages", params=params
            )
    except DSClientError as e:
        raise translate_error(e, resource_type="message") from e

    data["items"] = [_summarize_message(item) for item in data.get("items", [])]
    return data


@mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
async def alert_list_admin(
    username: str | None = None,
    process_id: str | None = None,
    file_id: str | None = None,
    page: int = 1,
    instance: str | None = None,
) -> dict[str, Any]:
    """List user alerts (admin). Use alert_get for full content.

    Args:
        username: Filter by recipient username.
        process_id: Filter by process ID.
        file_id: Filter by file UUID.
        page: Page number (default: 1).
        instance: Instance profile name.

    Returns:
        dict with items (summary fields only), count, page, page_size, has_next.
    """
    params: dict[str, Any] = {"page": page}
    if username:
        params["user__username"] = username
    if process_id:
        params["process_id"] = process_id
    if file_id:
        params["file__file_id"] = file_id

    try:
        async with DSClient.for_instance(instance) as client:
            data = await client.get_paginated(
                "/backend/admin/user/alerts", params=params
            )
    except DSClientError as e:
        raise translate_error(e, resource_type="alert") from e

    data["items"] = [_summarize_message(item) for item in data.get("items", [])]
    return data


@mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
async def message_get(
    message_id: int,
    instance: str | None = None,
) -> dict[str, Any]:
    """Get a single message by ID.

    Args:
        message_id: Message ID.
        instance: Instance profile name.

    Returns:
        dict with id, subject, content, is_seen, message_from, created_at.
    """
    try:
        async with DSClient.for_instance(instance) as client:
            # Detail endpoint uses user__username lookup, not PK.
            # Fetch list and find by ID client-side.
            raw = await client.get("/backend/admin/user/messages")
            items: list[dict[str, Any]] = (
                raw if isinstance(raw, list) else raw.get("results", [])
            )
            found: dict[str, Any] | None = next(
                (m for m in items if m.get("id") == message_id), None
            )
            if found is None:
                raise ToolError(
                    f"Message {message_id} not found. "
                    "Use message_list_admin to find valid IDs."
                )
    except DSClientError as e:
        raise translate_error(e, resource_type="message", resource_id=message_id) from e

    return found


@mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
async def alert_get(
    alert_id: int,
    instance: str | None = None,
) -> dict[str, Any]:
    """Get a single alert by ID.

    Args:
        alert_id: Alert ID.
        instance: Instance profile name.

    Returns:
        dict with id, subject, content, is_alert, created_at.
    """
    try:
        async with DSClient.for_instance(instance) as client:
            # Detail endpoint uses user__username lookup, not PK.
            # Fetch list and find by ID client-side.
            raw = await client.get("/backend/admin/user/alerts")
            items: list[dict[str, Any]] = (
                raw if isinstance(raw, list) else raw.get("results", [])
            )
            found: dict[str, Any] | None = next(
                (m for m in items if m.get("id") == alert_id), None
            )
            if found is None:
                raise ToolError(
                    f"Alert {alert_id} not found. "
                    "Use alert_list_admin to find valid IDs."
                )
    except DSClientError as e:
        raise translate_error(e, resource_type="alert", resource_id=alert_id) from e

    return found
