"""Workflow/process monitoring tools (Camunda integration)."""

from __future__ import annotations

from typing import Any

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

from mcp_eregistrations_ds.ds_client import (
    DSClient,
    DSClientError,
    DSNotFoundError,
    translate_error,
)
from mcp_eregistrations_ds.server import mcp


@mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
async def process_list(
    service_id: str,
    role: str,
    status: str | None = None,
    institution: str | None = None,
    size: int = 20,
    offset: int = 0,
    instance: str | None = None,
) -> dict[str, Any]:
    """List processes for a service and role.

    Args:
        service_id: Service ID.
        role: Role name (e.g., "officer", "reviewer").
        status: Filter by status.
        institution: Filter by institution.
        size: Page size (default: 20).
        offset: Start index (default: 0).
        instance: Instance profile name.

    Returns:
        dict with processes, count, role_counts, service_id, role.
    """
    params: dict[str, Any] = {"size": size, "skip": offset}
    if status:
        params["status"] = status
    if institution:
        params["institution"] = institution

    try:
        async with DSClient.for_instance(instance) as client:
            data: dict[str, Any] = await client.get(
                f"/backend/process/inprocess/{service_id}/{role}",
                params=params,
            )
    except DSClientError as e:
        raise translate_error(e, resource_type="process") from e

    return {
        "processes": data.get("list", []),
        "count": data.get("count", 0),
        "role_counts": data.get("roleCounts", {}),
        "service_id": service_id,
        "role": role,
    }


@mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
async def process_get(
    process_id: str,
    instance: str | None = None,
) -> dict[str, Any]:
    """Get single process detail with tasks and state.

    Args:
        process_id: Camunda process instance ID.
        instance: Instance profile name.

    Returns:
        dict with process_instance_id, ended, tasks and other fields.
    """
    try:
        async with DSClient.for_instance(instance) as client:
            try:
                data: dict[str, Any] = await client.get(
                    f"/backend/process/{process_id}"
                )
            except DSNotFoundError:
                raise ToolError(
                    f"Process '{process_id}' not found. "
                    "Use process_list to find active processes."
                )
    except DSClientError as e:
        raise translate_error(e, resource_type="process", resource_id=process_id) from e

    # Normalize camelCase keys from Camunda
    return {
        "process_instance_id": data.get("processInstanceId", process_id),
        "ended": data.get("ended", False),
        "tasks": data.get("tasks", []),
        "process_definition_id": data.get("processDefinitionId"),
        **{
            k: v
            for k, v in data.items()
            if k
            not in (
                "processInstanceId",
                "ended",
                "tasks",
                "processDefinitionId",
            )
        },
    }


@mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
async def process_task_variables(
    process_id: str,
    role: str,
    task_id: str,
    instance: str | None = None,
) -> dict[str, Any]:
    """Inspect task-level form variables for a role's task.

    Args:
        process_id: Camunda process instance ID.
        role: Role name.
        task_id: Camunda task ID.
        instance: Instance profile name.

    Returns:
        dict with process_id, role, task_id, variables.
    """
    try:
        async with DSClient.for_instance(instance) as client:
            try:
                data = await client.get(
                    f"/backend/process/{process_id}/role/{role}"
                    f"/camunda-variables/{task_id}"
                )
            except DSNotFoundError:
                raise ToolError(
                    f"Task '{task_id}' not found for process "
                    f"'{process_id}' and role '{role}'."
                )
    except DSClientError as e:
        raise translate_error(e, resource_type="task", resource_id=task_id) from e

    return {
        "process_id": process_id,
        "role": role,
        "task_id": task_id,
        "variables": data,
    }


@mcp.tool(annotations=ToolAnnotations(readOnlyHint=True))
async def process_history(
    process_id: str,
    instance: str | None = None,
) -> dict[str, Any]:
    """Get archived data for a completed process.

    Args:
        process_id: Camunda process instance ID.
        instance: Instance profile name.

    Returns:
        dict with process_id and archived variables/task history.
    """
    try:
        async with DSClient.for_instance(instance) as client:
            try:
                data: dict[str, Any] = await client.get(
                    f"/backend/process/{process_id}/historical-camunda-variables"
                )
            except DSNotFoundError:
                raise ToolError(
                    f"Process '{process_id}' not found in history. "
                    "Try process_get for active processes."
                )
    except DSClientError as e:
        raise translate_error(
            e, resource_type="process_history", resource_id=process_id
        ) from e

    return {"process_id": process_id, **data}
