#!/usr/bin/env python3
"""
Concept #20 — 좌우 분할 솔루션형 (Split-Layout Solution) 광고 이미지 생성기
Gemini AI 배경 + HTML/CSS Playwright 오버레이 하이브리드 파이프라인
"""

from __future__ import annotations

import base64
import sys
import time
from pathlib import Path

import requests
from playwright.sync_api import sync_playwright

# ─────────────────────────────────────────────────────────────────────────────
# 경로 상수
# ─────────────────────────────────────────────────────────────────────────────

BASE_DIR = Path("/home/jay/workspace/tools/ai-image-gen")
OUTPUT_DIR = Path("/home/jay/workspace/output/meta-ads/concept-catalog/20-split-layout")
BG_PATH = OUTPUT_DIR / "bg.png"
TEMPLATE_PATH = OUTPUT_DIR / "template.html"
FINAL_OUTPUT = OUTPUT_DIR / "sample.png"

GEMINI_API_BASE = "https://generativelanguage.googleapis.com/v1beta"
GEMINI_SCOPE = "https://www.googleapis.com/auth/generative-language"

BG_PROMPT = (
    "A thoughtful Korean professional man in his late 30s, wearing business casual attire "
    "(white shirt, dark blazer), standing slightly turned to the left side, gaze directed slightly "
    "downward with a pensive, introspective expression — not sad, but quietly concerned about career "
    "stagnation. The figure is positioned in the LEFT HALF of a square frame, leaving the right half "
    "as empty space. Background is a softly blurred modern office in cool grey-blue tones. "
    "Cool neutral side lighting from upper left. Shallow depth of field. "
    "Photorealistic high-quality editorial photography. No text. No logos. Square 1:1 format, 1080x1080px."
)


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

def generate_background() -> Path:
    """Gemini API로 배경 이미지를 생성하고 저장합니다."""
    sys.path.insert(0, str(BASE_DIR))
    import gcloud_auth

    print("[1/3] Gemini API로 배경 이미지 생성 중...")
    token = gcloud_auth.get_service_account_token(GEMINI_SCOPE)
    print(f"      SA 토큰 획득 성공 (길이: {len(token)} chars)")

    models = [
        "gemini-3-pro-image-preview",
        "gemini-3.1-flash-image-preview",
        "gemini-2.0-flash-preview-image-generation",
    ]

    for model_id in models:
        print(f"      모델 시도: {model_id}")
        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"]},
        }

        try:
            resp = requests.post(url, headers=headers, json=payload, timeout=120)
            if resp.status_code in (403, 404):
                print(f"      HTTP {resp.status_code} — 다음 모델로 시도")
                continue
            resp.raise_for_status()
        except requests.HTTPError as e:
            print(f"      HTTP 오류: {e} — 다음 모델로 시도")
            continue

        data = resp.json()
        candidates = data.get("candidates", [])
        if not candidates:
            print("      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("      이미지 데이터 없음 — 다음 모델로 시도")
            continue

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

    raise RuntimeError("모든 Gemini 모델 실패 — 배경 이미지 생성 불가")


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

HTML_TEMPLATE = """<!DOCTYPE html>
<html lang="ko">
<head>
  <meta charset="UTF-8">
  <style>
    @font-face {{
      font-family: 'Pretendard';
      src: url('file:///home/jay/.local/share/fonts/Pretendard/Pretendard-Black.otf') format('opentype');
      font-weight: 900;
    }}
    @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-Bold.otf') format('opentype');
      font-weight: 700;
    }}
    @font-face {{
      font-family: 'Pretendard';
      src: url('file:///home/jay/.local/share/fonts/Pretendard/Pretendard-SemiBold.otf') format('opentype');
      font-weight: 600;
    }}
    @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-Regular.otf') format('opentype');
      font-weight: 400;
    }}

    * {{ margin: 0; padding: 0; box-sizing: border-box; }}
    body {{
      width: 1080px;
      height: 1080px;
      overflow: hidden;
      font-family: 'Pretendard', 'Noto Sans KR', sans-serif;
      -webkit-font-smoothing: antialiased;
    }}
    .container {{
      display: flex;
      width: 1080px;
      height: 1080px;
    }}

    /* ── 좌측 패널 ── */
    .left-panel {{
      width: 540px;
      height: 1080px;
      position: relative;
      overflow: hidden;
    }}
    .left-panel img {{
      width: 100%;
      height: 100%;
      object-fit: cover;
      filter: saturate(0.65) brightness(0.92);
    }}
    .left-vignette {{
      position: absolute;
      inset: 0;
      background:
        radial-gradient(ellipse at 30% 30%, rgba(28,43,58,0.35) 0%, transparent 60%),
        linear-gradient(to bottom, transparent 40%, rgba(28,43,58,0.80) 100%);
    }}
    .left-hook {{
      position: absolute;
      bottom: 64px;
      left: 40px;
      right: 32px;
      color: #FFFFFF;
      font-size: 42px;
      font-weight: 700;
      line-height: 1.4;
      letter-spacing: -0.5px;
      text-shadow: 0 2px 12px rgba(0,0,0,0.80), 0 4px 24px rgba(0,0,0,0.60);
      word-break: keep-all;
    }}

    /* ── 우측 패널 ── */
    .right-panel {{
      width: 540px;
      height: 1080px;
      background: linear-gradient(160deg, #FFFBF0 0%, #FFF0E6 100%);
      display: flex;
      flex-direction: column;
      justify-content: center;
      padding: 56px 48px;
    }}
    .solution-label {{
      font-size: 18px;
      font-weight: 600;
      color: #E8600A;
      margin-bottom: 36px;
      letter-spacing: -0.2px;
      word-break: keep-all;
    }}
    .benefits-list {{
      display: flex;
      flex-direction: column;
      gap: 32px;
      margin-bottom: 48px;
    }}
    .benefit-item {{
      display: flex;
      align-items: flex-start;
      gap: 14px;
    }}
    .benefit-icon {{
      font-size: 22px;
      margin-top: 8px;
      flex-shrink: 0;
      line-height: 1;
    }}
    .benefit-icon.check {{ color: #E8600A; }}
    .benefit-icon.warn {{ color: #C8860A; }}
    .benefit-label {{
      font-size: 18px;
      font-weight: 500;
      color: #5A6A7A;
      line-height: 1.4;
      margin-bottom: 4px;
      word-break: keep-all;
    }}
    .benefit-value {{
      font-size: 36px;
      font-weight: 800;
      color: #1A2E4A;
      line-height: 1.2;
      letter-spacing: -1px;
      word-break: keep-all;
    }}
    .benefit-value .highlight {{ color: #E8600A; }}
    .benefit-value.amber {{ font-size: 30px; color: #C8860A; }}
    .cta-button {{
      display: flex;
      align-items: center;
      justify-content: center;
      gap: 10px;
      background: #E8600A;
      color: #FFFFFF;
      font-size: 22px;
      font-weight: 700;
      height: 64px;
      border-radius: 8px;
      margin-bottom: 18px;
      letter-spacing: -0.3px;
      word-break: keep-all;
    }}
    .org-label {{
      font-size: 15px;
      font-weight: 400;
      color: #8A9AAA;
      text-align: center;
      word-break: keep-all;
    }}
  </style>
</head>
<body>
  <div class="container">
    <div class="left-panel">
      <img src="file://{bg_path}" alt="person">
      <div class="left-vignette"></div>
      <div class="left-hook">열심히는 하는데<br>소득은<br>제자리걸음인가요?</div>
    </div>
    <div class="right-panel">
      <div class="solution-label">T.O.P 사업단의 파격적 정착지원금</div>
      <div class="benefits-list">
        <div class="benefit-item">
          <span class="benefit-icon check">✓</span>
          <div>
            <div class="benefit-label">신입 정착지원금</div>
            <div class="benefit-value">최대 <span class="highlight">1,000만원</span></div>
          </div>
        </div>
        <div class="benefit-item">
          <span class="benefit-icon check">✓</span>
          <div>
            <div class="benefit-label">경력직 지원</div>
            <div class="benefit-value">직전연봉 <span class="highlight">50%</span>까지</div>
          </div>
        </div>
        <div class="benefit-item">
          <span class="benefit-icon warn">⚠</span>
          <div>
            <div class="benefit-label">조건 변경 예정</div>
            <div class="benefit-value amber">2026년 7월</div>
          </div>
        </div>
      </div>
      <div class="cta-button">지금 상담 신청하기 <span>→</span></div>
      <div class="org-label">T.O.P 사업단 | 인카금융서비스 코스닥 상장</div>
    </div>
  </div>
</body>
</html>
"""


def create_html_template(bg_path: Path) -> Path:
    """배경 이미지 경로를 주입한 HTML 템플릿 파일을 생성합니다."""
    print("[2/3] HTML 오버레이 템플릿 생성 중...")
    html_content = HTML_TEMPLATE.format(bg_path=str(bg_path.resolve()))
    TEMPLATE_PATH.write_text(html_content, encoding="utf-8")
    print(f"      템플릿 저장: {TEMPLATE_PATH}")
    return TEMPLATE_PATH


# ─────────────────────────────────────────────────────────────────────────────
# Step 3: Playwright로 최종 이미지 캡처
# ─────────────────────────────────────────────────────────────────────────────

def capture_final_image(template_path: Path, output_path: Path) -> None:
    """Playwright 헤드리스 브라우저로 HTML을 렌더링하여 PNG로 저장합니다."""
    print("[3/3] Playwright로 최종 이미지 캡처 중...")

    output_path.parent.mkdir(parents=True, exist_ok=True)

    with sync_playwright() as p:
        browser = p.chromium.launch()
        try:
            page = browser.new_page(viewport={"width": 1080, "height": 1080})
            template_url = f"file://{template_path.resolve()}"
            page.goto(template_url, wait_until="networkidle")
            # 폰트 및 배경 이미지 로딩 대기
            page.wait_for_timeout(2500)
            page.screenshot(path=str(output_path), type="png")
            print(f"      최종 이미지 저장: {output_path}")
        finally:
            browser.close()


# ─────────────────────────────────────────────────────────────────────────────
# 메인 파이프라인
# ─────────────────────────────────────────────────────────────────────────────

def main() -> None:
    print("=" * 60)
    print("Concept #20 — 좌우 분할 솔루션형 광고 이미지 생성")
    print("Gemini AI 배경 + HTML 오버레이 하이브리드 파이프라인")
    print("=" * 60)

    start_time = time.time()

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

    # Step 1: Gemini 배경 생성
    bg_path = generate_background()

    # Step 2: HTML 템플릿 생성 (template.html as specified)
    template_path = create_html_template(bg_path)

    # Step 3: Playwright 캡처
    capture_final_image(template_path, FINAL_OUTPUT)

    elapsed = time.time() - start_time
    size_kb = FINAL_OUTPUT.stat().st_size / 1024

    print()
    print("=" * 60)
    print(f"완료! 총 소요시간: {elapsed:.1f}초")
    print(f"배경 이미지: {bg_path}")
    print(f"HTML 템플릿: {template_path}")
    print(f"최종 출력: {FINAL_OUTPUT}")
    print(f"파일 크기: {size_kb:.0f} KB")
    print("=" * 60)


if __name__ == "__main__":
    main()
