"""임시 실험 — gpt-image-2 image_edit에서 floor plan PNG ref가 bg 출력을
top-down으로 강하게 bias 시키는지 검증.

T19 결과의 도면 1장을 ref로 4가지 시나리오에서 1024x1024 high quality 1장씩 생성:
  A: 현재 시스템 prompt (도면 모방 강제 문구 포함)
  B: cinematic eye-level 강조 + 모방 차단 명시
  C: fp ref 없음 (text-only) — fp bias 측정용 baseline
  D: fp ref + "layout reference ONLY, NOT a visual model" 명시

각 결과를 별도 PNG로 저장. 비용 ~$0.6. 시나리오 의존 단어 0(옥탑방·한국·한복 등 hardcoded 금지) — 도면 자체가 옥탑방이니 LLM이 도면에서 architectural style을 읽어 출력해야 함.

실행:
  cd backend && .venv/bin/python scripts/experiment_fp_ref_bias.py
"""
from __future__ import annotations

import os
import sys
import time
import base64
from pathlib import Path
from typing import Optional

sys.path.insert(0, str(Path(__file__).resolve().parent.parent))

PROJECT_ROOT = Path("/Users/manta/Documents/Projects/TheRoad-I1")
FP_PATH = (
    PROJECT_ROOT / "projects" / "c00bbe19-a9b5-463f-acfc-806f2e820258"
    / "images" / "fe165e3a-19c2-4a0f-9acb-e0c9bab0ee5a"
    / "floor_plan" / "fp_rooftop_unit.png"
)

OUT_DIR = PROJECT_ROOT / "scripts_output" / "fp_ref_bias_test"


# 공통 base prompt — 거실(living room) eye-level 한 컷이 목표
# 도면은 옥탑방(rooftop room) 한국식 small unit이지만 hardcoded 금지.
# 실제 운용에서는 visual_world_rules + scene_segments에서 LLM이 derive해야 하므로
# 여기서는 도면이 충분한 architectural cue를 시각적으로 보여준다고 가정.
COMMON_TAIL = (
    " Photoreal, soft warm afternoon light filtering through a window, "
    "shallow depth of field, subtle film grain. No people, no faces, "
    "no body posture. Single architectural still."
)

PROMPT_A = (
    "Living room interior. Preserve room layout, furniture positions, and "
    "architectural elements from the reference floor plan exactly."
    + COMMON_TAIL
)

PROMPT_B = (
    "Cinematic eye-level photograph of a living room interior, taken with "
    "a 35mm lens at standing human height. Wide angle composition framing "
    "furniture and walls from inside the room. Strictly NOT a top-down view, "
    "NOT a floor plan, NOT an architectural diagram — this is a still frame "
    "from a film, captured from a person's eye level inside the room."
    + COMMON_TAIL
)

PROMPT_C = PROMPT_B  # 동일 prompt, fp ref 없음

PROMPT_D = (
    "Cinematic eye-level photograph of a living room interior at standing "
    "human height (35mm lens). The provided reference image is a top-down "
    "architectural floor plan — use it ONLY to understand which furniture "
    "and openings are present and their relative positions. Do NOT replicate "
    "the top-down view; instead, render this scene as a film still captured "
    "from inside the room at eye level. The output must be a photographic "
    "interior shot, NOT a diagram."
    + COMMON_TAIL
)

# F: E와 동일 의도를 100% 한국어로 작성 — 시나리오 원문 언어가
# web grounding 검색 query에 영향을 주는지 검증.
PROMPT_F = (
    "옥탑방 거실 내부의 영화적 아이레벨 사진. 서울 저층 주거 건물 "
    "옥상에 지어진 작은 원룸. 2010년대 후반에서 2020년대 초반의 "
    "서민 가정 인테리어 — 비닐 마감 벽지, 형광등 천장 조명, 온돌식 "
    "낮은 마루, 평평한 콘크리트 옥상으로 열리는 알루미늄 미닫이 "
    "창틀. 사람의 눈높이(약 1.6m)에서 35mm 광각 렌즈로 촬영, 방 "
    "안에서 가구와 벽을 담는 와이드 컴포지션. 절대 위에서 내려다본 "
    "시점이 아니며, 도면이 아니고, 건축 다이어그램도 아님 — 한국 "
    "영화의 한 컷처럼 방 안 사람의 눈높이에서 포착된 정지 화면. "
    "사실적 사진, 부드러운 따뜻한 오후 햇살이 창으로 들어옴, 얕은 "
    "피사계 심도, 미세한 필름 그레인. 사람 없음, 얼굴 없음, 자세 "
    "없음. 단일 건축 정지 이미지."
)

# E: B prompt + 한국 옥탑방 cultural cue (web grounding 트리거 검증).
# 실험 코드 한정 hardcoded — production에서는 LLM이 visual_world_rules에서 derive.
PROMPT_E = (
    "Cinematic eye-level photograph of the interior of a Korean rooftop "
    "room (옥탑방) — a small one-room unit built on the rooftop of a "
    "low-rise residential building in Seoul, Korea. Working-class interior "
    "from the late 2010s to early 2020s: vinyl-finish wallpaper, "
    "fluorescent ceiling light, low ondol-style floor, sliding aluminum "
    "window frame opening to a flat concrete rooftop. 35mm lens at "
    "standing human height, wide angle composition framing furniture and "
    "walls from inside the room. Strictly NOT a top-down view, NOT a "
    "floor plan, NOT an architectural diagram — this is a still frame "
    "from a Korean film, captured from a person's eye level inside the "
    "room."
    + COMMON_TAIL
)


def _make_client():
    from dotenv import load_dotenv
    load_dotenv(PROJECT_ROOT / "backend" / ".env")
    from openai import OpenAI
    return OpenAI()


def _save(resp, out_path: Path) -> None:
    b64 = resp.data[0].b64_json if resp and resp.data else None
    if not b64:
        raise RuntimeError("empty b64 response")
    out_path.write_bytes(base64.b64decode(b64))


def _edit_with_fp(client, fp: Path, prompt: str, out: Path) -> None:
    print(f"  → edit (fp ref) → {out.name}")
    with fp.open("rb") as f:
        resp = client.images.edit(
            model="gpt-image-2",
            image=f,
            prompt=prompt,
            size="1536x864",
            quality="high",
            n=1,
        )
    _save(resp, out)


def _generate_text_only(client, prompt: str, out: Path) -> None:
    print(f"  → generate (text-only) → {out.name}")
    resp = client.images.generate(
        model="gpt-image-2",
        prompt=prompt,
        size="1536x864",
        quality="high",
        n=1,
    )
    _save(resp, out)


def main() -> int:
    if not FP_PATH.exists():
        print(f"ERROR: floor plan not found: {FP_PATH}", file=sys.stderr)
        return 1

    OUT_DIR.mkdir(parents=True, exist_ok=True)
    client = _make_client()

    print(f"FP source: {FP_PATH}")
    print(f"OUT dir: {OUT_DIR}")
    print()

    cases = [
        ("F_korean_prompt_with_fp_ref.png", PROMPT_F, "fp"),
    ]

    for fname, prompt, ref_mode in cases:
        out = OUT_DIR / fname
        print(f"[{fname}] ref={ref_mode}")
        t0 = time.time()
        try:
            if ref_mode == "fp":
                _edit_with_fp(client, FP_PATH, prompt, out)
            else:
                _generate_text_only(client, prompt, out)
            elapsed = time.time() - t0
            print(f"  ✓ {elapsed:.1f}s\n")
        except Exception as exc:
            print(f"  ✗ FAILED: {exc}\n", file=sys.stderr)

    print(f"DONE. compare: {OUT_DIR}")
    print(f"FP source for visual comparison: {FP_PATH}")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
