#!/usr/bin/env python3
"""
Concept #20 v2 — 좌우 분할 솔루션형 (Split-Layout Solution) 광고 이미지 리메이크
사양서 준수: 핵심 메시지 84px+, 보조 메시지 64px+, 최소 40px
출력: sample-v2.png, 20-split-layout-v2.png
"""

from __future__ import annotations

import base64
import shutil
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_V2_PATH = OUTPUT_DIR / "bg_v2.png"
TEMPLATE_V2_PATH = OUTPUT_DIR / "template_v2.html"
FINAL_OUTPUT = OUTPUT_DIR / "sample-v2.png"
COPY_OUTPUT = OUTPUT_DIR / "20-split-layout-v2.png"

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

BG_PROMPT = (
    "Korean businessman in dark navy suit, early 30s, standing by large office window, "
    "contemplative thoughtful expression looking to the side, moody dramatic lighting with shadows on face, "
    "modern corporate office background, cinematic portrait style, upper body shot. "
    "The figure is positioned in the LEFT HALF of a square frame, right half intentionally empty space. "
    "Dark tones, cool blue-grey office atmosphere, shallow depth of field bokeh background. "
    "Photorealistic, editorial photography quality, no text, no logos, 1:1 square format 1080x1080."
)


# ─────────────────────────────────────────────────────────────────────────────
# 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_V2_PATH.write_bytes(image_bytes)
        print(f"      배경 저장: {BG_V2_PATH} ({len(image_bytes):,} bytes, mime={mime_type})")
        return BG_V2_PATH

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


# ─────────────────────────────────────────────────────────────────────────────
# Step 2: HTML 오버레이 템플릿 생성
# 폰트 크기 규칙: 핵심 84px+, 보조 64px+, 최소 40px
# ─────────────────────────────────────────────────────────────────────────────

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;
    }}

    /* ── 컨테이너: 좌우 50% 분할 ── */
    .container {{
      display: flex;
      width: 1080px;
      height: 1080px;
    }}

    /* ── 좌측 패널: 540px, 인물 사진 + 비네트 + 텍스트 ── */
    .left-panel {{
      width: 540px;
      height: 1080px;
      position: relative;
      overflow: hidden;
    }}
    .left-panel img {{
      width: 100%;
      height: 100%;
      object-fit: cover;
      filter: saturate(0.7) brightness(0.88);
    }}
    /* 어두운 비네트 — 하단으로 갈수록 어둡게 */
    .left-vignette {{
      position: absolute;
      inset: 0;
      background:
        linear-gradient(to bottom,
          rgba(10,18,28,0.10) 0%,
          rgba(10,18,28,0.25) 50%,
          rgba(10,18,28,0.82) 100%
        );
    }}
    /* 좌측 하단 텍스트 블록 */
    .left-text {{
      position: absolute;
      bottom: 60px;
      left: 40px;
      right: 24px;
    }}
    .left-line {{
      display: block;
      color: #FFFFFF;
      font-size: 64px;
      font-weight: 700;
      line-height: 1.32;
      letter-spacing: -1.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;
    }}

    /* ── 우측 패널: 540px, 따뜻한 크림 배경 + 해결책 ── */
    .right-panel {{
      width: 540px;
      height: 1080px;
      background: linear-gradient(160deg, #FFFBF0 0%, #FFF0E6 100%);
      display: flex;
      flex-direction: column;
      justify-content: center;
      padding: 0 48px;
    }}

    /* 브랜드 라벨 — 40px */
    .brand-label {{
      font-size: 40px;
      font-weight: 600;
      color: #E8600A;
      line-height: 1.3;
      letter-spacing: -0.8px;
      margin-bottom: 28px;
      word-break: keep-all;
    }}

    /* "최대" 레이블 — 44px */
    .sub-label {{
      font-size: 44px;
      font-weight: 500;
      color: #5A6A7A;
      line-height: 1.2;
      letter-spacing: -0.5px;
      margin-bottom: 4px;
      word-break: keep-all;
    }}

    /* "1,000만원" 핵심 메시지 — 84px */
    .main-value {{
      font-size: 84px;
      font-weight: 900;
      color: #E8600A;
      line-height: 1.1;
      letter-spacing: -3px;
      margin-bottom: 28px;
      word-break: keep-all;
    }}

    /* "경력직 지원" — 44px */
    .career-label {{
      font-size: 44px;
      font-weight: 500;
      color: #5A6A7A;
      line-height: 1.2;
      letter-spacing: -0.5px;
      margin-bottom: 4px;
      word-break: keep-all;
    }}

    /* "직전연봉 50%까지" 보조 메시지 — 64px */
    .salary-line {{
      font-size: 64px;
      font-weight: 800;
      color: #1A2E4A;
      line-height: 1.15;
      letter-spacing: -2px;
      margin-bottom: 28px;
      word-break: keep-all;
    }}

    /* "2026년 7월 변경" — 44px */
    .deadline-label {{
      font-size: 44px;
      font-weight: 600;
      color: #C8860A;
      line-height: 1.2;
      letter-spacing: -0.5px;
      margin-bottom: 28px;
      word-break: keep-all;
    }}

    /* CTA 버튼 — 높이 64px, 텍스트 40px */
    .cta-button {{
      display: flex;
      align-items: center;
      justify-content: center;
      background: #E8600A;
      color: #FFFFFF;
      font-size: 40px;
      font-weight: 700;
      height: 64px;
      border-radius: 8px;
      letter-spacing: -0.5px;
      margin-bottom: 16px;
      word-break: keep-all;
      white-space: nowrap;
    }}

    /* 하단 조직 레이블 — 40px */
    .org-label {{
      font-size: 40px;
      font-weight: 400;
      color: #8A9AAA;
      text-align: center;
      line-height: 1.3;
      letter-spacing: -0.3px;
      word-break: keep-all;
    }}
  </style>
</head>
<body>
  <div class="container">

    <!-- 좌측 패널: 인물 사진 + 비네트 + 문제 제기 텍스트 -->
    <div class="left-panel">
      <img src="file://{bg_path}" alt="Korean businessman contemplating">
      <div class="left-vignette"></div>
      <div class="left-text">
        <span class="left-line">열심히는 하는데</span>
        <span class="left-line">소득은</span>
        <span class="left-line">제자리걸음?</span>
      </div>
    </div>

    <!-- 우측 패널: 따뜻한 크림 배경 + 해결책 텍스트 -->
    <div class="right-panel">

      <!-- 브랜드 라벨 (40px) -->
      <div class="brand-label">T.O.P 정착지원금</div>

      <!-- "최대" (44px) -->
      <div class="sub-label">최대</div>

      <!-- "1,000만원" — 핵심 메시지 (84px) -->
      <div class="main-value">1,000만원</div>

      <!-- "경력직 지원" (44px) -->
      <div class="career-label">경력직 지원</div>

      <!-- "직전연봉 50%까지" — 보조 메시지 (64px) -->
      <div class="salary-line">직전연봉 50%까지</div>

      <!-- "2026년 7월 변경" (44px) -->
      <div class="deadline-label">2026년 7월 변경</div>

      <!-- CTA 버튼 (높이 64px, 텍스트 40px) -->
      <div class="cta-button">상담 신청하기 →</div>

      <!-- 조직 레이블 (40px) -->
      <div class="org-label">T.O.P 사업단 | 인카금융서비스</div>
    </div>

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


def create_html_template(bg_path: Path) -> Path:
    """배경 이미지 경로를 주입한 HTML 템플릿 v2 파일을 생성합니다."""
    print("[2/3] HTML 오버레이 템플릿 v2 생성 중...")
    html_content = HTML_TEMPLATE.format(bg_path=str(bg_path.resolve()))
    TEMPLATE_V2_PATH.write_text(html_content, encoding="utf-8")
    print(f"      템플릿 저장: {TEMPLATE_V2_PATH}")
    return TEMPLATE_V2_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 v2 — Split-Layout Solution 리메이크")
    print("폰트 규칙: 핵심 84px+ / 보조 64px+ / 최소 40px")
    print("=" * 60)

    start_time = time.time()

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

    # 기존 파일 보호 확인
    for protected in ["sample.png", "bg.png", "template.html"]:
        p = OUTPUT_DIR / protected
        if p.exists():
            print(f"      [보호] {protected} 유지 — 덮어쓰지 않음")

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

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

    # Step 3: Playwright 캡처 → sample-v2.png
    capture_final_image(template_path, FINAL_OUTPUT)

    # Step 4: 복사 → 20-split-layout-v2.png
    print(f"[복사] {FINAL_OUTPUT.name} → {COPY_OUTPUT.name}")
    shutil.copy2(str(FINAL_OUTPUT), str(COPY_OUTPUT))
    print(f"      복사 완료: {COPY_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"최종 출력 1: {FINAL_OUTPUT} ({size_kb:.0f} KB)")
    print(f"최종 출력 2: {COPY_OUTPUT}")
    print()
    print("[폰트 크기 검증]")
    print("  핵심 메시지 '1,000만원': 84px ✓")
    print("  보조 메시지 '직전연봉 50%까지': 64px ✓")
    print("  보조 메시지 '열심히는 하는데/소득은/제자리걸음?': 64px ✓")
    print("  CTA/브랜드/조직 라벨: 40px ✓")
    print("  최소 기준 40px 미만 없음 ✓")
    print("=" * 60)


if __name__ == "__main__":
    main()
