"""Graylog system tools — auth, connectivity, system info."""

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.graylog_client.client import (
    get_graylog_credentials,
    store_graylog_credentials,
)
from mcp_eregistrations_graylog.server import mcp


@mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
async def graylog_connection_status(
    instance: str | None = None,
) -> dict[str, Any]:
    """Test Graylog connectivity and show version.

    Args:
        instance: Instance name.

    Returns:
        dict with connected, version, error.
    """
    try:
        async with GraylogClient.for_instance(instance) as client:
            info = await client.get("/api/system")
            return {
                "connected": True,
                "version": info.get("version"),
                "cluster_id": info.get("cluster_id"),
                "instance": instance,
            }
    except GraylogClientError as e:
        return {
            "connected": False,
            "error": str(e),
            "instance": instance,
        }
    except ToolError:
        raise
    except Exception as e:
        return {
            "connected": False,
            "error": str(e),
            "instance": instance,
        }


@mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
async def graylog_system_info(
    instance: str | None = None,
) -> dict[str, Any]:
    """Get Graylog system info (version, status, cluster). Requires auth.

    Args:
        instance: Instance name.

    Returns:
        dict with version, hostname, lifecycle, lb_status, cluster_id, timezone.
    """
    try:
        async with GraylogClient.for_instance(instance) as client:
            result: dict[str, Any] = await client.get("/api/system")
            return result
    except GraylogClientError as e:
        raise translate_error(e, resource_type="system") from e


@mcp.tool()
async def graylog_auth_login(
    username: str | None = None,
    password: str | None = None,
    instance: str | None = None,
) -> dict[str, Any]:
    """Authenticate with Graylog (Basic Auth, NOT Keycloak).

    Validates credentials by calling GET /api/system, then persists
    them for future tool calls. Use an API token as username with
    literal "token" as password, or regular admin credentials.

    Args:
        username: Graylog username or API token.
        password: Graylog password or literal "token".
        instance: Instance name.

    Returns:
        dict with success, instance, graylog_version.
    """
    from mcp_eregistrations_common.config import get_instance_config

    config = get_instance_config(instance)
    graylog_url = config.get("graylog_url")
    if not graylog_url:
        raise ToolError(
            f"No graylog_url configured for instance '{instance}'. "
            f"Use instance_add to register an instance with a graylog_url."
        )

    # At this point instance is resolved (get_instance_config raises if None)
    assert instance is not None

    # Try stored credentials if none provided
    if not username or not password:
        stored = get_graylog_credentials(instance)
        if stored:
            username, password = stored

    if not username or not password:
        return {
            "action_required": "ask_credentials",
            "message": (
                f"No Graylog credentials for '{instance}'. "
                "Provide username and password. "
                "For token auth: use the API token as username, 'token' as password."
            ),
            "instance": instance,
        }

    # Validate by hitting /api/system
    try:
        async with GraylogClient(
            base_url=graylog_url,
            username=username,
            password=password,
            verify_ssl=config.get("verify_ssl", True),
        ) as client:
            info = await client.get("/api/system")
    except GraylogClientError as e:
        raise ToolError(
            f"Authentication failed for Graylog on '{instance}': {e}"
        ) from e

    # Store in-process
    store_graylog_credentials(instance, username, password)

    # Persist to auth_store for future sessions
    try:
        from mcp_eregistrations_common.auth_store import _set_instance

        _set_instance(
            instance,
            {"graylog_username": username, "graylog_password": password},
        )
    except Exception:
        pass  # Non-fatal: in-process store still works

    return {
        "success": True,
        "message": f"Authenticated with Graylog on '{instance}'.",
        "instance": instance,
        "graylog_version": info.get("version"),
    }
