"""GDB system tools — status, tag listing, instance listing, and authentication."""

from __future__ import annotations

from typing import Any

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

from mcp_eregistrations_gdb.gdb_client import GDBClient, GDBClientError, translate_error
from mcp_eregistrations_gdb.server import mcp


@mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
async def gdb_status(instance: str | None = None) -> dict[str, Any]:
    """Get GDB server health and version.

    Args:
        instance: Instance name (default: auto-select).

    Returns:
        dict with version, status.
    """
    try:
        async with GDBClient.for_instance(instance) as client:
            result: dict[str, Any] = await client.get("/api/v1/status")
            return result
    except GDBClientError as e:
        raise translate_error(e, resource_type="status") from e


@mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
async def gdb_tag_list(instance: str | None = None) -> dict[str, Any]:
    """List all GDB tags.

    Args:
        instance: Instance name (default: auto-select).

    Returns:
        dict with count, tags.
    """
    try:
        async with GDBClient.for_instance(instance) as client:
            data = await client.get("/api/v1/tags")
            raw = data if isinstance(data, list) else data.get("results", [])
            tags = [
                {
                    "id": t.get("id"),
                    "name": t.get("name"),
                }
                for t in raw
            ]
            return {"count": len(tags), "tags": tags}
    except GDBClientError as e:
        raise translate_error(e, resource_type="tag") from e


@mcp.tool()
async def gdb_auth_login(
    username: str | None = None,
    password: str | None = None,
    instance: str | None = None,
) -> dict[str, Any]:
    """Authenticate with eRegistrations. Shared across BPA/GDB/DS.

    Tries silent auto-login from stored credentials/tokens first.
    Only asks for credentials when no stored auth is available.

    Args:
        username: Username (email). Required on first login.
        password: Password. Required on first login.
        instance: Instance name (default: auto-select).

    Returns:
        dict with success, user_email, session_expires_in_minutes.
    """
    from mcp_eregistrations_common.auth import (
        get_or_refresh_token,
        keycloak_password_grant,
    )
    from mcp_eregistrations_common.auth_store import (
        get_credentials,
        store_credentials,
        store_refresh_context,
    )
    from mcp_eregistrations_common.config import (
        get_instance_config,
        resolve_auth_key,
    )

    inst = resolve_auth_key(instance)

    # 1. Try silent auto-login (stored tokens/credentials from BPA login)
    if not username:
        token = await get_or_refresh_token(inst)
        if token:
            creds = get_credentials(inst)
            return {
                "success": True,
                "message": f"Authenticated as {creds[0] if creds else 'stored user'}.",
                "user_email": creds[0] if creds else "stored user",
                "instance": inst,
            }

    # 2. Try provided credentials, fall back to stored
    if not username or not password:
        creds = get_credentials(inst)
        if creds:
            username, password = creds
    if not username or not password:
        return {
            "action_required": "ask_credentials",
            "message": (
                f"No stored credentials for '{inst}'. "
                "Provide username and password, or login via BPA MCP first."
            ),
            "instance": inst,
        }

    # 3. Keycloak password grant
    config = get_instance_config(inst)
    keycloak_url = config.get("keycloak_url")
    if not keycloak_url:
        raise ToolError(
            f"No keycloak_url for '{inst}'. "
            "For CAS instances, login via BPA MCP first — GDB will auto-authenticate."
        )

    try:
        result = await keycloak_password_grant(
            keycloak_url=keycloak_url,
            realm=config["keycloak_realm"],
            client_id=config.get("keycloak_client_id", "mcp-eregistrations-bpa"),
            username=username,
            password=password,
        )
    except Exception as e:
        raise ToolError(f"Authentication failed for '{inst}': {e}") from e

    store_credentials(
        inst,
        username,
        password,
        keycloak_url=keycloak_url,
        keycloak_realm=config["keycloak_realm"],
        client_id=config.get("keycloak_client_id", "mcp-eregistrations-bpa"),
    )
    store_refresh_context(
        inst,
        refresh_token=result.get("refresh_token", ""),
        token_endpoint=result["token_endpoint"],
        client_id=config.get("keycloak_client_id", "mcp-eregistrations-bpa"),
    )

    return {
        "success": True,
        "message": f"Authenticated as {username}.",
        "user_email": username,
        "instance": inst,
    }
