import json

from api.services.router_adapter import normalize_openai_schema, sanitize_content
from api.services.tool_executor import ToolExecutor


def test_tool_args_recovery_trailing_commas(tmp_path):
    te = ToolExecutor(workspace_root=str(tmp_path))
    out = normalize_openai_schema(
        raw={
            "tool_calls": [
                {
                    "id": "call_1",
                    "type": "function",
                    "function": {"name": "Write", "arguments": '{"path":"a.txt","content":"hi",}'},
                }
            ]
        },
        tools_enabled=True,
        tool_executor=te,
        request_id="req1",
    )
    assert out.get("tool_results")
    assert (tmp_path / "a.txt").read_text(encoding="utf-8") == "hi"


def test_tool_args_recovery_code_fence_json(tmp_path):
    te = ToolExecutor(workspace_root=str(tmp_path))
    args = "```json\n" + json.dumps({"path": "b.txt", "content": "ok"}) + "\n```"
    out = normalize_openai_schema(
        raw={
            "tool_calls": [
                {"id": "call_2", "type": "function", "function": {"name": "Write", "arguments": args}}
            ]
        },
        tools_enabled=True,
        tool_executor=te,
        request_id="req2",
    )
    assert out.get("tool_results")
    assert (tmp_path / "b.txt").read_text(encoding="utf-8") == "ok"


def test_tool_args_recovery_python_dict_literal_single_quotes(tmp_path):
    te = ToolExecutor(workspace_root=str(tmp_path))
    args = "{'path': 'c.txt', 'content': 'yo'}"
    out = normalize_openai_schema(
        raw={
            "tool_calls": [
                {"id": "call_3", "type": "function", "function": {"name": "Write", "arguments": args}}
            ]
        },
        tools_enabled=True,
        tool_executor=te,
        request_id="req3",
    )
    assert out.get("tool_results")
    # Tool results should be JSON-serializable for downstream provider reinjection
    json.loads(out["tool_results"][0]["content"])
    assert (tmp_path / "c.txt").read_text(encoding="utf-8") == "yo"


def test_sanitize_content_does_not_drop_normal_planning_language():
    text = "I need to inspect this module first.\nThen I will explain the result."
    out = sanitize_content(text)
    assert "I need to inspect this module first." in out
    assert "Then I will explain the result." in out


def test_normalize_openai_schema_recovers_when_sanitizer_would_empty_content():
    raw = {
        "content": "[assistant tool_calls]\n{\"tool_calls\":[]}\n<tool_call>Read</tool_call>\nUseful answer."
    }
    out = normalize_openai_schema(raw=raw, tools_enabled=False, model_name="test")
    assert isinstance(out.get("content"), str)
    assert out["content"] != "."
    assert "Useful answer." in out["content"]

