"""판정기는 후보·라벨·스키마가 어긋나면 **보내기 전에** 멈춘다 (2026-09-19).

S11sh1 실측: 후보는 A 한 장인데 판정기는 A·B 두 장용 스키마로 지어져
있었다. 그대로 보내면 두 심판 값을 다 치르고 「cross-model 선정 판정 전건
실패」로 돌아온다 — 그 오류문으로는 판정기가 틀렸는지 모델이 틀렸는지
못 가른다(실제로 나는 원인을 잘못 짚었다).
"""
from __future__ import annotations

import pytest


def _judge(monkeypatch, n_schema):
    from app.modules.llm import llm_client
    from app.modules.pipeline import multiroll_gemini as mg
    from app.modules.pipeline.multiroll_select import (
        build_judge_schema,
        roll_labels,
    )

    sent = []

    def fake_call_structured(*a, **k):
        sent.append(k.get("project_config"))
        return {"SAMPLE": True}

    monkeypatch.setattr(llm_client, "call_structured", fake_call_structured)
    # 단독 심판 갈래 — 이 시험은 보내기 **전** 검사만 본다
    monkeypatch.setattr(mg, "resolve_select_judge_models",
                        lambda: [mg.JUDGE_MODEL])
    jf = mg.make_gemini_judge_fn(
        judge_sys="SAMPLE",
        judge_schema=build_judge_schema(
            roll_labels(n_schema), with_physics=True))
    return jf, sent


def _png(tmp_path, name):
    p = tmp_path / name
    p.write_bytes(b"\x89PNG\r\n\x1a\n" + name.encode())
    return p


def test_one_candidate_against_two_label_schema_never_sends(
        monkeypatch, tmp_path):
    jf, sent = _judge(monkeypatch, 2)
    with pytest.raises(ValueError, match="judge 계약 불일치"):
        jf("S1sh1", "SAMPLE", [], [_png(tmp_path, "a.png")], ["A"])
    assert sent == []


def test_labels_and_candidates_of_different_length_never_send(
        monkeypatch, tmp_path):
    jf, sent = _judge(monkeypatch, 2)
    with pytest.raises(ValueError, match="judge 계약 불일치"):
        jf("S1sh1", "SAMPLE", [], [_png(tmp_path, "a.png")], ["A", "B"])
    assert sent == []


def test_matching_contract_sends(monkeypatch, tmp_path):
    jf, sent = _judge(monkeypatch, 1)
    out = jf("S1sh1", "SAMPLE", [], [_png(tmp_path, "a.png")], ["A"])
    assert out == {"SAMPLE": True}
    assert len(sent) == 1
