"""s17 — 블록 구조도 프롬프트를 LLM 이 저작 (사용자 정정, 2026-07-05):

잘못된 방식(폐기): 코드가 만든 FACTS 요약을 템플릿에 끼워 넣음.
올바른 방식(이 파일): **LLM 이 씬 원문 전체(+멤버+제작자 정정)를 직접 보고**,
"컴퓨터 프로그램이 그린 것 같은 플랫 블록 구조도"를 그리게 하는 **이미지 생성
프롬프트를 직접 저작**(EN, 한국어 번역 동봉) → 그 프롬프트만으로(참조 이미지 0)
nb2 가 작도. gpt 대조 1장 동시 생성.
사용: .venv/bin/python s17_blocks_llm.py [--only prompt|images|html]
산출: plans/blocks_llm_prompt.json, out/blockset/blocks2_{nb2,gpt}.png,
      blockgen.html 갱신
"""
import argparse
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).parent))
import forest_lib as F  # noqa: E402
import s13_blockset_v2 as S13  # noqa: E402
import s14_blockgen as S14  # noqa: E402

OUTB = F.OUT / "blockset"

AUTHOR_SYSTEM = """You write ONE SHORT image-generation prompt that makes an image
model draw a BLOCK DIAGRAM of one real-world place (a building and its
grounds), based on the production data you receive (member descriptions, full
scene texts, production-owner corrections).

This is the FIRST of THREE SEPARATE stages: (1) block diagram -> (2) detailed
floor plan -> (3) photorealistic still. Your prompt serves ONLY stage (1) — a
flat 2D top-down figure like one a computer program draws, for structural
comprehension only. Later stages own drawing style and realism: do NOT include
their concerns (no drafting/line/style aesthetics, no interior layout, no
materials, no mood).

Your prompt must demand exactly this and nothing more:
- plain flat solid-colour blocks (rectangles/circles) on a light background;
  strict top-down 2D; no 3D, no perspective, no shading, no texture.
- EXTERIOR structure only: each building is ONE solid block — NEVER any
  interior rooms, inner walls, furniture or fittings inside any building.
  Include: building masses, any upper-level unit block on its deck, exterior
  level-connecting routes, ground spaces (road/alley/yard/entrance), key
  exterior permanent fixtures, neighbouring masses as plain blocks.
- each element: ONE block with its relative size and position in plain spatial
  words (canvas thirds/edges, beside / on top of / connected to).
- one simple flat tint rule ONLY to tell height levels apart (list the few
  levels low to high). No other colour or style instructions.
- no text, letters, numbers, labels, legend or compass in the image; no
  people, no props, no vehicles; nothing story-specific.

Honour the production-owner corrections (they affect WHICH exterior elements
exist, e.g. the exterior stair type). Write ENGLISH, 80-150 words, direct
drawing instructions. Output prompt_en, faithful prompt_ko (human review),
notes (which scene/member lines grounded the layout)."""

AUTHOR_SCHEMA = {
    "type": "object",
    "properties": {
        "prompt_en": {"type": "string"},
        "prompt_ko": {"type": "string"},
        "notes": {"type": "string"},
    },
    "required": ["prompt_en", "prompt_ko", "notes"],
    "additionalProperties": False,
}


def author_prompt(recon):
    members = F.members_block(recon["members"])
    idxs, scenes = S13.scene_texts(recon)
    ov = S14.load_overrides()
    user = ("PLACE MEMBERS:\n" + members
            + "\n\nFULL ORIGINAL SCENE TEXTS:\n\n" + scenes
            + "\n\nPRODUCTION-OWNER CORRECTIONS:\n"
            + "\n".join(ov.get("facts_extra") or ["(none)"])
            + "\n\nWrite the block-diagram image prompt now.")
    out = F.llm("forest_blocks_llm_prompt", AUTHOR_SYSTEM, user, AUTHOR_SCHEMA,
                model="gpt")
    F.save_plan("blocks_llm_prompt", out)
    print(f"authored: {len(out['prompt_en'].split())} words | scenes {idxs}")
    return out


def images(authored, gen="blocks3"):
    p = authored["prompt_en"]
    # 페이지 표시용 — nb2 체인 섹션 프롬프트 사전에 병합
    try:
        prompts = F.load_plan("nb2_chain_prompts")
    except Exception:
        prompts = {}
    prompts[f"{gen}_nb2.png"] = p
    prompts[f"{gen}_gpt.png"] = p
    F.save_plan("nb2_chain_prompts", prompts)
    F.img_nb2(f"s17_{gen}_nb2", p, [], out_path=OUTB / f"{gen}_nb2.png")
    _html()
    F.img_gpt(f"s17_{gen}_gpt", p, refs=None,
              out_path=OUTB / f"{gen}_gpt.png")
    _html()


def _html():
    recon = F.load_recon()
    layout = F.load_plan("blockset_layout_v2")
    S14.build_html(layout, recon)


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--only", default="all",
                    choices=["all", "prompt", "images", "html"])
    args = ap.parse_args()
    recon = F.load_recon()
    if args.only in ("all", "prompt"):
        authored = author_prompt(recon)
    else:
        authored = F.load_plan("blocks_llm_prompt")
    if args.only in ("all", "images"):
        images(authored)
    if args.only in ("all", "html"):
        _html()
    F.runlog({"kind": "stage", "stage": "s17_blocks_llm", "done": args.only})


if __name__ == "__main__":
    main()
