"""Kimi-family endpoints don't need thinking blocks stripped on replay; DeepSeek does."""

from types import SimpleNamespace

from agent.transports import get_transport
from agent.anthropic_message_convert import convert_messages_to_anthropic

SIG = "sig-k3"

KIMI = "https://api.kimi.com/coding"
MOONSHOT = "https://api.moonshot.cn/anthropic"
DEEPSEEK = "https://api.deepseek.com/anthropic"


def _thinking_on_replay(base_url, signature=SIG, model="k3"):
    """Normalize a thinking+text turn, store it, convert to the next-turn request,
    and return its thinking blocks."""
    response = SimpleNamespace(
        content=[
            SimpleNamespace(type="thinking", thinking="five: 5 11 27 63 88", signature=signature),
            SimpleNamespace(type="text", text="5 27 88"),
        ],
        stop_reason="end_turn",
        usage=None,
    )
    normalized = get_transport("anthropic_messages").normalize_response(response)
    stored = {
        "role": "assistant",
        "content": normalized.content or "",
        "reasoning_details": (normalized.provider_data or {}).get("reasoning_details"),
    }
    messages = [
        {"role": "user", "content": "q1"},
        stored,
        {"role": "user", "content": "q2"},
    ]
    _sys, out = convert_messages_to_anthropic(messages, base_url=base_url, model=model)
    assistant = [m for m in out if m.get("role") == "assistant"][0]
    return [b for b in assistant["content"] if isinstance(b, dict) and b.get("type") == "thinking"]






def test_moonshot_keeps_signed_thinking():
    thinking = _thinking_on_replay(MOONSHOT)
    assert thinking and thinking[0].get("signature") == SIG




def test_kimi_model_name_on_foreign_gateway_keeps_thinking():
    """A Kimi-family model slug replayed through a non-Kimi gateway hostname
    keeps its thinking blocks — upstream Kimi still enforces its replay
    semantics no matter what host fronts it (hermes-agent#13848, #17057).
    Covers both the named and bare Coding Plan slugs."""
    for model in ("kimi-k2.5", "k3"):
        assert _thinking_on_replay(DEEPSEEK, model=model), model




def test_orphan_tool_turn_demotes_and_leaks_no_internal_marker():
    """Signed thinking + parallel tool batch interrupted mid-flight (one orphan):
    the internal _thinking_signature_invalidated marker must be popped —
    never leak into the Kimi payload — while the thinking block itself
    replays as-is (Kimi does not enforce signatures)."""
    response = SimpleNamespace(
        content=[
            SimpleNamespace(type="thinking", thinking="plan both reads", signature=SIG),
            SimpleNamespace(type="tool_use", id="toolu_1", name="read_file", input={"path": "a.py"}),
            SimpleNamespace(type="tool_use", id="toolu_2", name="read_file", input={"path": "b.py"}),
        ],
        stop_reason="tool_use",
        usage=None,
    )
    normalized = get_transport("anthropic_messages").normalize_response(response)
    provider_data = normalized.provider_data or {}
    stored = {
        "role": "assistant",
        "content": normalized.content or "",
        "reasoning_details": provider_data.get("reasoning_details"),
        "tool_calls": [
            {"id": tc.id, "type": "function", "function": {"name": tc.name, "arguments": tc.arguments}}
            for tc in (normalized.tool_calls or [])
        ],
    }
    if provider_data.get("anthropic_content_blocks"):
        stored["anthropic_content_blocks"] = provider_data["anthropic_content_blocks"]
    messages = [
        {"role": "user", "content": "inspect both"},
        stored,
        {"role": "tool", "tool_call_id": "toolu_1", "content": "a.py: ok"},
        # toolu_2 interrupted: no tool result follows (orphan)
        {"role": "user", "content": "continue"},
    ]
    _sys, out = convert_messages_to_anthropic(messages, base_url=KIMI, model="k3")
    assistant = [m for m in out if m.get("role") == "assistant"][0]
    assert "_thinking_signature_invalidated" not in assistant, (
        f"internal marker leaked into Kimi payload: {assistant.keys()}"
    )
    types = [b.get("type") for b in assistant["content"] if isinstance(b, dict)]
    assert "thinking" in types, (
        "Kimi does not enforce signatures — even orphan-invalidated blocks "
        f"must replay as-is: {types}"
    )
