"""합성은 **지금 몸**에 묶인다 — 수동 경로도 같은 판정 (Codex BLOCK 3·4, 2026-09-19).

## 무엇이 결함이었나

① 수동 합성 재생성은 사람 경로로 **고정**돼 있었다. 로봇 기본 참조를 전신으로
   고쳐 놓아도 사용자가 「합성 다시 만들기」를 누르면 **몸을 새로 그렸다**.
② 소비자는 (인물, 아웃룩) 두 칸만 보고 **먼저 걸린 자산**을 썼다. 기본 몸체를
   다시 만들어도 옛 몸으로 그린 합성이 그대로 붙을 수 있었다.
"""
from __future__ import annotations

import inspect


def test_manual_composite_reads_the_same_judgment():
    from app.services import reference_composite_service as m

    src = inspect.getsource(m)
    assert "body_identity_short_ids" in src, "수동 경로가 판정을 안 읽는다"
    assert '"composite_derive" if _derive else "composite"' in src
    assert "entity_type=_ctype" in src, "타입을 안 가르면 문안이 덮인다"
    assert "COMPLETE BODY" in src, "첫 참조를 몸으로 표시하지 않는다"


def test_manual_composite_key_matches_the_batch():
    from app.services import reference_composite_service as m

    src = inspect.getsource(m)
    assert 'composite:{character_id}:{outlook_id}:{face_asset.id}' in src, (
        "배치와 키 모양이 다르면 소비자가 못 고른다")
    assert '"key": f"[composite:{character_id}:{outlook_id}%"' in src, (
        "옛 합성이 안 내려가 둘이 공존한다")


def test_consumer_prefers_the_composite_of_the_current_base():
    from app.services import scene_reference_service as m

    src = inspect.getsource(m)
    assert "_cur_base" in src, "현재 기본 참조를 안 본다"
    assert "def _rank(" in src, "후보 중 고르는 규칙이 없다(먼저 걸린 것을 쓴다)"
    # 옛판(기본 참조 표시 없음)도 버리지 않고 뒤로 둔다
    assert "if not base_id else 2" in src


def test_the_key_regex_accepts_both_shapes():
    """옛 키(두 칸)와 새 키(세 칸)를 모두 읽어야 기존 자산이 안 사라진다."""
    import re

    pat = r'composite:([a-f0-9-]+):([a-f0-9-]+)(?::([a-f0-9-]+))?'
    old = re.search(pat, "[composite:aaa-1:bbb-2] 이름")
    new = re.search(pat, "[composite:aaa-1:bbb-2:ccc-3] 이름")
    assert old and old.group(3) is None
    assert new and new.group(3) == "ccc-3"
    assert old.group(1, 2) == new.group(1, 2)
