#!/usr/bin/env python3
"""컨셉 #31 — 어스 트루스 (Patagonia Style) 이미지 생성."""

import base64
import sys
import time
from pathlib import Path

import requests

sys.path.insert(0, str(Path(__file__).parent))
import gcloud_auth
from gen_config import CTA_MIN_PX, HEAD_SUB_RATIO, SUBHEAD_MIN_PX, WORKSPACE_ROOT

# ── 디자인 토큰 ──
_CTA_PX = CTA_MIN_PX
_SIZE_42PX = 42
_SUBHEAD_PX = SUBHEAD_MIN_PX
_SIZE_92PX = 92
_LH_1_15 = 1.15
_LH_RATIO = HEAD_SUB_RATIO


OUTPUT_PATH = WORKSPACE_ROOT / "output/meta-ads/concept-catalog/31-patagonia-style/sample.png"
HTML_PATH = Path("/tmp/concept31_overlay.html")

BG_PROMPT = (
    "Vast mountain landscape at golden hour, dramatic natural lighting, "
    "earthy warm tones with deep forest greens and warm browns, open field or mountain vista, "
    "natural and unfiltered color grading, slight film grain texture, "
    "documentary outdoor photography style, panoramic view, "
    "no text, no words, no letters, no people, 1080x1080 square format"
)

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

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

    html, body {{
      width: 1080px;
      height: 1080px;
      overflow: hidden;
      -webkit-font-smoothing: antialiased;
    }}

    body {{
      position: relative;
      background: #E8DCC8;
    }}

    /* 배경 이미지 레이어 */
    #bg-layer {{
      position: absolute;
      inset: 0;
      z-index: 0;
      background-image: url('{bg_url}');
      background-size: cover;
      background-position: center center;
      background-repeat: no-repeat;
    }}

    /* 하단 그라디언트 오버레이 (하단 40%) */
    #gradient-overlay {{
      position: absolute;
      inset: 0;
      z-index: 1;
      background: linear-gradient(
        to bottom,
        transparent 40%,
        rgba(28, 46, 28, 0.55) 65%,
        rgba(28, 46, 28, 0.85) 100%
      );
    }}

    /* 상단 좌측 코너 태그 */
    .corner-tag {{
      position: absolute;
      top: 52px;
      left: 52px;
      z-index: 4;
      background: rgba(74, 139, 139, 0.82);
      padding: 10px 22px;
      border-radius: 4px;
    }}

    .corner-tag span {{
      font-family: 'Noto Sans KR', 'Apple SD Gothic Neo', sans-serif;
      font-size: {_CTA_PX}px;
      font-weight: 700;
      color: #FFFFFF;
      letter-spacing: 0.12em;
      text-transform: uppercase;
    }}

    /* 하단 텍스트 영역 */
    .bottom-zone {{
      position: absolute;
      bottom: 0;
      left: 0;
      right: 0;
      z-index: 3;
      padding: 0 64px 72px 64px;
      display: flex;
      flex-direction: column;
      align-items: flex-start;
    }}

    /* 핵심 메시지 */
    .headline {{
      font-family: 'Noto Sans KR', 'Apple SD Gothic Neo', sans-serif;
      font-size: {_SIZE_92PX}px;
      font-weight: 800;
      line-height: {_LH_1_15};
      color: #FFFFFF;
      letter-spacing: -0.02em;
      white-space: pre-line;
      margin-bottom: 28px;
      text-shadow: 0 2px 16px rgba(0,0,0,0.4);
    }}

    /* 보조 메시지 */
    .subtext {{
      font-family: 'Noto Sans KR', 'Apple SD Gothic Neo', sans-serif;
      font-size: {_SUBHEAD_PX}px;
      font-weight: 400;
      line-height: {_LH_RATIO};
      color: #E8DCC8;
      letter-spacing: -0.01em;
      margin-bottom: 36px;
      text-shadow: 0 2px 8px rgba(0,0,0,0.35);
    }}

    /* 구분선 */
    .divider {{
      width: 64px;
      height: 3px;
      background-color: #D4541A;
      margin-bottom: 28px;
    }}

    /* CTA */
    .cta {{
      font-family: 'Noto Sans KR', 'Apple SD Gothic Neo', sans-serif;
      font-size: {_SIZE_42PX}px;
      font-weight: 700;
      color: #D4541A;
      letter-spacing: 0.02em;
    }}
  </style>
</head>
<body>
  <div id="bg-layer"></div>
  <div id="gradient-overlay"></div>

  <!-- 상단 좌측 태그 -->
  <div class="corner-tag">
    <span>CAREER CHANGE</span>
  </div>

  <!-- 하단 텍스트 영역 -->
  <div class="bottom-zone">
    <div class="headline">열심히는 하는데,&#10;월급은 제자리걸음?</div>
    <div class="subtext">당신의 노력만큼 보상받고 계십니까?</div>
    <div class="divider"></div>
    <div class="cta">지금 확인하기 →</div>
  </div>
</body>
</html>"""


def generate_bg_image(token: str, prompt: str) -> bytes:
    """Gemini API로 배경 이미지 생성."""
    model_ids = [
        "gemini-3-pro-image-preview",
        "gemini-3.1-flash-image-preview",
        "gemini-2.5-flash-image",
    ]
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/json",
    }
    payload = {
        "contents": [{"parts": [{"text": prompt}]}],
        "generationConfig": {"responseModalities": ["IMAGE", "TEXT"]},
    }

    last_err = None
    resp = None
    for model_id in model_ids:
        url = f"https://generativelanguage.googleapis.com/v1beta/models/{model_id}:generateContent"
        print(f"  [Gemini] 배경 이미지 생성 중 (모델: {model_id})...")
        start = time.time()
        try:
            resp = requests.post(url, headers=headers, json=payload, timeout=300)
            if resp.status_code in (403, 404):
                print(f"  [Gemini] {resp.status_code} — 다음 모델 시도...")
                last_err = resp.status_code
                continue
            resp.raise_for_status()
            elapsed = time.time() - start
            print(f"  [Gemini] 완료 ({elapsed:.1f}초)")
            break
        except Exception as e:
            last_err = e
            print(f"  [Gemini] 오류: {e} — 다음 모델 시도...")
            continue
    else:
        raise RuntimeError(f"모든 모델 실패. 마지막 오류: {last_err}")

    data = resp.json()
    candidates = data.get("candidates", [])
    if not candidates:
        raise RuntimeError(f"No candidates: {str(data)[:300]}")

    for part in candidates[0].get("content", {}).get("parts", []):
        if "inlineData" in part:
            return base64.b64decode(part["inlineData"]["data"])

    raise RuntimeError("이미지 데이터가 응답에 없습니다.")


def render_html_to_png(bg_bytes: bytes, html_template: str, output_path: Path) -> None:
    """HTML + Playwright로 최종 PNG 생성."""
    from playwright.sync_api import sync_playwright
    import base64 as b64

    bg_b64 = b64.b64encode(bg_bytes).decode()
    bg_data_url = f"data:image/jpeg;base64,{bg_b64}"

    html_content = html_template.format(bg_url=bg_data_url)
    HTML_PATH.write_text(html_content, encoding="utf-8")
    print(f"  [HTML] 템플릿 저장: {HTML_PATH}")

    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})
            page.goto(f"file://{HTML_PATH}", wait_until="networkidle")
            page.wait_for_timeout(2000)
            page.screenshot(path=str(output_path), type="png")
            print(f"  [PNG] 저장 완료: {output_path}")
        finally:
            browser.close()


def main():
    print("=== 컨셉 #31 어스 트루스 (Patagonia Style) 생성 시작 ===")

    print("\n[1/3] Gemini 인증 토큰 획득...")
    token = gcloud_auth.get_service_account_token(
        "https://www.googleapis.com/auth/generative-language"
    )
    print(f"  토큰 획득 성공 (길이: {len(token)}자)")

    print("\n[2/3] 배경 이미지 생성...")
    bg_bytes = generate_bg_image(token, BG_PROMPT)
    print(f"  배경 이미지 크기: {len(bg_bytes):,} bytes")

    print("\n[3/3] HTML 오버레이 합성 및 PNG 저장...")
    render_html_to_png(bg_bytes, HTML_TEMPLATE, OUTPUT_PATH)

    size_kb = OUTPUT_PATH.stat().st_size / 1024
    print(f"\n=== 완료: {OUTPUT_PATH} ({size_kb:.0f} KB) ===")


if __name__ == "__main__":
    main()
