#!/usr/bin/env python3
"""
Pilot A-3 (Solution) — Meta Carousel Slide
Deep navy → Gold/Ivory blueprint aesthetic
Hybrid: Gemini background + Playwright HTML overlay
"""

import base64
import sys
import time
from pathlib import Path

import requests
from playwright.sync_api import sync_playwright

# ── paths ─────────────────────────────────────────────────────────────────────
BASE_DIR = Path("/home/jay/workspace/output/meta-ads/a-group-v6/pilot")
BG_PATH   = BASE_DIR / "bg_A3.jpg"
HTML_PATH = BASE_DIR / "overlay_A3.html"
OUT_PATH  = BASE_DIR / "pilot-A3-solution.png"
BASE_DIR.mkdir(parents=True, exist_ok=True)

# ── Gemini config ──────────────────────────────────────────────────────────────
sys.path.insert(0, "/home/jay/workspace/tools/ai-image-gen")
import gcloud_auth  # noqa: E402

GEMINI_API_BASE = "https://generativelanguage.googleapis.com/v1beta"
MODEL_PRIMARY   = "gemini-3-pro-image-preview"
MODEL_FALLBACK  = "gemini-3.1-flash-image-preview"
SCOPE           = "https://www.googleapis.com/auth/generative-language"

BG_PROMPT = """
Create a dark, premium architectural blueprint visualization for a luxury insurance strategy advertisement.

COMPOSITION: 1:1 square, 1080x1080px. Full bleed.

SCENE: An intricate, glowing technical diagram — a precision sales flow network — unfolding in deep darkness.
Blueprint-style lines and nodes form a connected strategy map. The diagram has geometric precision:
clean vector-like glowing lines connecting circular and rectangular nodes.
Three clearly labeled node clusters are visible: flowing connection paths between them.

VISUAL LANGUAGE:
- Blueprint / engineering schematic aesthetic
- Glowing cyan-gold lines on deep navy background
- Lines and nodes reminiscent of circuit boards + architectural floor plans
- The system diagram occupies the center-left area of the frame
- Subtle grid pattern in extreme background (like graph paper, very faint)
- Depth: foreground elements sharp and bright, background fades into darkness

LIGHTING / COLOR:
- Dominant: Deep navy blue (#1A2F5E) to near-black
- Glowing elements: Gold (#C9A84C) and warm ivory lines
- Occasional faint teal-blue accent on technical grid lines
- Top 40% of image: deepest navy, almost black — good for text overlay
- Bottom 30%: slightly lighter, warm glow rising from lower-left as if dawn breaking —
  subtle gold-ivory light suggesting transition from dark to light (this is slide 3 of 5 in a dark-to-light journey)
- Overall: intelligent warmth, NOT cold tech blue

STYLE:
- Like a McKinsey strategy presentation visual made into premium advertising
- Premium, dark luxury advertising — Rolex / Patek Philippe meets consulting firm
- NO stock photo aesthetic
- NO people, faces, or human figures
- NO text or labels — all text will be overlaid separately
- NO bright white areas
- Cinematic quality, ultra-detailed

MOOD: Precision. Intelligence. Systematic. Warm authority. The system itself is the protagonist.
"""

# ── Step 1: Generate Gemini background ────────────────────────────────────────

def generate_background() -> Path:
    if BG_PATH.exists():
        print(f"[BG] 기존 배경 이미지 재사용: {BG_PATH}")
        return BG_PATH

    print("[BG] Gemini API로 배경 이미지 생성 중...")
    token = gcloud_auth.get_service_account_token(SCOPE)

    def _call(model_id: str) -> requests.Response:
        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"]},
        }
        return requests.post(url, headers=headers, json=payload, timeout=300)

    t0 = time.time()
    resp = _call(MODEL_PRIMARY)
    if resp.status_code in (403, 404):
        print(f"[BG] Pro 모델 실패 (HTTP {resp.status_code}), fallback 시도...")
        resp = _call(MODEL_FALLBACK)
    resp.raise_for_status()

    data = resp.json()
    parts = data["candidates"][0]["content"]["parts"]
    img_part = next((p for p in parts if "inlineData" in p), None)
    if img_part is None:
        raise RuntimeError(f"이미지 없음. 응답: {str(data)[:400]}")

    mime  = img_part["inlineData"].get("mimeType", "image/jpeg")
    b64   = img_part["inlineData"]["data"]
    ext   = ".jpg" if "jpeg" in mime else ".png"
    fpath = BG_PATH.with_suffix(ext)
    fpath.write_bytes(base64.b64decode(b64))
    print(f"[BG] 완료: {fpath.name} ({fpath.stat().st_size:,} bytes, {time.time()-t0:.1f}초)")
    return fpath


# ── Step 2: Write HTML overlay ─────────────────────────────────────────────────

HTML_TEMPLATE = """\
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<style>
  @font-face {{
    font-family: 'Pretendard';
    src: local('Pretendard Variable'),
         url('/home/jay/.local/share/fonts/Pretendard/PretendardVariable.ttf') format('truetype');
    font-weight: 100 900;
  }}

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

  html, body {{
    width: 1080px;
    height: 1080px;
    overflow: hidden;
    background: #0d1e3a;
  }}

  .canvas {{
    width: 1080px;
    height: 1080px;
    position: relative;
    background-image: url('{bg_url}');
    background-size: cover;
    background-position: center center;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding: 56px 72px 60px 72px;
  }}

  /* Dark overlay gradient — heavier at top for text readability */
  .canvas::before {{
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(
      180deg,
      rgba(10, 18, 42, 0.72) 0%,
      rgba(10, 18, 42, 0.48) 40%,
      rgba(10, 18, 42, 0.30) 65%,
      rgba(15, 25, 55, 0.55) 100%
    );
    pointer-events: none;
  }}

  /* All direct children above the overlay */
  .canvas > * {{ position: relative; z-index: 1; }}

  /* ── TOP: Brand badge ── */
  .top-zone {{
    display: flex;
    align-items: flex-start;
  }}

  .brand-badge {{
    display: inline-flex;
    align-items: center;
    gap: 10px;
    border: 1.5px solid rgba(201, 168, 76, 0.55);
    border-radius: 6px;
    padding: 10px 20px;
    background: rgba(13, 30, 58, 0.60);
    backdrop-filter: blur(8px);
  }}

  .badge-dot {{
    width: 7px;
    height: 7px;
    background: #C9A84C;
    border-radius: 50%;
    flex-shrink: 0;
    box-shadow: 0 0 8px rgba(201, 168, 76, 0.8);
  }}

  .badge-text {{
    font-family: 'Pretendard', 'Noto Sans KR', sans-serif;
    font-weight: 700;
    font-size: 28px;
    color: #C9A84C;
    letter-spacing: 0.04em;
    line-height: 1;
  }}

  /* ── MIDDLE: Headline zone ── */
  .middle-zone {{
    display: flex;
    flex-direction: column;
    flex: 1;
    justify-content: center;
    padding: 20px 0;
  }}

  .eyebrow {{
    font-family: 'Pretendard', 'Noto Sans KR', sans-serif;
    font-weight: 400;
    font-size: 22px;
    color: rgba(201, 168, 76, 0.75);
    letter-spacing: 0.18em;
    text-transform: uppercase;
    margin-bottom: 26px;
  }}

  .headline {{
    font-family: 'Pretendard', 'Noto Sans KR', sans-serif;
    font-weight: 800;
    font-size: 84px;
    line-height: 1.20;
    letter-spacing: -0.025em;
    color: #F5F0E8;
    margin-bottom: 0;
    word-break: keep-all;
  }}

  .headline .hl-gold {{
    color: #C9A84C;
    font-weight: 900;
  }}

  .divider {{
    width: 72px;
    height: 2px;
    background: linear-gradient(90deg, #C9A84C 0%, rgba(201, 168, 76, 0.15) 100%);
    margin: 38px 0 0 0;
  }}

  /* ── BOTTOM: Subcopy zone ── */
  .bottom-zone {{
    display: flex;
    flex-direction: column;
    gap: 0;
  }}

  /* Antithesis pair */
  .antithesis-block {{
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin-bottom: 24px;
  }}

  .antithesis-row {{
    display: flex;
    align-items: baseline;
    font-family: 'Pretendard', 'Noto Sans KR', sans-serif;
    font-size: 44px;
    font-weight: 300;
    line-height: 1.55;
    color: rgba(240, 235, 225, 0.62);
    letter-spacing: -0.01em;
    white-space: nowrap;
  }}

  .antithesis-row .dim {{
    font-weight: 300;
    color: rgba(240, 235, 225, 0.55);
  }}

  .antithesis-row .sep {{
    color: rgba(201, 168, 76, 0.45);
    font-weight: 300;
    margin: 0 12px;
    font-size: 38px;
  }}

  .antithesis-row .kw {{
    font-weight: 800;
    color: #C9A84C;
    font-size: 46px;
    letter-spacing: -0.02em;
  }}

  /* Final sentence */
  .final-sentence {{
    font-family: 'Pretendard', 'Noto Sans KR', sans-serif;
    font-size: 44px;
    font-weight: 500;
    color: rgba(240, 235, 225, 0.82);
    line-height: 1.5;
    letter-spacing: -0.015em;
    word-break: keep-all;
  }}

  .final-sentence .accent {{
    color: #C9A84C;
    font-weight: 700;
  }}

  /* Bottom meta */
  .bottom-meta {{
    margin-top: 30px;
    display: flex;
    align-items: center;
    gap: 14px;
  }}

  .meta-rule {{
    width: 28px;
    height: 1px;
    background: rgba(201, 168, 76, 0.5);
  }}

  .meta-label {{
    font-family: 'Pretendard', 'Noto Sans KR', sans-serif;
    font-size: 19px;
    font-weight: 400;
    color: rgba(201, 168, 76, 0.55);
    letter-spacing: 0.12em;
  }}

  /* Slide indicator (top-right) */
  .slide-num {{
    position: absolute;
    top: 56px;
    right: 72px;
    z-index: 2;
    font-family: 'Pretendard', 'Noto Sans KR', sans-serif;
    font-size: 20px;
    font-weight: 400;
    color: rgba(201, 168, 76, 0.50);
    letter-spacing: 0.06em;
  }}
</style>
</head>
<body>
<div class="canvas">

  <!-- Slide number -->
  <div class="slide-num">3 / 5</div>

  <!-- TOP: Brand badge -->
  <div class="top-zone">
    <div class="brand-badge">
      <div class="badge-dot"></div>
      <span class="badge-text">서울대보험쌤</span>
    </div>
  </div>

  <!-- MIDDLE: Headline -->
  <div class="middle-zone">
    <div class="eyebrow">SOLUTION · A-3</div>
    <h1 class="headline">
      서울대 출신 팀장이<br>
      보험 영업을<br>
      <span class="hl-gold">다시 설계했다.</span>
    </h1>
    <div class="divider"></div>
  </div>

  <!-- BOTTOM: Subcopy -->
  <div class="bottom-zone">
    <div class="antithesis-block">
      <div class="antithesis-row">
        <span class="dim">감각이 아닌</span>
        <span class="sep">—</span>
        <span class="kw">데이터</span><span class="dim">로,</span>
      </div>
      <div class="antithesis-row">
        <span class="dim">경험이 아닌</span>
        <span class="sep">—</span>
        <span class="kw">시스템</span><span class="dim">으로.</span>
      </div>
    </div>
    <div class="final-sentence">
      <span class="accent">혼자 뛰지 않아도 되는 구조</span>를 만들었다.
    </div>
    <div class="bottom-meta">
      <div class="meta-rule"></div>
      <span class="meta-label">SEOUL NATIONAL UNIV. · INSURANCE SYSTEM DESIGN</span>
    </div>
  </div>

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


def write_html(bg_path: Path) -> Path:
    bg_url = f"file://{bg_path.resolve()}"
    html = HTML_TEMPLATE.format(bg_url=bg_url)
    HTML_PATH.write_text(html, encoding="utf-8")
    print(f"[HTML] 오버레이 작성: {HTML_PATH}")
    return HTML_PATH


# ── Step 3: Playwright screenshot ─────────────────────────────────────────────

def capture(html_path: Path, out_path: Path) -> None:
    print(f"[RENDER] 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_path.resolve()}", wait_until="networkidle")
            # Wait for fonts
            page.evaluate("async () => { await document.fonts.ready; }")
            page.wait_for_timeout(2000)
            out_path.parent.mkdir(parents=True, exist_ok=True)
            page.screenshot(
                path=str(out_path),
                type="png",
                clip={"x": 0, "y": 0, "width": 1080, "height": 1080},
            )
        finally:
            browser.close()
    size_kb = out_path.stat().st_size / 1024
    print(f"[RENDER] 완료: {out_path} ({size_kb:.0f} KB)")


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

if __name__ == "__main__":
    t_start = time.time()
    print("=" * 60)
    print("Pilot A-3 (Solution) — 하이브리드 이미지 생성")
    print(f"출력: {OUT_PATH}")
    print("=" * 60)

    bg = generate_background()
    html = write_html(bg)
    capture(html, OUT_PATH)

    elapsed = time.time() - t_start
    print(f"\n[완료] {OUT_PATH.name}  ({elapsed:.1f}초 총 소요)")
