from __future__ import annotations

from pathlib import Path
from types import SimpleNamespace

import pytest

from beaver.engine.loader import EngineLoader
from beaver.engine.loop import AgentLoop
from beaver.engine.providers.base import LLMProvider, LLMResponse, ToolCallRequest
from beaver.engine.providers.factory import ProviderBundle
from beaver.skills.learning.replay import ReplayToolExecutor, ReplayToolPolicy


class ToolCallingProvider(LLMProvider):
    def __init__(self) -> None:
        super().__init__()
        self.calls = 0

    async def chat(
        self,
        messages: list[dict],
        tools: list[dict] | None = None,
        model: str | None = None,
        max_tokens: int | None = None,
        temperature: float = 0.7,
        thinking_enabled: bool | None = None,
    ) -> LLMResponse:
        self.calls += 1
        if self.calls == 1:
            return LLMResponse(
                content="",
                tool_calls=[
                    ToolCallRequest(
                        id="call-1",
                        name="read_file",
                        arguments={"path": "README.md"},
                    )
                ],
            )
        return LLMResponse(content="done")

    def get_default_model(self) -> str:
        return "stub"


@pytest.mark.asyncio
async def test_process_direct_uses_replay_tool_executor(tmp_path: Path) -> None:
    loop = AgentLoop(loader=EngineLoader(workspace=tmp_path))
    loaded = loop.boot()
    provider = ToolCallingProvider()
    runtime = SimpleNamespace(model="stub", provider_name="stub")
    replay_executor = ReplayToolExecutor(
        loaded.tool_executor,
        registry=loaded.tool_registry,
        policy=ReplayToolPolicy(),
    )

    result = await loop.process_direct(
        "Read the README.",
        provider_bundle=ProviderBundle(main_runtime=runtime, main_provider=provider),  # type: ignore[arg-type]
        include_skill_assembly=False,
        pinned_skill_names=[],
        tool_executor_override=replay_executor,
        max_tool_iterations=2,
        source="skill_replay_eval",
    )

    assert result.output_text == "done"
    assert replay_executor.traces
    assert replay_executor.traces[0]["tool_name"] == "read_file"
