#!/usr/bin/env python3
"""Meta 캐러셀 광고 A-2 (Problem 슬라이드) v2 — 감정 사진 배경 + 오버레이 개선.

변경 사항:
1. Gemini 배경: 라인 아이콘 그래픽 → 감정적 사진 장면 (비 오는 밤 사무실)
2. SVG 아이콘 레이어 제거
3. overlay-dark opacity 완화 (0.88 → 0.62)
4. 헤드라인 좌측 정렬 유지 확인
"""

from __future__ import annotations

import base64
import sys
import time
from pathlib import Path

import requests
from playwright.sync_api import sync_playwright
from gen_config import WORKSPACE_ROOT, FONT_DIR, CTA_MIN_PX

sys.path.insert(0, str(Path(__file__).parent))
import gcloud_auth  # noqa: E402
_SIZE_26PX = 26
_CTA_PX = CTA_MIN_PX
_SIZE_88PX = 88
_LH_1_18 = 1.18
_LH_1_65 = 1.65

# ─────────────────────────────────────────────────────────────────────────────
# 경로 설정
# ─────────────────────────────────────────────────────────────────────────────

OUTPUT_DIR = WORKSPACE_ROOT / "output/meta-ads/a-group-v6/production"
BG_JPEG = OUTPUT_DIR / "_bg_a2_problem.jpg"
OUTPUT_PNG = OUTPUT_DIR / "meta-A2-problem.png"
HTML_TEMP = OUTPUT_DIR / "_a2_problem_template.html"

# ─────────────────────────────────────────────────────────────────────────────
# Gemini 배경 생성 프롬프트 — 감정적 사진 장면
# ─────────────────────────────────────────────────────────────────────────────

BG_PROMPT = (
    "Cinematic photograph scene: A lone person's silhouette standing at a dark office window at night, "
    "rain streaking down the glass outside. The figure faces away from camera — backlit, solitary. "
    "On the desk behind: a dead monitor screen showing only darkness, scattered papers and documents. "
    "Color palette: cold blue-grey tones, desaturated, moody. "
    "Lighting: only faint city glow through the rain-soaked window casting blue-silver reflections. "
    "Atmosphere: profound isolation, quiet desperation, late-night exhaustion. "
    "IMPORTANT COMPOSITION: The upper 15% of the image should be dark and relatively clear/simple. "
    "The central 50% area (middle of frame) should have MINIMAL visual clutter — the silhouette figure "
    "should be positioned to one side or slightly off-center. "
    "The lower 35% should transition to deeper darkness for text readability. "
    "NO icons, NO graphics, NO illustrations, NO charts, NO infographics. "
    "NO text, NO watermarks, NO overlays. "
    "Photorealistic cinematic photography style. "
    "Film grain texture. Shallow depth of field. "
    "Aspect ratio: square 1:1, 1080x1080 pixels. "
    "Mood keywords: loneliness, stagnation, isolation, cold night, silent office."
)

# ─────────────────────────────────────────────────────────────────────────────
# Gemini API 설정
# ─────────────────────────────────────────────────────────────────────────────

MODEL_ID = "gemini-2.5-flash-image"
FALLBACK_MODEL_IDS = [
    "gemini-3.1-flash-image-preview",
    "gemini-3-pro-image-preview",
    "gemini-2.5-flash-image",
]
GEMINI_API_BASE = "https://generativelanguage.googleapis.com/v1beta"
GEMINI_SCOPE = "https://www.googleapis.com/auth/generative-language"


def generate_background(force: bool = False) -> Path:
    """Gemini API로 감정적 사진 배경 이미지를 생성하고 JPEG로 저장합니다."""
    if BG_JPEG.exists() and not force:
        print(f"[배경] 캐시된 배경 이미지 삭제 후 재생성 (force=False → 기존 파일 사용)")
        # 기존 파일이 있어도 새 배경이 필요하므로 항상 재생성
        pass

    # 기존 배경 삭제 후 새로 생성
    if BG_JPEG.exists():
        BG_JPEG.unlink()
        print(f"[배경] 기존 배경 이미지 삭제: {BG_JPEG}")

    print("[배경] Gemini API 토큰 획득 중...")
    token = gcloud_auth.get_access_token()
    print(f"[배경] 토큰 획득 완료 ({len(token)} chars)")

    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json",
    }

    # Gemini 이미지 생성 모델 시도
    models_to_try = [MODEL_ID] + FALLBACK_MODEL_IDS
    last_error = None

    for model in models_to_try:
        url = f"{GEMINI_API_BASE}/models/{model}:generateContent"
        payload = {
            "contents": [{"parts": [{"text": BG_PROMPT}]}],
            "generationConfig": {"responseModalities": ["IMAGE", "TEXT"]},
        }
        print(f"[배경] 이미지 생성 요청 중... (모델: {model})")
        start = time.time()

        try:
            resp = requests.post(url, headers=headers, json=payload, timeout=300)
            if resp.status_code in (403, 404):
                print(f"[배경] 모델 접근 불가 (HTTP {resp.status_code}): {model}")
                last_error = f"HTTP {resp.status_code}"
                continue

            resp.raise_for_status()
            elapsed = time.time() - start

            data = resp.json()
            candidates = data.get("candidates", [])
            if not candidates:
                print(f"[배경] candidates 없음, 다음 모델 시도: {str(data)[:200]}")
                last_error = "candidates 없음"
                continue

            parts = candidates[0].get("content", {}).get("parts", [])
            image_part = next((p for p in parts if "inlineData" in p), None)
            if image_part is None:
                texts = [p.get("text", "") for p in parts if "text" in p]
                print(f"[배경] 이미지 데이터 없음. 텍스트: {texts[:2]}")
                last_error = f"이미지 데이터 없음: {texts[:1]}"
                continue

            mime = image_part["inlineData"].get("mimeType", "image/jpeg")
            image_bytes = base64.b64decode(image_part["inlineData"]["data"])

            ext = ".jpg" if "jpeg" in mime else ".png"
            save_path = BG_JPEG.with_suffix(ext)
            save_path.write_bytes(image_bytes)
            print(f"[배경] 완료: {save_path.name} ({len(image_bytes):,} bytes, {elapsed:.1f}초) (모델: {model})")
            return save_path

        except requests.HTTPError as e:
            print(f"[배경] HTTP 오류: {e} (모델: {model})")
            last_error = str(e)
            continue
        except Exception as e:
            print(f"[배경] 오류: {e} (모델: {model})")
            last_error = str(e)
            continue

    raise RuntimeError(f"모든 Gemini 모델 시도 실패. 마지막 오류: {last_error}")


# ─────────────────────────────────────────────────────────────────────────────
# HTML 오버레이 템플릿 (수정된 버전)
# 변경: 1) top-icons 섹션 제거 2) overlay-dark opacity 완화 3) 좌측 정렬 유지
# ─────────────────────────────────────────────────────────────────────────────


def build_html(bg_path: str) -> str:
    """A-2 Problem 슬라이드 HTML 오버레이 v2를 빌드합니다.

    변경사항:
    - .top-icons 섹션 및 SVG 아이콘 3개 완전 제거
    - .overlay-dark 상단 opacity 0.88 → 0.62 (배경 사진 투과)
    - 헤드라인 좌측 정렬 (left: 64px) 유지
    """
    return f"""<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
  @font-face {{
    font-family: 'Pretendard';
    src: url('file://{FONT_DIR}/Pretendard-Black.otf') format('opentype');
    font-weight: 900;
  }}
  @font-face {{
    font-family: 'Pretendard';
    src: url('file://{FONT_DIR}/Pretendard-ExtraBold.otf') format('opentype');
    font-weight: 800;
  }}
  @font-face {{
    font-family: 'Pretendard';
    src: url('file://{FONT_DIR}/Pretendard-Bold.otf') format('opentype');
    font-weight: 700;
  }}
  @font-face {{
    font-family: 'Pretendard';
    src: url('file://{FONT_DIR}/Pretendard-Medium.otf') format('opentype');
    font-weight: 500;
  }}
  @font-face {{
    font-family: 'Pretendard';
    src: url('file://{FONT_DIR}/Pretendard-Regular.otf') format('opentype');
    font-weight: 400;
  }}

  * {{
    margin: 0;
    padding: 0;
    box-sizing: border-box;
  }}

  body {{
    width: 1080px;
    height: 1080px;
    overflow: hidden;
    background: #1A202C;
  }}

  .canvas {{
    width: 1080px;
    height: 1080px;
    position: relative;
    font-family: 'Pretendard', 'Noto Sans KR', sans-serif;
    overflow: hidden;
  }}

  /* ─── 배경 이미지 ─── */
  .bg {{
    position: absolute;
    inset: 0;
    background: url('file://{bg_path}') center center / cover no-repeat;
  }}

  /* ─── 전체 어둠 오버레이 — 배경 사진이 보이도록 opacity 완화 ─── */
  /* 변경: 상단 0.88 → 0.62 (배경 감정 전달을 위해) */
  .overlay-dark {{
    position: absolute;
    inset: 0;
    background: linear-gradient(
      to bottom,
      rgba(15, 18, 28, 0.62) 0%,
      rgba(15, 18, 28, 0.45) 20%,
      rgba(15, 18, 28, 0.38) 45%,
      rgba(10, 12, 20, 0.65) 72%,
      rgba(6, 8, 14, 0.95) 100%
    );
  }}

  /* ─── 헤드라인 영역 (Center 50%) — LEFT 정렬, 단호한 선언 느낌 ─── */
  /* Top 15% ~ 65%: y=162 ~ y=702 */
  .headline-wrap {{
    position: absolute;
    top: 162px;
    left: 64px;
    right: 64px;
    height: 540px;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: flex-start;
  }}

  .headline {{
    font-size: {_SIZE_88PX}px;
    font-weight: 900;
    color: #F7F8FA;
    line-height: {_LH_1_18};
    letter-spacing: -3.5px;
    word-break: keep-all;
    text-align: left;
    text-shadow: 0 2px 28px rgba(0,0,0,0.75);
  }}

  /* "방법이 없었던 거다." — 딥 앰버 포인트 컬러 강조 */
  .headline .accent {{
    color: #D97706;
    text-shadow:
      0 0 40px rgba(217, 119, 6, 0.45),
      0 2px 24px rgba(0,0,0,0.65);
    font-weight: 900;
  }}

  /* ─── 하단 서브카피 영역 (Bottom 35%) ─── */
  /* y=702 ~ y=1080 */
  .bottom-zone {{
    position: absolute;
    top: 702px;
    left: 0;
    right: 0;
    bottom: 0;
  }}

  /* 하단 어둠 강화 — 텍스트 가독성 보강 (유지) */
  .bottom-gradient {{
    position: absolute;
    inset: 0;
    background: linear-gradient(
      to bottom,
      rgba(6, 8, 14, 0.0) 0%,
      rgba(6, 8, 14, 0.75) 35%,
      rgba(6, 8, 14, 0.95) 100%
    );
  }}

  .subcopy-wrap {{
    position: absolute;
    bottom: 80px;
    left: 64px;
    right: 72px;
  }}

  /* 1번 서브카피 문장 */
  .subcopy-line1 {{
    font-size: {_CTA_PX}px;
    font-weight: 400;
    color: rgba(200, 205, 216, 0.80);
    line-height: {_LH_1_65};
    letter-spacing: -0.8px;
    word-break: keep-all;
    margin-bottom: 20px;
    text-align: left;
  }}

  /* 2번 서브카피 문장 — 여운을 위한 분리 */
  .subcopy-line2 {{
    font-size: {_CTA_PX}px;
    font-weight: 500;
    color: rgba(218, 220, 230, 0.88);
    line-height: {_LH_1_65};
    letter-spacing: -0.8px;
    word-break: keep-all;
    text-align: left;
  }}

  /* 페이지 인디케이터 2/5 */
  .page-indicator {{
    position: absolute;
    bottom: 32px;
    right: 52px;
    font-size: {_SIZE_26PX}px;
    font-weight: 500;
    color: rgba(180, 185, 200, 0.45);
    letter-spacing: 2px;
  }}

</style>
</head>
<body>
<div class="canvas">

  <!-- 배경 이미지 (감정적 사진 장면) -->
  <div class="bg"></div>

  <!-- 전체 어둠 오버레이 (opacity 완화 — 배경 사진 감정 전달) -->
  <div class="overlay-dark"></div>

  <!-- 상단 15%: 미니멀 여백 (아이콘 없이 깨끗하게) -->
  <!-- SVG 아이콘 3개 완전 제거 → 배경 사진이 시각적 역할 대체 -->

  <!-- 헤드라인 (Center 50%) — LEFT 정렬, 좌측 여백 64px, 단호한 선언 -->
  <div class="headline-wrap">
    <div class="headline">
      문제는 노력이 아니다.<br>
      <span class="accent">방법이 없었던 거다.</span>
    </div>
  </div>

  <!-- 하단 서브카피 영역 -->
  <div class="bottom-zone">
    <div class="bottom-gradient"></div>
    <div class="subcopy-wrap">
      <p class="subcopy-line1">지인 명단은 바닥났고, 알려줄 멘토도 없었다.</p>
      <p class="subcopy-line2">혼자 버티는 건 미덕이 아니라 손실이다.</p>
    </div>
  </div>

  <!-- 페이지 인디케이터 -->
  <div class="page-indicator">2 / 5</div>

</div>
</body>
</html>"""


# ─────────────────────────────────────────────────────────────────────────────
# Playwright 합성
# ─────────────────────────────────────────────────────────────────────────────


def capture_overlay(bg_path: Path) -> None:
    """HTML 오버레이를 Playwright로 캡처하여 최종 PNG를 저장합니다."""
    html_content = build_html(str(bg_path.resolve()))
    HTML_TEMP.write_text(html_content, encoding="utf-8")
    print(f"[오버레이] HTML 템플릿 저장: {HTML_TEMP}")

    print("[오버레이] Playwright 캡처 시작...")
    with sync_playwright() as p:
        browser = p.chromium.launch()
        try:
            page = browser.new_page(viewport={"width": 1080, "height": 1080})
            page.goto(f"file://{HTML_TEMP.resolve()}", wait_until="networkidle")
            # 폰트 렌더링 + 이미지 로드 대기
            page.wait_for_timeout(2500)
            OUTPUT_PNG.parent.mkdir(parents=True, exist_ok=True)
            page.screenshot(path=str(OUTPUT_PNG), type="png")
        finally:
            browser.close()

    size = OUTPUT_PNG.stat().st_size
    print(f"[오버레이] 완료: {OUTPUT_PNG} ({size:,} bytes)")


# ─────────────────────────────────────────────────────────────────────────────
# Main
# ─────────────────────────────────────────────────────────────────────────────


def main() -> None:
    print("=" * 60)
    print("Meta 캐러셀 A-2 Problem v2 이미지 생성 시작")
    print("변경: 감정 사진 배경 + 아이콘 제거 + overlay 완화")
    print(f"출력: {OUTPUT_PNG}")
    print("=" * 60)

    OUTPUT_DIR.mkdir(parents=True, exist_ok=True)

    # Step 1: 새 배경 이미지 생성 (기존 파일 강제 교체)
    bg_path = generate_background(force=True)

    # Step 2 & 3: HTML 오버레이 합성
    capture_overlay(bg_path)

    print("\n" + "=" * 60)
    print(f"완료: {OUTPUT_PNG}")
    print("=" * 60)


if __name__ == "__main__":
    main()
