#!/usr/bin/env python3
"""Meta 캐러셀 광고 Venus A-1 (Hook 슬라이드) 하이브리드 이미지 생성.

Gemini API로 배경(어두운 야간 작업 환경) 생성 →
Playwright HTML 오버레이로 한글 카피 합성.
출력: 1080x1080 PNG → /home/jay/workspace/output/meta-ads/a-group-venus/venus-A1-hook.png
"""

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
_CTA_PX = CTA_MIN_PX
_SIZE_88PX = 88
_LH_1_18 = 1.18
_LH_1_72 = 1.72

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

OUTPUT_DIR = WORKSPACE_ROOT / "output/meta-ads/a-group-venus"
BG_JPEG = OUTPUT_DIR / "_bg_venus_a1_hook.jpg"
OUTPUT_PNG = OUTPUT_DIR / "venus-A1-hook.png"
HTML_TEMP = OUTPUT_DIR / "_venus_a1_hook_template.html"

# ─────────────────────────────────────────────────────────────────────────────
# Gemini 배경 생성 프롬프트
# ─────────────────────────────────────────────────────────────────────────────

BG_PROMPT = (
    "Cinematic still photograph for a premium Meta advertisement. "
    "Scene: A dimly lit office desk late at night, viewed from slightly above at 25-degree angle. "
    "A silhouette of a person's upper body sits hunched at the desk — only the outline visible, "
    "no face details, viewed from behind or side. "
    "Scattered papers, notebooks, and a closed laptop on the dark desk surface. "
    "A single dim desk lamp casts a cold, lonely blue-grey glow — not warm, cold light only. "
    "The room is otherwise in near-darkness, deep charcoal walls. "
    "Mood: crushing weight of daily grind, invisible exhaustion, numbness, late-night loneliness. "
    "Color palette: deep charcoal (#1A1A2E), dark navy (#16213E), cold blue-grey (#0F3460). "
    "Zero warm tones — no orange, no yellow. Pure cold darkness. "
    "The bottom 40% of frame fades into absolute near-black for text overlay space. "
    "Shallow depth of field, cinematic grain (ISO 6400 film look). "
    "Shot on ARRI Alexa 65 with Zeiss Master Prime 35mm — cinematic anamorphic lens flare faint. "
    "Style: Christopher Nolan / Denis Villeneuve film still. Premium advertising photography. "
    "1:1 square composition 1080x1080. No text, no watermarks, no logos."
)

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

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


def generate_background() -> Path:
    """Gemini API로 배경 이미지를 생성하고 JPEG로 저장합니다."""
    if BG_JPEG.exists():
        print(f"[배경] 캐시된 배경 이미지 사용: {BG_JPEG}")
        return BG_JPEG

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

    url = f"{GEMINI_API_BASE}/models/{MODEL_ID}:generateContent"
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json",
    }
    payload = {
        "contents": [{"parts": [{"text": BG_PROMPT}]}],
        "generationConfig": {"responseModalities": ["IMAGE", "TEXT"]},
    }

    print(f"[배경] 이미지 생성 요청 중... (모델: {MODEL_ID})")
    start = time.time()
    resp = requests.post(url, headers=headers, json=payload, timeout=300)

    # fallback to pro image model if flash preview unavailable
    if resp.status_code in (403, 404):
        print(f"[배경] 모델 접근 불가 (HTTP {resp.status_code}). Fallback: {FALLBACK_MODEL_ID}")
        url = f"{GEMINI_API_BASE}/models/{FALLBACK_MODEL_ID}:generateContent"
        resp = requests.post(url, headers=headers, json=payload, timeout=300)

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

    data = resp.json()
    candidates = data.get("candidates", [])
    if not candidates:
        raise RuntimeError(f"candidates 없음: {str(data)[:300]}")

    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]
        raise RuntimeError(f"이미지 데이터 없음. 텍스트: {texts[:2]}")

    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}초)")
    return save_path


# ─────────────────────────────────────────────────────────────────────────────
# HTML 오버레이 템플릿 생성
# ─────────────────────────────────────────────────────────────────────────────


def build_html(bg_path: str) -> str:
    """Venus A-1 Hook 슬라이드 HTML 오버레이를 빌드합니다."""
    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: #0D0F1A;
  }}

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

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

  /* ─── 전체 어둠 오버레이 (분위기 강화) ─── */
  .overlay-dark {{
    position: absolute;
    inset: 0;
    background: linear-gradient(
      to bottom,
      rgba(10, 12, 24, 0.72) 0%,
      rgba(10, 12, 24, 0.40) 25%,
      rgba(10, 12, 24, 0.30) 45%,
      rgba(6, 8, 18, 0.65) 65%,
      rgba(3, 4, 12, 0.96) 100%
    );
  }}

  /* ─── 헤드라인 (중앙 배치, 골든비율 위치) ─── */
  .headline-wrap {{
    position: absolute;
    top: 50%;
    left: 64px;
    right: 64px;
    transform: translateY(-55%);
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
  }}

  .headline {{
    font-size: {_SIZE_88PX}px;
    font-weight: 900;
    color: #FFFFFF;
    line-height: {_LH_1_18};
    letter-spacing: -3.5px;
    word-break: keep-all;
    text-shadow:
      0 2px 32px rgba(0,0,0,0.80),
      0 0 80px rgba(0,0,0,0.50);
    /* WCAG AAA 7:1 contrast: white on dark overlay */
  }}

  /* ─── 하단 텍스트 영역 ─── */
  .bottom-zone {{
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 380px;
  }}

  /* 하단 그라디언트 오버레이 — 텍스트 가독성 WCAG AAA */
  .bottom-gradient {{
    position: absolute;
    inset: 0;
    background: linear-gradient(
      to bottom,
      rgba(3, 4, 12, 0.0) 0%,
      rgba(3, 4, 12, 0.88) 35%,
      rgba(3, 4, 12, 0.97) 100%
    );
  }}

  .subcopy-wrap {{
    position: absolute;
    bottom: 100px;
    left: 64px;
    right: 112px;
  }}

  .subcopy {{
    font-size: {_CTA_PX}px;
    font-weight: 400;
    color: rgba(190, 195, 215, 0.82);
    line-height: {_LH_1_72};
    letter-spacing: -0.8px;
    word-break: keep-all;
    text-shadow: 0 1px 12px rgba(0,0,0,0.80);
  }}

  .subcopy .em {{
    color: rgba(220, 224, 238, 0.95);
    font-weight: 600;
  }}

  /* ─── 페이지 인디케이터 1/5 ─── */
  .page-indicator {{
    position: absolute;
    bottom: 44px;
    right: 52px;
    font-size: {_CTA_PX}px;
    font-weight: 500;
    color: rgba(180, 185, 205, 0.65);
    letter-spacing: 1px;
    text-shadow: 0 1px 8px rgba(0,0,0,0.70);
    font-variant-numeric: tabular-nums;
  }}

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

  <!-- 배경 이미지 -->
  <div class="bg"></div>

  <!-- 전체 어둠 오버레이 -->
  <div class="overlay-dark"></div>

  <!-- 헤드라인 (중앙) -->
  <div class="headline-wrap">
    <div class="headline">
      열심히 했다.<br>
      근데 왜 나만 안 되지?
    </div>
  </div>

  <!-- 하단 서브카피 영역 -->
  <div class="bottom-zone">
    <div class="bottom-gradient"></div>
    <div class="subcopy-wrap">
      <p class="subcopy">
        <span class="em">방문 횟수, 전화 통화, 상담 건수</span>—<br>
        숫자는 쌓이는데 통장은 그대로다.
      </p>
    </div>
  </div>

  <!-- 페이지 인디케이터 -->
  <div class="page-indicator">1/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("Venus Meta 캐러셀 A-1 Hook 이미지 생성 시작")
    print(f"출력: {OUTPUT_PNG}")
    print("=" * 60)

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

    # Step 1: 배경 이미지 생성
    bg_path = generate_background()

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

    print("\n" + "=" * 60)
    print(f"완료: {OUTPUT_PNG}")
    file_size = OUTPUT_PNG.stat().st_size
    print(f"파일 크기: {file_size:,} bytes")
    print("=" * 60)


if __name__ == "__main__":
    main()
