"""In-process Claude SDK MCP tools; credentials and intent remain host-owned."""

import asyncio
import json
import sys
from pathlib import Path
from pydantic import ValidationError
from claude_agent_sdk import tool, create_sdk_mcp_server

try:
    import truefetch_rest as core
except ModuleNotFoundError as error:
    if error.name != "truefetch_rest":
        raise
    sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "python"))
    import truefetch_rest as core

API = core.API


class Toolset:
    def __init__(self, api_key, *, max_tool_calls=16, **options):
        if type(max_tool_calls) is not int or not 1 <= max_tool_calls <= 64:
            raise ValueError("Invalid tool-call bound")
        self._rest = core.make_tools(api_key, api_url=API, **options)
        self.calls, self.task_ids, self.closed, self.failed = 0, [], False, False
        self.tools = [self._adapt(rest, max_tool_calls) for rest in self._rest]
        self.server = create_sdk_mcp_server("truefetch", version="0.1.0", tools=self.tools)
        self.allowed = ["mcp__truefetch__" + rest.name for rest in self._rest]

    def close(self):
        self.closed = True

    def _adapt(self, rest, limit):
        async def invoke(arguments):
            try:
                if self.closed or self.failed or self.calls >= limit:
                    raise core.ToolException("Toolset stopped or tool-call limit reached")
                self.calls += 1
                parsed = rest.args_schema.model_validate(arguments)
                values = {name: getattr(parsed, name) for name in type(parsed).model_fields}

                def execute():
                    result = rest.fn(**values)
                    task_id = core.observed_task_id(result)
                    if isinstance(task_id, str) and task_id not in self.task_ids:
                        self.task_ids.append(task_id)
                    return result

                result = await asyncio.to_thread(execute)
                return {"content": [{"type": "text", "text": json.dumps(result, allow_nan=False)}]}
            except (ValidationError, ValueError, TypeError):
                message = "Invalid TrueFetch tool arguments"
            except core.ToolException as error:
                message = str(error)
            except Exception:
                message = "TrueFetch tool failed. Preserve original request key/input and task ID."
            self.failed = True
            return {"is_error": True, "content": [{"type": "text", "text": message}]}

        return tool(rest.name, rest.description, rest.args_schema.model_json_schema())(invoke)

    async def recover(self, task_id, **options):
        return await asyncio.to_thread(core.recover_results, self._rest, task_id, **options)
