"""옷 참조의 **마네킹**이 합성 결과에 들어오면 안 된다 (2026-09-19).

## 무엇이 났나 — 실측 (사용자 지적)

찰리(고릴라 비율 로봇)의 아웃룩 합성 셋과 그 합성을 밑감으로 만든 상태
변형 둘이 전부 **몸이 두 번 그려진** 그림으로 나왔다. 사람 비율 몸통에
우비를 입히고, 로봇 팔·어깨는 그 뒤에 따로 떠 있는 식이다. 팔다리가
서너 개씩 겹친 것도 있다.

## 왜

합성에 들어가는 참조가 두 장이다.

    image 1 — 찰리 (고릴라 비율 로봇 전신)
    image 2 — **사람 모양 회색 마네킹이 입은 우비** (회색 바지·초록 장화까지)

`character_outlook_ref` 는 **일부러** 「회색 사람 모양 마네킹」을 그린다.
사람 인물끼리는 모양이 같아 넘어갔지만, 합성 문안 어디에도 **「마네킹은
진열대일 뿐 옷만 가져와라」**가 없었다. 그래서 모델이 몸 둘을 섞었다.

그리고 파생 문안에는 모순이 있었다 — 「몸을 그대로 두라」와 「각 품목의
겉모습을 그대로 유지하라」가 동시에 절대 명령이었다. 사람 몸에 맞춘 옷은
고릴라 비율 로봇에 **그대로** 들어갈 수 없다. 모델은 둘 다 그려서 풀었다.

## 어떻게 고쳤나

금지를 쌓는 대신 **무엇을 가져오고 무엇을 바꿀지** 적었다.
 - 참조 2+ 는 진열용 마네킹이다. **옷만** 가져온다.
 - 옷은 이 몸에 맞게 **다시 재단한다** — 색·무늬·재질은 그대로, 재단만 바뀐다.
 - 못 덮는 팔다리는 참조 1 그대로 드러난 채 둔다.
"""
from __future__ import annotations

from app.modules.prompt_loader import load_prompt, resolve_effective


def _pack(stem: str) -> str:
    return load_prompt("ref_image_prompts", stem)


def _flat(stem: str) -> str:
    """줄바꿈을 지운 형태. ★팩은 줄을 접어 쓰므로 「A B」가 「A\n  B」로
    들어간다 — 그대로 견주면 있는 문장을 없다고 읽는다(실측)."""
    import re
    return re.sub(r"\s+", " ", _pack(stem))


def test_the_human_composite_says_the_mannequin_is_a_fixture():
    """★사람 갈래는 옷 사진을 **계속 쓴다** — 그래서 마네킹 절이 필요하다.

    로봇 갈래(derive)는 v9 부터 옷 사진을 **아예 안 받는다**(아래 시험).
    사진이 없는데 「마네킹은 진열대」라고 적으면 없는 것을 설명하는 꼴이다.
    """
    t = _pack("character_composite_ref")
    assert "display mannequin" in t
    assert "NOT a character" in t
    assert "ONLY the clothing" in t


def test_the_derive_prompt_takes_the_outfit_as_text_not_a_photo():
    """★글 다섯 판이 실패한 뒤 **재료를 바꿨다** (v9).

    팩 v7 에 「마네킹은 진열대」·「이 몸에 맞게 재단」을 넣고 유료로 다시
    만들었는데도 찰리가 카고바지에 사람 다리로 나왔다. 참조 두 장이 둘 다
    몸인 한 글로는 안 막힌다 — 그래서 **두 번째 몸을 안 보여준다.**
    """
    t = _pack("character_composite_derive_ref")
    assert "DESCRIBED, not shown" in t
    assert "{outlook_description}" in t, "옷 설명을 받을 자리가 없다"
    assert "ONE reference image" in t
    # 사진이 없으니 마네킹 얘기도 없어야 한다 — 없는 것을 설명하지 않는다.
    assert "display mannequin" not in t


def test_the_derive_prompt_resolves_the_contradiction():
    """몸을 그대로 두면서 옷도 그대로 둘 수는 없다 — 누가 이기는지 적어야 한다."""
    t = _flat("character_composite_derive_ref")
    assert "proportions decide" in t, (
        "옷이 몸에 맞춰지는 것이지 그 반대가 아니라는 말이 없다")
    assert "Cut and drape the garment to fit" in t
    # ★실측으로 나온 실패를 이름으로 막는다 — 카고바지에 사람 다리.
    assert "human proportions" in t and "trousers" in t


def test_the_derive_prompt_pins_the_limb_count():
    """★「나란히 둘」이 아니라 **한 몸에 팔다리가 겹치는** 실패였다.

    옛 문안의 「Draw exactly ONE figure. No alternate versions, no turnaround
    sheet」로는 이 실패가 안 걸린다 — 그림 속 figure 는 하나였다.
    """
    t = _pack("character_composite_derive_ref")
    assert "the same count, in the same places" in t
    assert "One head, one torso, one set of limbs" in t


def test_the_outlook_reference_still_uses_a_mannequin():
    """★마네킹 자체는 그대로 둔다 — 고칠 곳은 **쓰는 법**이지 재료가 아니다.

    아웃룩 단독 참조는 옷을 보여 주는 그림이라 사람 모양 틀이 필요하다.
    이것까지 바꾸면 사람 인물 25벌이 통째로 다시 돈다.
    """
    t = _pack("character_outlook_ref")
    assert "mannequin" in t


def test_the_pack_version_moved_forward():
    """덮어쓰지 않고 새 판을 냈는가 (이 저장소 규칙)."""
    v = resolve_effective("ref_image_prompts", "character_composite_derive_ref",
                          kind="prompt")["version"]
    assert v.split(".")[0].isdigit() and int(v.split(".")[0]) >= 7, v


# ── ★새 방어를 넣으면서 **옛 방어를 지웠다** (2026-09-19) ──────────────

def test_the_old_turnaround_guard_is_still_there():
    """★내가 지웠다가 되살린 줄이다 — 지우자마자 세 컷이 나왔다.

    팩 v7 에서 「팔다리 개수」 문장을 넣으면서 옛 줄을 **갈아치웠다**::

        Draw exactly ONE figure. No alternate versions, no turnaround sheet,
        no variants side by side.

    바로 다음 유료 생성에서 찰리 합성이 **세 컷 나란히**(턴어라운드 시트)로
    나왔다. 새 방어를 더할 때는 **옛 방어가 막던 실패도 같이 태워야** 한다.

    두 실패는 다른 것이다.
      - 턴어라운드: 그림 안에 figure 가 **여럿** (나란히)
      - 팔다리 겹침: figure 는 하나인데 **한 몸 안에서** 겹침
    둘 다 적혀 있어야 한다.
    """
    for stem in ("character_composite_ref", "character_composite_derive_ref"):
        t = _pack(stem)
        assert "turnaround sheet" in t, f"{stem}: 턴어라운드 방어가 사라졌다"
        assert "ONE figure" in t, f"{stem}: figure 하나 제약이 사라졌다"

    d = _pack("character_composite_derive_ref")
    # 겹침 방어도 그대로 있어야 한다 — 하나를 넣느라 다른 하나를 빼면 안 된다.
    assert "the same count, in the same places" in d
