"""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")
            if isinstance(data, list):
                return {"count": len(data), "tags": data}
            return {
                "count": data.get("count", 0),
                "tags": data.get("results", []),
            }
    except GDBClientError as e:
        raise translate_error(e, resource_type="tag") from e


@mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
async def gdb_instance_list() -> dict[str, Any]:
    """List eRegistrations instances with GDB URLs configured.

    Returns:
        dict with count, instances (name, display_name, gdb_url).
    """
    from mcp_eregistrations_common.config import load_builtin_instances

    instances = load_builtin_instances()
    gdb_instances = []
    for inst in instances:
        gdb_url = inst.get("gdb_url")
        if gdb_url:
            gdb_instances.append(
                {
                    "name": inst["name"],
                    "display_name": inst.get("display_name", inst["name"]),
                    "gdb_url": gdb_url,
                }
            )
    return {"count": len(gdb_instances), "instances": gdb_instances}


@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.

    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 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)
    config = get_instance_config(inst)

    # 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."
            ),
            "instance": inst,
        }

    try:
        result = await keycloak_password_grant(
            keycloak_url=config["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=config["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,
    }
