#!/usr/bin/env python3
"""
#14 SVG-first 렌더링 파이프라인 배너 v2 생성 스크립트
hybrid-image 방식: Gemini 배경 + HTML 오버레이
출력: /home/jay/workspace/output/meta-ads/concept-catalog/14-svg-first/sample-v2.png
"""

from __future__ import annotations

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

import requests
from playwright.sync_api import sync_playwright

# 경로 설정
TOOL_DIR = Path(__file__).parent
OUTPUT_PATH = Path("/home/jay/workspace/output/meta-ads/concept-catalog/14-svg-first/sample-v2.png")
COPY_PATH = Path("/home/jay/workspace/output/meta-ads/concept-catalog/14-svg-first/14-svg-first-v2.png")
BG_PATH = TOOL_DIR / "output" / "v4-hybrid" / "bg_14_svg_first_v2.jpg"
HTML_PATH = TOOL_DIR / "output" / "v4-hybrid" / "overlay_14_svg_first_v2.html"

# Gemini API 설정
GEMINI_API_BASE = "https://generativelanguage.googleapis.com/v1beta"
GEMINI_SCOPE = "https://www.googleapis.com/auth/generative-language"

BG_PROMPT = (
    "Clean white background, minimal corporate design, faint light gray geometric lines as subtle texture, "
    "professional financial services aesthetic, no people, no text, soft shadow at edges, "
    "pure white dominant, barely visible gridlines, sophisticated business atmosphere, 1080x1080"
)


HTML_TEMPLATE = """<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<style>
  @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;700;800;900&display=swap');

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

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

  .canvas {
    width: 1080px;
    height: 1080px;
    position: relative;
    background: #FFFFFF;
    background-image: url('{{BG_URL}}');
    background-size: cover;
    background-position: center;
  }

  .content {
    position: absolute;
    top: 0;
    left: 0;
    width: 1080px;
    height: 1080px;
    padding: 60px 72px;
    display: flex;
    flex-direction: column;
  }

  /* 상단 영역 */
  .top-section {
    flex: 0 0 auto;
  }

  .top-label {
    font-size: 44px;
    font-weight: 700;
    color: #1A3A5C;
    line-height: 1.2;
    letter-spacing: -0.5px;
  }

  .sub-label {
    font-size: 40px;
    font-weight: 400;
    color: #888888;
    margin-top: 8px;
    line-height: 1.2;
    letter-spacing: -0.3px;
  }

  .divider {
    width: 100%;
    height: 2px;
    background-color: #1A3A5C;
    margin-top: 24px;
    margin-bottom: 0;
  }

  /* 중간 메인 영역 */
  .middle-section {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    justify-content: center;
    padding-top: 20px;
  }

  .headline {
    font-size: 96px;
    font-weight: 800;
    color: #1A3A5C;
    line-height: 1.15;
    letter-spacing: -2px;
    word-break: keep-all;
  }

  .sub-copy {
    font-size: 72px;
    font-weight: 700;
    color: #2D6A4F;
    margin-top: 32px;
    line-height: 1.2;
    letter-spacing: -1.5px;
    word-break: keep-all;
  }

  .support-text {
    font-size: 44px;
    font-weight: 400;
    color: #555555;
    margin-top: 28px;
    line-height: 1.3;
    letter-spacing: -0.5px;
  }

  /* 하단 영역 */
  .bottom-section {
    flex: 0 0 auto;
    padding-bottom: 0px;
  }

  .urgent-badge {
    display: inline-block;
    font-size: 40px;
    font-weight: 600;
    color: #E53935;
    background: #FFF0F0;
    border: 2px solid #E53935;
    border-radius: 6px;
    padding: 8px 20px;
    line-height: 1.4;
    letter-spacing: -0.5px;
    margin-bottom: 28px;
    word-break: keep-all;
  }

  .cta-button {
    display: inline-block;
    font-size: 48px;
    font-weight: 700;
    color: #FFFFFF;
    background: #1A3A5C;
    border-radius: 8px;
    padding: 22px 60px;
    line-height: 1.2;
    letter-spacing: -0.5px;
    cursor: pointer;
  }
</style>
</head>
<body>
<div class="canvas">
  <div class="content">

    <!-- 상단 라벨 영역 -->
    <div class="top-section">
      <div class="top-label">T.O.P 사업단</div>
      <div class="sub-label">인카금융서비스 코스닥 상장</div>
      <div class="divider"></div>
    </div>

    <!-- 중간 메인 카피 영역 -->
    <div class="middle-section">
      <div class="headline">신입 최대<br>1,000만원</div>
      <div class="sub-copy">경력직 직전연봉 50%</div>
      <div class="support-text">지금이 기회입니다</div>
    </div>

    <!-- 하단 배지 + CTA -->
    <div class="bottom-section">
      <div class="urgent-badge">정착지원금 2026.7월 변경 예정</div>
      <br>
      <div class="cta-button">지금 상담 신청하기</div>
    </div>

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


def get_gemini_token() -> str:
    """Gemini SA 토큰 획득"""
    sys.path.insert(0, str(TOOL_DIR))
    import gcloud_auth
    return gcloud_auth.get_service_account_token(GEMINI_SCOPE)


def generate_background(token: str) -> None:
    """Gemini API로 배경 이미지 생성"""
    if BG_PATH.exists():
        print(f"[배경] 기존 배경 이미지 사용: {BG_PATH}")
        return

    print("[배경] Gemini AI로 배경 생성 중...")
    model_id = "gemini-3.1-flash-image-preview"
    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"]},
    }

    start = time.time()
    response = requests.post(url, headers=headers, json=payload, timeout=300)

    # fallback 시도
    if response.status_code in (400, 403, 404):
        print(f"[배경] 모델 {model_id} 실패 (HTTP {response.status_code}), fallback 시도...")
        for fallback_model in [
            "gemini-3-pro-image-preview",
            "gemini-2.5-flash-image",
        ]:
            url2 = f"{GEMINI_API_BASE}/models/{fallback_model}:generateContent"
            response = requests.post(url2, headers=headers, json=payload, timeout=300)
            if response.status_code == 200:
                print(f"[배경] Fallback 성공: {fallback_model}")
                break

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

    data = response.json()
    candidates = data.get("candidates", [])
    if not candidates:
        raise RuntimeError(f"배경 생성 실패: candidates 없음. 응답: {json.dumps(data)[:300]}")

    parts = candidates[0].get("content", {}).get("parts", [])
    image_part = None
    for part in parts:
        if "inlineData" in part:
            image_part = part
            break

    if image_part is None:
        # 이미지가 없으면 흰색 배경 사용
        print("[배경] 이미지 데이터 없음 — 흰색 배경 사용")
        return

    mime_type = image_part["inlineData"].get("mimeType", "image/jpeg")
    image_bytes = base64.b64decode(image_part["inlineData"]["data"])
    BG_PATH.parent.mkdir(parents=True, exist_ok=True)
    BG_PATH.write_bytes(image_bytes)
    print(f"[배경] 완료: {BG_PATH.name} ({len(image_bytes):,} bytes, {elapsed:.1f}초)")


def render_html_to_png(bg_url: str) -> None:
    """Playwright로 HTML 오버레이를 PNG로 렌더링"""
    print("[HTML] 오버레이 HTML 생성 중...")
    html_content = HTML_TEMPLATE.replace("{{BG_URL}}", bg_url)
    HTML_PATH.parent.mkdir(parents=True, exist_ok=True)
    HTML_PATH.write_text(html_content, encoding="utf-8")

    print("[Playwright] 브라우저 렌더링 중...")
    with sync_playwright() as p:
        browser = p.chromium.launch(
            args=["--font-render-hinting=none", "--disable-font-subpixel-positioning"]
        )
        try:
            page = browser.new_page(viewport={"width": 1080, "height": 1080})

            # 한글 폰트 로드
            try:
                pretendard_dir = Path("/home/jay/.local/share/fonts/Pretendard")
                if pretendard_dir.exists():
                    for font_file in pretendard_dir.glob("*.ttf"):
                        weight = "400"
                        name = font_file.stem
                        if "Bold" in name or "700" in name:
                            weight = "700"
                        elif "ExtraBold" in name or "800" in name:
                            weight = "800"
                        elif "Black" in name or "900" in name:
                            weight = "900"
                        page.add_init_script(f"""
                            const style = document.createElement('style');
                            style.textContent = `
                              @font-face {{
                                font-family: 'Pretendard';
                                src: url('file://{font_file}') format('truetype');
                                font-weight: {weight};
                                font-style: normal;
                              }}
                            `;
                            document.head.appendChild(style);
                        """)
            except Exception as e:
                print(f"[폰트] Pretendard 로드 건너뜀: {e}")

            html_file_url = f"file://{HTML_PATH.resolve()}"
            page.goto(html_file_url, 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", full_page=False)
            print(f"[캡처] {OUTPUT_PATH}")
        finally:
            browser.close()


def main() -> None:
    print("=" * 60)
    print("#14 SVG-first 배너 v2 생성 시작 (hybrid-image)")
    print("=" * 60)

    # 1. Gemini 토큰 획득
    print("\n[1/4] Gemini 인증 토큰 획득...")
    try:
        token = get_gemini_token()
        print(f"[인증] 토큰 획득 성공 (길이: {len(token)} chars)")
    except Exception as e:
        print(f"[경고] Gemini 토큰 획득 실패: {e}")
        print("[경고] 흰색 배경으로 진행합니다...")
        token = None

    # 2. 배경 이미지 생성
    print("\n[2/4] 배경 이미지 생성...")
    if token:
        try:
            generate_background(token)
        except Exception as e:
            print(f"[경고] 배경 생성 실패: {e}")
            print("[경고] 흰색 배경으로 진행...")

    # 배경 URL 결정
    if BG_PATH.exists():
        bg_url = f"file://{BG_PATH.resolve()}"
    else:
        bg_url = ""  # 흰색 배경 (CSS에서 처리)
        print("[배경] 흰색 배경 CSS 사용")

    # 3. HTML 오버레이 렌더링
    print("\n[3/4] HTML 오버레이 렌더링...")
    render_html_to_png(bg_url)

    # 4. 파일 복사
    print(f"\n[4/4] 파일 복사: {COPY_PATH}")
    shutil.copy2(str(OUTPUT_PATH), str(COPY_PATH))

    # 결과 출력
    size_kb = OUTPUT_PATH.stat().st_size / 1024
    print("\n" + "=" * 60)
    print("완료!")
    print(f"  sample-v2.png    : {OUTPUT_PATH} ({size_kb:.0f} KB)")
    print(f"  14-svg-first-v2  : {COPY_PATH}")
    print("=" * 60)


if __name__ == "__main__":
    main()
