#!/usr/bin/env python3
"""Cell-8 서울대보험쌤 × 관리자/조직 비전 배너 생성 (v3.2 최종본)
- meta-feed-1080x1080.png  (Template B: 전체 배경 + 크림 패널)
- google-resp-1200x628.png (Template A: 좌측 텍스트 + 우측 배경)

카피 v3.2:
  Headline   : "1200% 룰 후엔 지점장 문, 좁아집니다"
  Sub-copy   : "본부 5개 | 지점 10개 | 200명+ 함께"
  Urgency    : "사무실 개설비 지원 | 조직 구축 시스템"
  Badge      : "서울대보험쌤"
  CTA        : "지점장 이직 상담 신청 →"

디자인 시스템: Cell-7 동일 (컬러만 골드 → 카라멜로 전환)
  주조색: #3E2723 (딥 브라운)
  강조색: #A0522D (카라멜)
  보조강조: #C07540
"""

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 CTA_MIN_PX, FONT_DIR, WORKSPACE_ROOT

# ── 디자인 토큰 ──
_SIZE_38PX = 38
_CTA_PX = CTA_MIN_PX
_SIZE_44PX = 44
_SIZE_48PX = 48
_SIZE_58PX = 58
_SIZE_60PX = 60
_LH_48PX = 48
_LH_52PX = 52
_LH_56PX = 56
_LH_76PX = 76
_LH_1_2 = 1.2
_LH_1_25 = 1.25


# ── 경로 설정 ─────────────────────────────────────────────────────────────────
BASE_DIR = WORKSPACE_ROOT / "tools/ai-image-gen"
OUTPUT_DIR = WORKSPACE_ROOT / "output/banners/cell-8-snu-leader"
FALLBACK_BG = WORKSPACE_ROOT / "output/meta-ads/concept-catalog/45-oneshow-finance-luxury/bg.jpg"

BG_1080_PATH = OUTPUT_DIR / "bg-cell8-1080.png"
BG_1200_PATH = OUTPUT_DIR / "bg-cell8-1200.png"

GEMINI_API_BASE = "https://generativelanguage.googleapis.com/v1beta"
GEMINI_MODEL = "gemini-2.0-flash-preview-image-generation"
GEMINI_FALLBACK_MODEL = "gemini-2.0-flash-exp"


# ── 배경 프롬프트 ──────────────────────────────────────────────────────────────

PROMPT_1080 = (
    "Modern meeting room with warm natural lighting, organized documents and "
    "organizational charts on table, whiteboard with handwritten notes in background, "
    "professional but warm atmosphere, morning sunlight through window, warm brown "
    "and amber tones, intimate professional space, no people, no text, no logos. "
    "Square 1:1 format, ultra-realistic photograph."
)

PROMPT_1200 = (
    "Wide angle professional office space with whiteboard showing organizational "
    "structure diagram, warm desk lamp casting golden light, documents on dark wooden "
    "table, certificates and framed awards on wall, cozy professional atmosphere, "
    "warm brown and amber tones, no people, no text, no logos. "
    "Wide landscape 1.91:1 format, ultra-realistic photograph."
)


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

def get_api_key() -> str:
    sys.path.insert(0, str(BASE_DIR))
    import gcloud_auth
    return gcloud_auth.get_api_key("GEMINI_API_KEY") or "AIzaSyDEy7IcOoTbQsI4nxfPOw3ZFbYqEL_PgFU"


def generate_gemini_background(prompt: str, out_path: Path, label: str) -> bool:
    """Gemini API로 배경 이미지 생성. 성공 시 True 반환."""
    if out_path.exists() and out_path.stat().st_size > 30_000:
        print(f"[{label}] 기존 배경 재사용: {out_path}")
        return True

    api_key = get_api_key()
    payload = {
        "contents": [{"parts": [{"text": prompt}]}],
        "generationConfig": {"responseModalities": ["IMAGE", "TEXT"]},
    }

    models = [GEMINI_MODEL, GEMINI_FALLBACK_MODEL, "gemini-1.5-flash"]
    for model in models:
        url = f"{GEMINI_API_BASE}/models/{model}:generateContent?key={api_key}"
        print(f"[{label}] Gemini 요청 중 (모델: {model})...")
        try:
            resp = requests.post(url, json=payload, timeout=120)
        except Exception as e:
            print(f"  요청 예외: {e}")
            continue

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

        data = resp.json()
        candidates = data.get("candidates", [])
        if not candidates:
            print(f"  candidates 없음")
            continue

        parts = candidates[0].get("content", {}).get("parts", [])
        image_part = next((p for p in parts if "inlineData" in p), None)
        if not image_part:
            print(f"  inlineData 없음. parts keys: {[list(p.keys()) for p in parts]}")
            continue

        img_bytes = base64.b64decode(image_part["inlineData"]["data"])
        out_path.write_bytes(img_bytes)
        print(f"  [OK] {out_path} ({len(img_bytes):,} bytes)")
        return True

    return False


# ── HTML 1080x1080 ─────────────────────────────────────────────────────────────
# 브랜드: 카라멜(#A0522D) 강조, "좁아집니다" 카라멜 강조
# 패널: 크림 반투명 + 브라운 오버레이

HTML_1080 = f"""\
<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=1080">
  <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-SemiBold.otf') format('opentype'); font-weight: 600; }}
    @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; }}

    *, *::before, *::after {{ box-sizing: border-box; margin: 0; padding: 0; }}
    html, body {{ width: 1080px; height: 1080px; overflow: hidden; font-family: 'Pretendard', sans-serif; word-break: keep-all; }}

    .canvas {{ position: relative; width: 1080px; height: 1080px; overflow: hidden; }}
    .bg-image {{ position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: center; }}
    .dark-overlay {{ position: absolute; inset: 0; background: rgba(62, 39, 35, 0.58); }}

    .text-panel {{
      position: absolute;
      top: 50%; left: 50%;
      transform: translate(-50%, -50%);
      width: 860px;
      padding: 56px 48px;
      background: rgba(255, 248, 231, 0.82);
      border-radius: 12px;
      backdrop-filter: blur(4px);
      box-shadow: 0 8px 32px rgba(62,39,35,0.25);
      display: flex; flex-direction: column;
      align-items: center;
      gap: 28px; text-align: center;
    }}

    .badge {{
      display: inline-block;
      background: #A0522D;
      color: #FFFFFF;
      font-size: {_CTA_PX}px; font-weight: 700;
      height: 52px; line-height: {_LH_52PX}px;
      padding: 0 24px;
      border-radius: 6px;
      white-space: nowrap;
      letter-spacing: -0.03em;
    }}

    .headline {{
      font-size: {_SIZE_60PX}px; font-weight: 700;
      color: #3E2723; line-height: {_LH_1_25};
      letter-spacing: -1.5px;
    }}
    .headline .accent {{ color: #A0522D; }}

    .sub-copy {{
      font-size: {_SIZE_44PX}px; font-weight: 500;
      color: #7A3D1F;
      white-space: nowrap;
      letter-spacing: -0.02em;
    }}

    .urgency {{
      font-size: {_CTA_PX}px; font-weight: 600;
      color: #7A3D1F;
      white-space: nowrap;
      letter-spacing: -0.02em;
    }}

    .cta-btn {{
      display: inline-block;
      background: linear-gradient(135deg, #A0522D 0%, #C07540 100%);
      color: #FFFFFF;
      font-size: {_SIZE_48PX}px; font-weight: 700;
      height: 76px; line-height: {_LH_76PX}px;
      padding: 0 40px;
      min-width: 360px;
      width: auto;
      border-radius: 6px;
      box-shadow: 0 6px 24px rgba(160,82,45,0.40);
      white-space: nowrap;
      letter-spacing: -0.03em;
      text-align: center;
    }}
  </style>
</head>
<body>
  <div class="canvas">
    <img class="bg-image" src="bg-cell8-1080.png" alt="background">
    <div class="dark-overlay"></div>
    <div class="text-panel">
      <span class="badge">서울대보험쌤</span>
      <p class="headline">1200% 룰 후엔 지점장 문,<br><span class="accent">좁아집니다</span></p>
      <p class="sub-copy">본부 5개 | 지점 10개 | 200명+ 함께</p>
      <p class="urgency">사무실 개설비 지원 | 조직 구축 시스템</p>
      <div class="cta-btn">지점장 이직 상담 신청 →</div>
    </div>
  </div>
</body>
</html>
"""

# ── HTML 1200x628 ──────────────────────────────────────────────────────────────
# 브랜드: 카라멜(#D4956A) 강조, 좌측 텍스트 + 우측 배경
# "좁아집니다" → #D4956A 강조

HTML_1200 = f"""\
<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=1200">
  <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-SemiBold.otf') format('opentype'); font-weight: 600; }}
    @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; }}

    *, *::before, *::after {{ box-sizing: border-box; margin: 0; padding: 0; }}
    html, body {{ width: 1200px; height: 628px; overflow: hidden; font-family: 'Pretendard', sans-serif; word-break: keep-all; }}

    .canvas {{ position: relative; width: 1200px; height: 628px; overflow: hidden; }}
    .bg-image {{ position: absolute; right: 0; top: 0; width: 65%; height: 100%; object-fit: cover; object-position: center right; }}

    .gradient-overlay {{
      position: absolute; inset: 0;
      background: linear-gradient(
        to right,
        rgba(62,39,35,0.97) 0%,
        rgba(62,39,35,0.95) 40%,
        rgba(62,39,35,0.85) 52%,
        rgba(62,39,35,0.50) 68%,
        rgba(62,39,35,0.15) 82%,
        transparent 100%
      );
    }}

    .accent-bar {{
      position: absolute;
      top: 80px; left: 0;
      width: 4px; height: 460px;
      background: linear-gradient(to bottom, #A0522D, #C07540);
      border-radius: 2px;
    }}

    .text-area {{
      position: absolute;
      top: 0; left: 0;
      width: 62%; height: 100%;
      padding: 48px 56px 48px 60px;
      display: flex; flex-direction: column;
      justify-content: center;
      gap: 18px;
    }}

    .badge {{
      display: inline-block;
      background: #A0522D;
      color: #FFFFFF;
      font-size: {_CTA_PX}px; font-weight: 700;
      height: 48px; line-height: {_LH_48PX}px;
      padding: 0 20px;
      border-radius: 6px;
      white-space: nowrap;
      letter-spacing: -0.03em;
      align-self: flex-start;
      margin-bottom: 6px;
    }}

    .headline {{
      font-size: {_SIZE_58PX}px; font-weight: 700;
      color: #FFF8E7; line-height: {_LH_1_2};
      letter-spacing: -1.2px;
    }}
    .headline .accent {{ color: #D4956A; }}

    .sub-copy {{
      font-size: {_CTA_PX}px; font-weight: 500;
      color: #D4956A;
      text-shadow: 0 1px 3px rgba(62,39,35,0.6);
      white-space: nowrap;
      letter-spacing: -0.02em;
    }}

    .urgency {{
      font-size: {_SIZE_38PX}px; font-weight: 500;
      color: rgba(255, 248, 231, 0.82);
      text-shadow: 0 1px 3px rgba(62,39,35,0.6);
      white-space: nowrap;
      letter-spacing: -0.02em;
    }}

    .cta-btn {{
      display: inline-block;
      background: linear-gradient(135deg, #A0522D 0%, #C07540 100%);
      color: #FFFFFF;
      font-size: {_SIZE_44PX}px; font-weight: 700;
      height: 56px; line-height: {_LH_56PX}px;
      padding: 0 32px;
      min-width: 220px;
      width: auto;
      border-radius: 6px;
      box-shadow: 0 4px 16px rgba(160,82,45,0.40);
      white-space: nowrap;
      letter-spacing: -0.03em;
      align-self: flex-start;
      text-align: center;
      margin-top: 14px;
    }}
  </style>
</head>
<body>
  <div class="canvas">
    <img class="bg-image" src="bg-cell8-1200.png" alt="background">
    <div class="gradient-overlay"></div>
    <div class="accent-bar"></div>
    <div class="text-area">
      <span class="badge">서울대보험쌤</span>
      <p class="headline">1200% 룰 후엔 지점장 문,<br><span class="accent">좁아집니다</span></p>
      <p class="sub-copy">본부 5개 | 지점 10개 | 200명+ 함께</p>
      <p class="urgency">사무실 개설비 지원 | 조직 구축 시스템</p>
      <div class="cta-btn">지점장 이직 상담 신청 →</div>
    </div>
  </div>
</body>
</html>
"""


# ── Playwright 렌더링 ──────────────────────────────────────────────────────────

def render_html_to_png(html_path: Path, width: int, height: int, out_path: Path) -> None:
    """Playwright로 HTML을 PNG로 캡처합니다."""
    with sync_playwright() as p:
        browser = p.chromium.launch()
        try:
            page = browser.new_page(viewport={"width": width, "height": height})
            page.goto(f"file://{html_path.resolve()}", wait_until="networkidle")
            page.wait_for_timeout(2500)  # 폰트 + 이미지 로딩 대기
            page.screenshot(
                path=str(out_path),
                type="png",
                clip={"x": 0, "y": 0, "width": width, "height": height},
            )
            size_kb = out_path.stat().st_size // 1024
            print(f"  [렌더링 완료] {out_path.name} ({size_kb} KB)")
        finally:
            browser.close()


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

def main():
    print("=" * 60)
    print("Cell-8 서울대보험쌤 × 관리자/조직 비전 배너 생성")
    print("=" * 60)

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

    # ── Step 1: 배경 이미지 생성 ──────────────────────────────────────────────

    print("\n[Step 1] 배경 이미지 생성")

    ok_1080 = generate_gemini_background(PROMPT_1080, BG_1080_PATH, "1080x1080 배경")
    if not ok_1080:
        print(f"  Gemini 실패 → 폴백 사용: {FALLBACK_BG}")
        import shutil
        if FALLBACK_BG.exists():
            shutil.copy2(FALLBACK_BG, BG_1080_PATH)
            print(f"  폴백 복사 완료: {BG_1080_PATH}")
        else:
            # 순색 배경으로 대체
            print("  폴백도 없음 → 브라운 단색 배경으로 대체")
            create_solid_bg(BG_1080_PATH, 1080, 1080, "#3E2723")

    ok_1200 = generate_gemini_background(PROMPT_1200, BG_1200_PATH, "1200x628 배경")
    if not ok_1200:
        print(f"  Gemini 실패 → 폴백 사용: {FALLBACK_BG}")
        import shutil
        if FALLBACK_BG.exists():
            shutil.copy2(FALLBACK_BG, BG_1200_PATH)
            print(f"  폴백 복사 완료: {BG_1200_PATH}")
        else:
            print("  폴백도 없음 → 브라운 단색 배경으로 대체")
            create_solid_bg(BG_1200_PATH, 1200, 628, "#3E2723")

    # ── Step 2: HTML 파일 저장 ────────────────────────────────────────────────

    print("\n[Step 2] HTML 파일 저장")

    html_1080_path = OUTPUT_DIR / "meta-feed-1080x1080.html"
    html_1200_path = OUTPUT_DIR / "google-resp-1200x628.html"

    html_1080_path.write_text(HTML_1080, encoding="utf-8")
    print(f"  저장: {html_1080_path}")

    html_1200_path.write_text(HTML_1200, encoding="utf-8")
    print(f"  저장: {html_1200_path}")

    # ── Step 3: Playwright 렌더링 ─────────────────────────────────────────────

    print("\n[Step 3] Playwright 렌더링")

    out_1080 = OUTPUT_DIR / "meta-feed-1080x1080.png"
    out_1200 = OUTPUT_DIR / "google-resp-1200x628.png"

    print("  1080x1080 렌더링 중...")
    render_html_to_png(html_1080_path, 1080, 1080, out_1080)

    print("  1200x628 렌더링 중...")
    render_html_to_png(html_1200_path, 1200, 628, out_1200)

    # ── 완료 보고 ─────────────────────────────────────────────────────────────

    print("\n" + "=" * 60)
    print("완료!")
    files = [BG_1080_PATH, BG_1200_PATH, html_1080_path, html_1200_path, out_1080, out_1200]
    for f in files:
        if f.exists():
            print(f"  OK  {f}  ({f.stat().st_size // 1024} KB)")
        else:
            print(f"  !!  {f}  (없음)")
    print("=" * 60)


def create_solid_bg(path: Path, w: int, h: int, color: str) -> None:
    """PIL 없이 SVG→PNG로 단색 배경 생성 (최후 수단)."""
    svg = f'<svg xmlns="http://www.w3.org/2000/svg" width="{w}" height="{h}"><rect width="{w}" height="{h}" fill="{color}"/></svg>'
    svg_path = path.with_suffix(".svg")
    svg_path.write_text(svg)
    import subprocess
    subprocess.run(["convert", str(svg_path), str(path)], check=True)
    svg_path.unlink(missing_ok=True)


if __name__ == "__main__":
    main()
