"""Graylog search tools — log search with Elasticsearch syntax."""

from __future__ import annotations

from typing import Any

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

from mcp_eregistrations_graylog.graylog_client import (
    GraylogClient,
    GraylogClientError,
    translate_error,
)
from mcp_eregistrations_graylog.server import mcp

# Bind parse_time_range directly to avoid mock interference in tests
_parse_time_range = GraylogClient.parse_time_range


@mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
async def graylog_search_logs(
    query: str,
    time_range: str = "1h",
    fields: str | None = None,
    stream_id: str | None = None,
    limit: int = 50,
    offset: int = 0,
    sort: str | None = None,
    instance: str | None = None,
) -> dict[str, Any]:
    """Search logs with Elasticsearch syntax. Requires auth.

    Common queries:
    - level:3 — error logs (syslog: 3=error, 4=warning, 6=info)
    - app_name:Mule AND serviceId:"<id>" — bot execution logs
    - app_name:Mule AND actionName:"<name>" — specific bot action
    - app_name:GDB — GDB backend logs

    Key fields: message, level, app_name, serviceName, serviceId,
    actionId, actionName, user, inputData, outputData.

    Args:
        query: Elasticsearch query (e.g. 'level:3', 'app_name:Mule').
        time_range: Relative time range (default: '1h'). Examples: 30m, 1h, 24h, 7d.
        fields: Comma-separated fields to return (e.g. 'message,level,app_name').
        stream_id: Filter to a specific stream ID.
        limit: Max results (default: 50, max: 1000).
        offset: Pagination offset (default: 0).
        sort: Sort field:direction (e.g. 'timestamp:asc'). Default: timestamp:desc.
        instance: Instance name.

    Returns:
        dict with total_results, query, messages (flattened).
    """
    # Parse time range early to catch invalid formats
    try:
        range_seconds = _parse_time_range(time_range)
    except ValueError as e:
        raise ToolError(str(e)) from e

    params: dict[str, Any] = {
        "query": query,
        "range": range_seconds,
        "limit": min(limit, 1000),
        "offset": offset,
    }
    if fields:
        params["fields"] = fields
    if stream_id:
        params["filter"] = f"streams:{stream_id}"
    if sort:
        params["sort"] = sort

    try:
        async with GraylogClient.for_instance(instance) as client:
            raw = await client.get("/api/search/universal/relative", params=params)
    except GraylogClientError as e:
        raise translate_error(e, resource_type="logs") from e

    # Flatten messages: extract .message dict from each wrapper
    messages = []
    for entry in raw.get("messages", []):
        msg = entry.get("message", entry)
        messages.append(msg)

    return {
        "total_results": raw.get("total_results", 0),
        "query": raw.get("query", query),
        "time_range": time_range,
        "messages": messages,
    }
