#!/usr/bin/env python3
"""Concept 38: Cannes Grid Opportunity — 프로덕션 배너 생성
- c38-1200x628.png  (가로형 Meta/Google 광고)
- c38-1200x1200.png (정사각형 Meta 광고)
- c38-1200x628.html
- c38-1200x1200.html

캠페인: TOP사업단 리쿠르팅 마케팅 v2.0
디자인: 다크 배경 + 황금 그리드 구조 + 황금빛 스포트라이트 (Cannes-award aesthetic)
"""

from __future__ import annotations

import base64
import json
import sys
import time
from pathlib import Path

import requests
from playwright.sync_api import sync_playwright

# ── 경로 설정 ────────────────────────────────────────────────────────────────
BASE_DIR = Path(__file__).parent
OUTPUT_DIR = Path("/home/jay/workspace/output/meta-ads/production-banners/38-cannes-grid-opportunity")
TMP_DIR = BASE_DIR / "output" / "v4-hybrid"
BG_PATH = TMP_DIR / "bg_c38_cannes.jpg"

# Gemini API 설정
GEMINI_API_BASE = "https://generativelanguage.googleapis.com/v1beta"
MODEL_ID = "gemini-3-pro-image-preview"
FALLBACK_MODEL_ID = "gemini-3.1-flash-image-preview"

# ── 배경 프롬프트 ─────────────────────────────────────────────────────────────
BG_PROMPT = (
    "Abstract golden spotlight on very dark background. "
    "Subtle geometric grid pattern lines in deep charcoal — thin gold lines forming a precise grid, "
    "like a luxury advertising layout guide. "
    "Central warm golden glow radiating outward, fading to deep near-black edges (#1A1A1A to pure black). "
    "Metallic gold dust particles suspended in the air, catching light. "
    "The center has a soft warm amber-gold luminous halo effect. "
    "Premium luxury advertising aesthetic — like a Cannes Lions award-winning campaign background. "
    "No people. No text. No logos. No UI elements. "
    "Photorealistic render quality. "
    "The grid lines are very subtle — barely visible, like watermarks on expensive paper. "
    "Overall mood: sophisticated, premium, aspirational, dark luxury."
)


# ── Gemini 배경 생성 ──────────────────────────────────────────────────────────

def get_auth_token() -> str:
    """gcloud_auth 모듈로 Bearer 토큰을 획득합니다."""
    sys.path.insert(0, str(BASE_DIR))
    import gcloud_auth
    return gcloud_auth.get_access_token()


def _call_model(token: str, api_key: str | None, model: str, payload: dict) -> requests.Response:
    """SA 토큰 우선, 실패 시 API 키로 Gemini 호출."""
    url_bearer = f"{GEMINI_API_BASE}/models/{model}:generateContent"
    headers_bearer = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
    resp = requests.post(url_bearer, headers=headers_bearer, json=payload, timeout=300)
    if resp.status_code == 200:
        return resp
    # API 키 폴백
    if api_key:
        url_key = f"{GEMINI_API_BASE}/models/{model}:generateContent?key={api_key}"
        headers_key = {"Content-Type": "application/json"}
        return requests.post(url_key, headers=headers_key, json=payload, timeout=300)
    return resp


def generate_background() -> Path:
    """Gemini API로 배경 이미지를 생성하고 경로를 반환합니다."""
    if BG_PATH.exists() and BG_PATH.stat().st_size > 50_000:
        print(f"[배경] 기존 배경 이미지 재사용: {BG_PATH}")
        return BG_PATH

    print("[배경] Gemini API로 배경 이미지 생성 중...")
    token = get_auth_token()
    sys.path.insert(0, str(BASE_DIR))
    import gcloud_auth as ga
    api_key = ga.get_api_key("GEMINI_API_KEY")

    payload = {
        "contents": [{"parts": [{"text": BG_PROMPT}]}],
        "generationConfig": {"responseModalities": ["IMAGE", "TEXT"]},
    }

    models_to_try = [MODEL_ID, FALLBACK_MODEL_ID]
    last_error = None

    for attempt, model in enumerate(models_to_try, 1):
        print(f"  시도 {attempt}: 모델={model}")
        try:
            resp = _call_model(token, api_key, model, payload)
        except Exception as e:
            last_error = str(e)
            print(f"  요청 실패: {e}")
            continue

        if resp.status_code in (400, 403, 404):
            print(f"  모델 접근 실패 ({resp.status_code}: {resp.text[:200]})")
            last_error = f"HTTP {resp.status_code}"
            continue

        if resp.status_code != 200:
            print(f"  HTTP {resp.status_code}: {resp.text[:300]}")
            last_error = f"HTTP {resp.status_code}"
            continue

        data = resp.json()
        candidates = data.get("candidates", [])
        if not candidates:
            print(f"  응답에 candidates 없음: {json.dumps(data)[:200]}")
            last_error = "No 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:
            print(f"  이미지 없음. parts: {[list(p.keys()) for p in parts]}")
            last_error = "No inlineData"
            continue

        mime = image_part["inlineData"].get("mimeType", "image/jpeg")
        img_bytes = base64.b64decode(image_part["inlineData"]["data"])
        BG_PATH.write_bytes(img_bytes)
        print(f"  [배경] 저장 완료: {BG_PATH} ({len(img_bytes):,} bytes, mime={mime})")
        return BG_PATH

    raise RuntimeError(f"배경 이미지 생성 실패: {last_error}")


# ── HTML 템플릿 ───────────────────────────────────────────────────────────────

def make_html_1200x628(bg_path: Path) -> str:
    """1200x628 가로형 배너 HTML 생성.

    디자인: Cannes 그리드-오퍼튜니티
    - 다크 배경 + Gemini 스포트라이트 이미지 (우측 40%)
    - 좌측-to-우측 그라데이션 오버레이: 다크 샤코올 좌측 60% 커버
    - 황금 수평 그리드 액센트라인
    - T.O.P 사업단 브랜드 뱃지 (골드)
    - 헤드라인 + 골드 키워드 하이라이트
    - 서브카피 + 혜택 텍스트
    - CTA 버튼 (골드 그라데이션)
    """
    bg_uri = f"file://{bg_path.resolve()}"
    return f"""<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
  @font-face {{
    font-family: 'Pretendard';
    src: url('file:///home/jay/.local/share/fonts/Pretendard/Pretendard-Bold.otf') format('opentype');
    font-weight: 700;
  }}
  @font-face {{
    font-family: 'Pretendard';
    src: url('file:///home/jay/.local/share/fonts/Pretendard/Pretendard-ExtraBold.otf') format('opentype');
    font-weight: 800;
  }}
  @font-face {{
    font-family: 'Pretendard';
    src: url('file:///home/jay/.local/share/fonts/Pretendard/Pretendard-Medium.otf') format('opentype');
    font-weight: 500;
  }}
  @font-face {{
    font-family: 'Pretendard';
    src: url('file:///home/jay/.local/share/fonts/Pretendard/Pretendard-SemiBold.otf') format('opentype');
    font-weight: 600;
  }}
  * {{ margin: 0; padding: 0; box-sizing: border-box; }}

  body {{
    width: 1200px;
    height: 628px;
    overflow: hidden;
    font-family: 'Pretendard', 'Noto Sans KR', sans-serif;
    background: #1A1A1A;
  }}

  .container {{
    position: relative;
    width: 1200px;
    height: 628px;
    overflow: hidden;
    background: #1A1A1A;
  }}

  /* 배경 이미지: 전체 (우측 스포트라이트 강조) */
  .bg-image {{
    position: absolute;
    inset: 0;
    background-image: url('{bg_uri}');
    background-size: cover;
    background-position: center right;
  }}

  /* 좌→우 다크 그라데이션 오버레이 */
  .gradient-overlay {{
    position: absolute;
    inset: 0;
    background: linear-gradient(
      to right,
      rgba(26,26,26,0.97) 0%,
      rgba(26,26,26,0.94) 35%,
      rgba(26,26,26,0.82) 52%,
      rgba(26,26,26,0.42) 70%,
      rgba(26,26,26,0.10) 85%,
      transparent 100%
    );
  }}

  /* 황금 그리드 라인 — 수평 */
  .grid-line-h1 {{
    position: absolute;
    top: 120px;
    left: 0;
    right: 0;
    height: 1px;
    background: linear-gradient(to right, rgba(201,168,76,0.18) 0%, rgba(201,168,76,0.06) 65%, transparent 100%);
  }}
  .grid-line-h2 {{
    position: absolute;
    top: 510px;
    left: 0;
    right: 0;
    height: 1px;
    background: linear-gradient(to right, rgba(201,168,76,0.18) 0%, rgba(201,168,76,0.06) 65%, transparent 100%);
  }}

  /* 황금 세로 액센트바 */
  .accent-bar {{
    position: absolute;
    top: 60px;
    left: 0;
    width: 3px;
    height: 508px;
    background: linear-gradient(to bottom, transparent, #C9A84C 15%, #D4B87A 50%, #C9A84C 85%, transparent);
  }}

  /* 텍스트 영역: 좌측 62% */
  .text-area {{
    position: absolute;
    left: 0;
    top: 0;
    width: 62%;
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding: 44px 52px 44px 56px;
    gap: 0;
  }}

  /* 브랜드 텍스트 */
  .brand {{
    font-size: 40px;
    font-weight: 600;
    color: #C9A84C;
    letter-spacing: 1px;
    margin-bottom: 22px;
    opacity: 0.9;
    word-break: keep-all;
  }}

  /* 헤드라인 */
  .headline {{
    font-size: 54px;
    font-weight: 700;
    color: #FFFFFF;
    line-height: 1.3;
    letter-spacing: -0.8px;
    margin-bottom: 18px;
    word-break: keep-all;
  }}
  .headline .gold {{
    color: #C9A84C;
  }}

  /* 서브카피 구분선 */
  .divider {{
    width: 48px;
    height: 2px;
    background: #C9A84C;
    margin-bottom: 18px;
    border-radius: 1px;
  }}

  /* 서브카피 */
  .sub-copy {{
    font-size: 44px;
    font-weight: 700;
    color: #C9A84C;
    letter-spacing: -0.5px;
    margin-bottom: 22px;
    word-break: keep-all;
  }}

  /* 혜택 텍스트 */
  .benefits {{
    font-size: 40px;
    font-weight: 500;
    color: rgba(255,255,255,0.82);
    letter-spacing: -0.3px;
    margin-bottom: 28px;
    word-break: keep-all;
    white-space: nowrap;
  }}
  .benefits .sep {{
    color: rgba(201,168,76,0.55);
    margin: 0 10px;
  }}

  /* CTA 버튼 */
  .cta-btn {{
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, #C9A84C 0%, #D4B87A 100%);
    color: #1A1A1A;
    font-size: 40px;
    font-weight: 700;
    height: 58px;
    padding: 0 32px;
    border-radius: 6px;
    letter-spacing: -0.3px;
    box-shadow: 0 4px 20px rgba(201,168,76,0.38);
    white-space: nowrap;
    width: fit-content;
  }}
</style>
</head>
<body>
<div class="container">
  <!-- 배경 이미지 -->
  <div class="bg-image"></div>
  <!-- 다크 그라데이션 오버레이 -->
  <div class="gradient-overlay"></div>
  <!-- 황금 그리드 라인 -->
  <div class="grid-line-h1"></div>
  <div class="grid-line-h2"></div>
  <!-- 황금 세로 액센트바 -->
  <div class="accent-bar"></div>
  <!-- 텍스트 영역 -->
  <div class="text-area">
    <div class="brand">T.O.P 사업단</div>
    <div class="headline">열심히는 하는데,<br>월급은 <span class="gold">제자리걸음?</span></div>
    <div class="divider"></div>
    <div class="sub-copy">이 자리만 다릅니다.</div>
    <div class="benefits">신입 정착지원금 최대 1,000만원<span class="sep">|</span>경력직 직전연봉 50%까지 지원</div>
    <div class="cta-btn">지금 상담 신청하기 →</div>
  </div>
</div>
</body>
</html>"""


def make_html_1200x1200(bg_path: Path) -> str:
    """1200x1200 정사각형 배너 HTML 생성.

    디자인: Cannes 그리드-오퍼튜니티 (중앙 패널 구조)
    - 다크 배경 + Gemini 스포트라이트 (중앙 글로우)
    - 다크 오버레이 (opacity 0.58)
    - 중앙 크림 패널 (rgba(255,248,231,0.82)) — knowhow Template B
    - 황금 그리드 장식 라인
    - T.O.P 사업단 골드 뱃지
    - 헤드라인 다크 텍스트 + 골드 키워드
    - 서브카피 + 혜택 + CTA
    """
    bg_uri = f"file://{bg_path.resolve()}"
    return f"""<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
  @font-face {{
    font-family: 'Pretendard';
    src: url('file:///home/jay/.local/share/fonts/Pretendard/Pretendard-Bold.otf') format('opentype');
    font-weight: 700;
  }}
  @font-face {{
    font-family: 'Pretendard';
    src: url('file:///home/jay/.local/share/fonts/Pretendard/Pretendard-ExtraBold.otf') format('opentype');
    font-weight: 800;
  }}
  @font-face {{
    font-family: 'Pretendard';
    src: url('file:///home/jay/.local/share/fonts/Pretendard/Pretendard-Medium.otf') format('opentype');
    font-weight: 500;
  }}
  @font-face {{
    font-family: 'Pretendard';
    src: url('file:///home/jay/.local/share/fonts/Pretendard/Pretendard-SemiBold.otf') format('opentype');
    font-weight: 600;
  }}
  * {{ margin: 0; padding: 0; box-sizing: border-box; }}

  body {{
    width: 1200px;
    height: 1200px;
    overflow: hidden;
    font-family: 'Pretendard', 'Noto Sans KR', sans-serif;
    background: #1A1A1A;
  }}

  .container {{
    position: relative;
    width: 1200px;
    height: 1200px;
    overflow: hidden;
    background: #1A1A1A;
  }}

  /* 배경 이미지: 전체 (중앙 스포트라이트) */
  .bg-image {{
    position: absolute;
    inset: 0;
    background-image: url('{bg_uri}');
    background-size: cover;
    background-position: center center;
  }}

  /* 다크 오버레이 (0.58 opacity) */
  .dark-overlay {{
    position: absolute;
    inset: 0;
    background: rgba(26,26,26,0.58);
  }}

  /* 황금 그리드 라인 — 수평 장식 */
  .grid-line-top {{
    position: absolute;
    top: 88px;
    left: 80px;
    right: 80px;
    height: 1px;
    background: rgba(201,168,76,0.20);
  }}
  .grid-line-bottom {{
    position: absolute;
    bottom: 88px;
    left: 80px;
    right: 80px;
    height: 1px;
    background: rgba(201,168,76,0.20);
  }}
  /* 모서리 황금 장식 */
  .corner-tl {{
    position: absolute;
    top: 60px;
    left: 60px;
    width: 40px;
    height: 40px;
    border-top: 2px solid rgba(201,168,76,0.55);
    border-left: 2px solid rgba(201,168,76,0.55);
  }}
  .corner-tr {{
    position: absolute;
    top: 60px;
    right: 60px;
    width: 40px;
    height: 40px;
    border-top: 2px solid rgba(201,168,76,0.55);
    border-right: 2px solid rgba(201,168,76,0.55);
  }}
  .corner-bl {{
    position: absolute;
    bottom: 60px;
    left: 60px;
    width: 40px;
    height: 40px;
    border-bottom: 2px solid rgba(201,168,76,0.55);
    border-left: 2px solid rgba(201,168,76,0.55);
  }}
  .corner-br {{
    position: absolute;
    bottom: 60px;
    right: 60px;
    width: 40px;
    height: 40px;
    border-bottom: 2px solid rgba(201,168,76,0.55);
    border-right: 2px solid rgba(201,168,76,0.55);
  }}

  /* 중앙 크림 패널 (Template B 구조) */
  .central-panel {{
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 920px;
    padding: 60px 64px 56px 64px;
    background: rgba(255,248,231,0.82);
    border-radius: 8px;
    backdrop-filter: blur(6px);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 28px;
    text-align: center;
    /* 황금 테두리 */
    border: 1px solid rgba(201,168,76,0.28);
    box-shadow: 0 0 80px rgba(201,168,76,0.12), 0 20px 60px rgba(26,26,26,0.30);
  }}

  /* 브랜드 뱃지 */
  .brand-badge {{
    display: inline-flex;
    align-items: center;
    background: linear-gradient(135deg, #C9A84C 0%, #D4B87A 100%);
    color: #1A1A1A;
    font-size: 40px;
    font-weight: 700;
    height: 52px;
    padding: 0 24px;
    border-radius: 6px;
    letter-spacing: 0.5px;
    width: fit-content;
    white-space: nowrap;
  }}

  /* 헤드라인 */
  .headline {{
    font-size: 60px;
    font-weight: 700;
    color: #1A1A1A;
    line-height: 1.3;
    letter-spacing: -1px;
    text-align: center;
    word-break: keep-all;
  }}
  .headline .gold {{
    color: #A07828;
  }}

  /* 구분선 */
  .divider {{
    width: 56px;
    height: 2px;
    background: linear-gradient(to right, #C9A84C, #D4B87A);
    border-radius: 1px;
  }}

  /* 서브카피 */
  .sub-copy {{
    font-size: 48px;
    font-weight: 700;
    color: #A07828;
    letter-spacing: -0.5px;
    word-break: keep-all;
  }}

  /* 혜택 텍스트 */
  .benefits {{
    font-size: 38px;
    font-weight: 500;
    color: #3D3D3D;
    letter-spacing: -0.3px;
    word-break: keep-all;
    text-align: center;
    line-height: 1.6;
  }}
  .benefits .sep {{
    display: block;
    width: 100%;
    height: 0;
  }}

  /* CTA 버튼 */
  .cta-btn {{
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, #C9A84C 0%, #D4B87A 100%);
    color: #1A1A1A;
    font-size: 48px;
    font-weight: 700;
    height: 72px;
    padding: 0 48px;
    border-radius: 6px;
    letter-spacing: -0.3px;
    box-shadow: 0 6px 24px rgba(201,168,76,0.42);
    white-space: nowrap;
    width: fit-content;
    margin-top: 4px;
  }}
</style>
</head>
<body>
<div class="container">
  <!-- 배경 이미지 -->
  <div class="bg-image"></div>
  <!-- 다크 오버레이 -->
  <div class="dark-overlay"></div>
  <!-- 황금 그리드 장식 -->
  <div class="grid-line-top"></div>
  <div class="grid-line-bottom"></div>
  <!-- 코너 장식 -->
  <div class="corner-tl"></div>
  <div class="corner-tr"></div>
  <div class="corner-bl"></div>
  <div class="corner-br"></div>
  <!-- 중앙 크림 패널 -->
  <div class="central-panel">
    <div class="brand-badge">T.O.P 사업단</div>
    <div class="headline">열심히는 하는데,<br>월급은 <span class="gold">제자리걸음?</span></div>
    <div class="divider"></div>
    <div class="sub-copy">이 자리만 다릅니다.</div>
    <div class="benefits">신입 정착지원금 최대 1,000만원<span class="sep"></span>경력직 직전연봉 50%까지 지원</div>
    <div class="cta-btn">지금 상담 신청하기 →</div>
  </div>
</div>
</body>
</html>"""


# ── Playwright 캡처 ───────────────────────────────────────────────────────────

def capture_html_to_png(html_content: str, width: int, height: int, output_path: Path, html_save_path: Path | None = None) -> None:
    """HTML을 Playwright로 캡처하여 PNG로 저장합니다."""
    tmp_html = TMP_DIR / f"_tmp_c38_{width}x{height}.html"
    tmp_html.write_text(html_content, encoding="utf-8")

    # HTML 파일도 저장
    if html_save_path:
        html_save_path.parent.mkdir(parents=True, exist_ok=True)
        html_save_path.write_text(html_content, encoding="utf-8")
        print(f"  [HTML] {html_save_path}")

    with sync_playwright() as p:
        browser = p.chromium.launch()
        try:
            page = browser.new_page(viewport={"width": width, "height": height})
            page.goto(f"file://{tmp_html.resolve()}", wait_until="networkidle")
            page.wait_for_timeout(2000)  # 폰트 로딩 대기
            output_path.parent.mkdir(parents=True, exist_ok=True)
            page.screenshot(path=str(output_path), type="png", clip={
                "x": 0, "y": 0, "width": width, "height": height
            })
            size_kb = output_path.stat().st_size / 1024
            print(f"  [PNG] {output_path} ({size_kb:.0f} KB)")
        finally:
            browser.close()


# ── 메인 ─────────────────────────────────────────────────────────────────────

def main() -> None:
    print("=" * 60)
    print("Concept 38: Cannes Grid Opportunity — 배너 생성 시작")
    print("=" * 60)

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

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

    # 2. 1200x628 가로형 배너
    print("\n[1200x628] 가로형 배너 생성 중...")
    html_628 = make_html_1200x628(bg_path)
    capture_html_to_png(
        html_content=html_628,
        width=1200,
        height=628,
        output_path=OUTPUT_DIR / "c38-1200x628.png",
        html_save_path=OUTPUT_DIR / "c38-1200x628.html",
    )

    # 3. 1200x1200 정사각형 배너
    print("\n[1200x1200] 정사각형 배너 생성 중...")
    html_1200 = make_html_1200x1200(bg_path)
    capture_html_to_png(
        html_content=html_1200,
        width=1200,
        height=1200,
        output_path=OUTPUT_DIR / "c38-1200x1200.png",
        html_save_path=OUTPUT_DIR / "c38-1200x1200.html",
    )

    print("\n" + "=" * 60)
    print("완료!")
    print(f"출력 디렉토리: {OUTPUT_DIR}")
    for f in OUTPUT_DIR.iterdir():
        size_kb = f.stat().st_size / 1024
        print(f"  {f.name}: {size_kb:.0f} KB")
    print("=" * 60)


if __name__ == "__main__":
    main()
