"""structured output 의 tool-call 래퍼 벗기기 계약.

2026-08-06 실측: Anthropic 경로가 간헐적으로 `{"parameters": {…}}` 로 한 겹
감싸 돌려준다(같은 프롬프트 4회 중 1회, 223쌍 재판정에서 92건). 벗기지 않으면
로컬 스키마 검증이 root 에서 실패하고 call_structured 가 Tier 2 로 내려가는데,
Tier 2 는 **입력을 sanitize 한 다른 프롬프트**로 다시 묻는다 — 판정에 조용한
계약 변경이 들어간다.

벗기기는 보수적이어야 한다. 스키마가 그 키를 실제로 원하는 경우까지 벗기면
정상 응답을 망가뜨린다.
"""
from app.modules.llm.llm_client import _unwrap_tool_envelope

JUDGE_SCHEMA = {
    "type": "object",
    "properties": {"winner": {"type": "string"}, "ranking": {"type": "array"}},
    "required": ["winner", "ranking"],
}


def test_unwraps_parameters_envelope():
    inner = {"winner": "A", "ranking": ["A", "B"]}
    assert _unwrap_tool_envelope({"parameters": inner}, JUDGE_SCHEMA) is inner


def test_unwraps_arguments_and_input_envelopes():
    inner = {"winner": "A", "ranking": ["A"]}
    for key in ("arguments", "input"):
        assert _unwrap_tool_envelope({key: inner}, JUDGE_SCHEMA) is inner


def test_leaves_normal_payload_untouched():
    p = {"winner": "A", "ranking": ["A", "B"]}
    assert _unwrap_tool_envelope(p, JUDGE_SCHEMA) is p


def test_does_not_unwrap_when_schema_wants_that_key():
    """스키마가 `parameters` 를 property 로 선언하면 그것은 래퍼가 아니다."""
    schema = {
        "type": "object",
        "properties": {"parameters": {"type": "object"}},
        "required": ["parameters"],
    }
    p = {"parameters": {"a": 1}}
    assert _unwrap_tool_envelope(p, schema) is p


def test_does_not_unwrap_when_more_than_one_key():
    """키가 둘 이상이면 래퍼가 아니다 — 실제 페이로드일 수 있다."""
    p = {"parameters": {"a": 1}, "winner": "A"}
    assert _unwrap_tool_envelope(p, JUDGE_SCHEMA) is p


def test_does_not_unwrap_unknown_single_key():
    """알려진 래퍼 이름이 아니면 손대지 않는다."""
    p = {"result": {"winner": "A"}}
    assert _unwrap_tool_envelope(p, JUDGE_SCHEMA) is p


def test_does_not_unwrap_non_dict_inner():
    p = {"parameters": [1, 2, 3]}
    assert _unwrap_tool_envelope(p, JUDGE_SCHEMA) is p


def test_passes_through_non_dict_payload():
    assert _unwrap_tool_envelope([1, 2], JUDGE_SCHEMA) == [1, 2]
    assert _unwrap_tool_envelope("x", JUDGE_SCHEMA) == "x"
