"""GDB translation tools — config, list, modify, add/delete language, publish."""

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
from mcp_eregistrations_gdb.tools import _add_optional


@mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
async def gdb_translation_config(instance: str | None = None) -> dict[str, Any]:
    """Get translation service configuration.

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

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


@mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
async def gdb_translation_list(instance: str | None = None) -> dict[str, Any]:
    """List all translations (languages and messages).

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

    Returns:
        dict with languages (list of code, name), message_count.
    """
    try:
        async with GDBClient.for_instance(instance) as client:
            result: dict[str, Any] = await client.get("/api/v1/translations")
    except GDBClientError as e:
        raise translate_error(e, resource_type="translation") from e

    raw_languages = result.get("languages", {})
    messages = result.get("messages", {})
    # Languages may be a dict keyed by code or a list of objects
    if isinstance(raw_languages, dict):
        languages = [
            {"code": code, "name": info.get("name") if isinstance(info, dict) else info}
            for code, info in raw_languages.items()
        ]
    else:
        languages = [
            {"code": lang.get("code"), "name": lang.get("name")}
            for lang in raw_languages
        ]
    return {
        "languages": languages,
        "message_count": len(messages) if isinstance(messages, dict) else 0,
    }


@mcp.tool(annotations=ToolAnnotations(readOnlyHint=False))
async def gdb_translation_modify(
    language_code: str,
    key: str,
    value: str,
    database_catalog_id: int | None = None,
    database_catalog_group_id: int | None = None,
    data_view_catalog_id: int | None = None,
    catalog_field_id: int | None = None,
    instance: str | None = None,
) -> dict[str, Any]:
    """Modify a translation entry. Audited write operation.

    Args:
        language_code: Language code (e.g., "es", "fr").
        key: Translation key.
        value: Translation value.
        database_catalog_id: Scope to catalog (exclusive with other scope params).
        database_catalog_group_id: Scope to group (exclusive with other scope params).
        data_view_catalog_id: Scope to data view (exclusive with other scope params).
        catalog_field_id: Further scope to a field within a catalog.
        instance: Instance name (default: auto-select).

    Returns:
        dict with result.
    """
    # Validate mutual exclusivity of scope params
    scope_params = [
        database_catalog_id,
        database_catalog_group_id,
        data_view_catalog_id,
    ]
    if sum(p is not None for p in scope_params) > 1:
        raise ToolError(
            "Only one scope parameter allowed: database_catalog_id, "
            "database_catalog_group_id, or data_view_catalog_id"
        )

    try:
        async with GDBClient.for_instance(instance) as client:
            body: dict[str, Any] = {"key": key, "value": value}
            _add_optional(body, "databaseCatalogId", database_catalog_id)
            _add_optional(body, "databaseCatalogGroupId", database_catalog_group_id)
            _add_optional(body, "dataViewCatalogId", data_view_catalog_id)
            _add_optional(body, "catalogFieldId", catalog_field_id)
            result: dict[str, Any] = await client.post(
                f"/api/v1/translation/{language_code}/modify",
                data=body,
            )
            return result
    except GDBClientError as e:
        raise translate_error(e, resource_type="translation") from e


@mcp.tool(annotations=ToolAnnotations(readOnlyHint=False))
async def gdb_translation_add_language(
    language_code: str,
    instance: str | None = None,
) -> dict[str, Any]:
    """Add a new language for translations. Audited write operation.

    Args:
        language_code: Language code to add (e.g., "fr", "de").
        instance: Instance name (default: auto-select).

    Returns:
        dict with added language details.
    """
    try:
        async with GDBClient.for_instance(instance) as client:
            result: dict[str, Any] = await client.post(
                f"/api/v1/translation/{language_code}/add-language",
                data={},
            )
            return result
    except GDBClientError as e:
        raise translate_error(e, resource_type="translation") from e


@mcp.tool(annotations=ToolAnnotations(readOnlyHint=False))
async def gdb_translation_publish(
    language_code: str,
    instance: str | None = None,
) -> dict[str, Any]:
    """Publish translations for a single language. Audited write operation.

    Args:
        language_code: Language code to publish (e.g., "es").
        instance: Instance name (default: auto-select).

    Returns:
        dict with publish result.
    """
    try:
        async with GDBClient.for_instance(instance) as client:
            result: dict[str, Any] = await client.post(
                f"/api/v1/translation/{language_code}/publish",
                data={},
            )
            return result
    except GDBClientError as e:
        raise translate_error(e, resource_type="translation") from e


@mcp.tool(annotations=ToolAnnotations(readOnlyHint=False))
async def gdb_translation_publish_all(
    instance: str | None = None,
) -> dict[str, Any]:
    """Publish translations for all languages. Audited write operation.

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

    Returns:
        dict with publish result.
    """
    try:
        async with GDBClient.for_instance(instance) as client:
            result: dict[str, Any] = await client.post(
                "/api/v1/translations/publish",
                data={},
            )
            return result
    except GDBClientError as e:
        raise translate_error(e, resource_type="translation") from e


@mcp.tool(annotations=ToolAnnotations(readOnlyHint=False))
async def gdb_translation_delete(
    language_code: str,
    instance: str | None = None,
) -> dict[str, Any]:
    """Delete a language from translations. Audited write operation.

    Args:
        language_code: Language code to delete.
        instance: Instance name (default: auto-select).

    Returns:
        dict with deleted (bool), language_code.
    """
    try:
        async with GDBClient.for_instance(instance) as client:
            await client.delete(f"/api/v1/translation/{language_code}")
            return {"deleted": True, "language_code": language_code}
    except GDBClientError as e:
        raise translate_error(e, resource_type="translation") from e
