"""MCP tool for running a saved API flow."""

import json

from mcp.types import TextContent, Tool

from maeris_mcp.auth.token_store import TokenStore
from maeris_mcp.maeris.client import MaerisClient


def run_flow_tool() -> Tool:
    return Tool(
        name="run_flow",
        description=(
            "Execute one saved API flow by name and return the full backend response. "
            "Environment may be passed by name."
        ),
        inputSchema={
            "type": "object",
            "properties": {
                "flow_name": {"type": "string", "description": "Name of the flow to execute."},
                "environment_name": {"type": "string", "description": "Optional environment name to resolve to ID."},
            },
            "required": ["flow_name"],
        },
    )


def _flow_id(flow: dict) -> str:
    for key in ["flow_id", "api_flow_id", "id", "_id"]:
        value = flow.get(key)
        if value:
            return str(value)
    return ""


def _flow_name(flow: dict) -> str:
    for key in ["name", "flow_name"]:
        value = flow.get(key)
        if isinstance(value, str) and value.strip():
            return value
    return ""


def _environment_id(env: dict) -> str:
    for key in ["environment_id", "api_environment_id", "id", "env_id"]:
        value = env.get(key)
        if value:
            return str(value)
    return ""


def _environment_name(env: dict) -> str:
    for key in ["name", "environment_name"]:
        value = env.get(key)
        if isinstance(value, str) and value.strip():
            return value
    return ""


async def _resolve_flow(
    client: MaerisClient, flow_name: str
) -> tuple[str | None, str | None, str | None]:
    flows = await client.get_api_flows()

    exact = [f for f in flows if _flow_name(f).lower() == flow_name.lower()]
    if len(exact) == 1:
        matched = exact[0]
        return _flow_id(matched), _flow_name(matched), None
    if len(exact) > 1:
        choices = [{"id": _flow_id(f), "name": _flow_name(f)} for f in exact]
        return None, None, f"Error: multiple flows matched '{flow_name}'. Matches: {json.dumps(choices)}"

    partial = [f for f in flows if flow_name.lower() in _flow_name(f).lower()]
    if len(partial) == 1:
        matched = partial[0]
        return _flow_id(matched), _flow_name(matched), None
    if len(partial) > 1:
        choices = [{"id": _flow_id(f), "name": _flow_name(f)} for f in partial]
        return None, None, f"Error: multiple flows matched '{flow_name}'. Matches: {json.dumps(choices)}"

    return None, None, f"Error: no flow matched '{flow_name}'"


async def _resolve_env(
    client: MaerisClient, environment_name: str | None
) -> tuple[str | None, str | None, str | None]:
    if environment_name:
        environments = await client.get_environments()
        exact = [e for e in environments if _environment_name(e).lower() == environment_name.lower()]
        if len(exact) == 1:
            matched = exact[0]
            return _environment_id(matched), _environment_name(matched), None
        if len(exact) > 1:
            choices = [{"id": _environment_id(e), "name": _environment_name(e)} for e in exact]
            return None, None, f"Error: multiple environments matched '{environment_name}'. Matches: {json.dumps(choices)}"

        partial = [e for e in environments if environment_name.lower() in _environment_name(e).lower()]
        if len(partial) == 1:
            matched = partial[0]
            return _environment_id(matched), _environment_name(matched), None
        if len(partial) > 1:
            choices = [{"id": _environment_id(e), "name": _environment_name(e)} for e in partial]
            return None, None, f"Error: multiple environments matched '{environment_name}'. Matches: {json.dumps(choices)}"

        return None, None, f"Error: no environment matched '{environment_name}'"

    store = TokenStore()
    selected_env_id = store.get_environment_id()
    selected_env_name = store.get_environment_name()
    if selected_env_id:
        return str(selected_env_id), selected_env_name, None

    return (
        None,
        None,
        "Error: no environment specified and no selected environment found. Provide environment_name or select one first.",
    )


async def handle_run_flow(arguments: dict) -> list[TextContent]:
    flow_name = arguments.get("flow_name")
    environment_name = arguments.get("environment_name")

    if not flow_name:
        return [TextContent(type="text", text="Error: flow_name is required")]

    async with MaerisClient() as client:
        flow_id, _resolved_flow_name, flow_err = await _resolve_flow(client, str(flow_name))
        if flow_err:
            return [TextContent(type="text", text=flow_err)]

        env_id, resolved_env_name, env_err = await _resolve_env(
            client, str(environment_name) if environment_name else None
        )
        if env_err:
            return [TextContent(type="text", text=env_err)]

        response = await client.run_flow(flow_id=flow_id or "", env_id=env_id or "")

    result = {
        "flowName": flow_name,
        "flowId": flow_id,
        "environmentName": resolved_env_name,
        "envId": env_id,
        "response": response,
    }

    return [TextContent(type="text", text=json.dumps(result, indent=2))]
