"""Native OpenAI Agents SDK tools backed by the shared REST contract."""

import asyncio
import json
import sys
from pathlib import Path
from agents import FunctionTool
from pydantic import ValidationError

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
TrueFetchError = core.ToolException


class Toolset:
    """One host-owned intent per instance. Never serialize this object as model input."""

    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("max_tool_calls must be between 1 and 64")
        self._rest = core.make_tools(api_key, api_url=API, **options)
        self.calls, self.task_ids, self._closed = 0, [], False
        self.tools = [self._adapt(rest, max_tool_calls) for rest in self._rest]

    def close(self):
        self._closed = True

    def _adapt(self, rest, limit):
        async def invoke(context, arguments):
            if self._closed or self.calls >= limit:
                raise TrueFetchError("Application tool-call limit reached or run closed")
            self.calls += 1
            try:
                # Validate before starting HTTP; never reflect private arguments in errors.
                parsed = rest.args_schema.model_validate_json(arguments)
                values = {name: getattr(parsed, name) for name in type(parsed).model_fields}
            except (ValidationError, ValueError, TypeError):
                raise TrueFetchError("Invalid TrueFetch tool arguments") from None

            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 json.dumps(result, allow_nan=False)

            return await asyncio.to_thread(execute)

        return FunctionTool(
            name=rest.name,
            description=rest.description,
            params_json_schema=rest.args_schema.model_json_schema(),
            on_invoke_tool=invoke,
            strict_json_schema=True,
        )

    async def recover(self, task_id, **options):
        """Host-only deterministic export; no model or collection call."""
        return await asyncio.to_thread(core.recover_results, self._rest, task_id, **options)
