#!/usr/bin/env python3
"""
컨셉 #24, #25, #26 하이브리드 이미지 생성 스크립트
Gemini Pro 배경 + Playwright HTML 오버레이
"""

from __future__ import annotations

import base64
import json
import sys
import time
from pathlib import Path
from typing import Any

import requests
from playwright.sync_api import sync_playwright

# ─────────────────────────────────────────────────────────────────────────────
# 경로 설정
# ─────────────────────────────────────────────────────────────────────────────

BASE_DIR = Path(__file__).parent
WORK_DIR = Path("/home/jay/workspace/tools/ai-image-gen")
OUTPUT_BASE = Path("/home/jay/workspace/output/meta-ads/concept-catalog")

CONCEPTS = {
    "24": {
        "output_dir": OUTPUT_BASE / "24-apple-style",
        "bg_prompt": (
            "Pure clean off-white background #F5F5F7, extremely minimal, no objects, "
            "no texture, vast empty space, ultra clean studio lighting, "
            "Apple-inspired minimalism, 1080x1080, square format"
        ),
        "style": "apple",
    },
    "25": {
        "output_dir": OUTPUT_BASE / "25-mcdonalds-style",
        "bg_prompt": (
            "Bold energetic background, top half bright vivid red #DA291C, "
            "bottom half golden yellow #FFC72C, diagonal split line between colors, "
            "cheerful and optimistic mood, high saturation, no text, no people, "
            "1080x1080, square format"
        ),
        "style": "mcdonalds",
    },
    "26": {
        "output_dir": OUTPUT_BASE / "26-hyundai-style",
        "bg_prompt": (
            "Dark cinematic studio background, deep charcoal black #0D0F12, "
            "subtle metallic silver light streak coming from upper left corner, "
            "soft blue-tinted ambient glow on the edges, "
            "ultra-premium automotive aesthetic, no text, no objects, "
            "high contrast, 1080x1080, square format"
        ),
        "style": "hyundai",
    },
}

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

GEMINI_API_BASE = "https://generativelanguage.googleapis.com/v1beta"
MODEL_ID = "gemini-3-pro-image-preview"
FALLBACK_MODEL = "gemini-3.1-flash-image-preview"


def get_auth_token() -> str:
    """인증 토큰 획득 (SA 우선, gcloud CLI fallback)"""
    sys.path.insert(0, str(WORK_DIR))
    import gcloud_auth
    try:
        token = gcloud_auth.get_service_account_token(
            "https://www.googleapis.com/auth/generative-language"
        )
        print(f"  [인증] SA 토큰 획득 성공 ({len(token)} chars)")
        return token
    except Exception as e:
        print(f"  [인증] SA 토큰 실패: {e}, API 키 시도...")

    try:
        api_key = gcloud_auth.get_api_key("GEMINI_API_KEY")
        if api_key:
            return f"API_KEY:{api_key}"
    except Exception:
        pass

    import subprocess
    result = subprocess.run(
        ["gcloud", "auth", "print-access-token"],
        capture_output=True, text=True, check=True
    )
    token = result.stdout.strip()
    print(f"  [인증] gcloud CLI 토큰 획득 성공 ({len(token)} chars)")
    return token


def generate_background(token: str, prompt: str, output_path: Path) -> bool:
    """Gemini API로 배경 이미지 생성"""
    print(f"  [배경생성] 프롬프트: {prompt[:80]}...")

    # API 키 방식
    if token.startswith("API_KEY:"):
        api_key = token[8:]
        url = f"{GEMINI_API_BASE}/models/{MODEL_ID}:generateContent?key={api_key}"
        headers = {"Content-Type": "application/json"}
    else:
        url = f"{GEMINI_API_BASE}/models/{MODEL_ID}:generateContent"
        headers = {
            "Authorization": f"Bearer {token}",
            "Content-Type": "application/json",
        }

    payload = {
        "contents": [{"parts": [{"text": 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"  [배경생성] 모델 접근 실패 ({resp.status_code}), fallback 시도...")
            if token.startswith("API_KEY:"):
                url = f"{GEMINI_API_BASE}/models/{FALLBACK_MODEL}:generateContent?key={api_key}"
            else:
                url = f"{GEMINI_API_BASE}/models/{FALLBACK_MODEL}:generateContent"
            resp = requests.post(url, headers=headers, json=payload, timeout=120)

        resp.raise_for_status()
        data = resp.json()

        candidates = data.get("candidates", [])
        if not candidates:
            print(f"  [배경생성] 오류: candidates 없음")
            return False

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

        if image_part is None:
            print(f"  [배경생성] 오류: 이미지 데이터 없음")
            return False

        image_bytes = base64.b64decode(image_part["inlineData"]["data"])
        output_path.write_bytes(image_bytes)
        size_kb = len(image_bytes) / 1024
        print(f"  [배경생성] 완료: {output_path.name} ({size_kb:.0f} KB)")
        return True

    except Exception as e:
        print(f"  [배경생성] 오류: {e}")
        return False


# ─────────────────────────────────────────────────────────────────────────────
# HTML 오버레이 템플릿
# ─────────────────────────────────────────────────────────────────────────────

def build_apple_html(bg_path: Path) -> str:
    """#24 Apple Style HTML"""
    return f"""<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
  @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;600;700&display=swap');
  * {{ margin: 0; padding: 0; box-sizing: border-box; }}
  body {{
    width: 1080px;
    height: 1080px;
    overflow: hidden;
    background: #F5F5F7;
    font-family: 'Pretendard', 'Noto Sans KR', -apple-system, BlinkMacSystemFont, sans-serif;
  }}
  .container {{
    width: 1080px;
    height: 1080px;
    position: relative;
    background-image: url('file://{bg_path}');
    background-size: cover;
    background-position: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
  }}
  .content {{
    text-align: center;
    padding: 0 120px;
  }}
  .headline {{
    font-size: 84px;
    font-weight: 600;
    color: #1D1D1F;
    line-height: 1.15;
    letter-spacing: -2px;
    white-space: pre-line;
    margin-bottom: 36px;
  }}
  .sub {{
    font-size: 64px;
    font-weight: 400;
    color: #86868B;
    line-height: 1.3;
    letter-spacing: -1px;
    margin-bottom: 0;
  }}
  .cta {{
    position: absolute;
    bottom: 80px;
    left: 50%;
    transform: translateX(-50%);
    font-size: 40px;
    font-weight: 400;
    color: #0066CC;
    letter-spacing: -0.5px;
    white-space: nowrap;
    text-decoration: none;
  }}
</style>
</head>
<body>
<div class="container">
  <div class="content">
    <div class="headline">열심히는 하는데,<br>월급은 제자리걸음?</div>
    <div class="sub">이제 다른 방법을 찾아볼 때입니다</div>
  </div>
  <div class="cta">더 알아보기 →</div>
</div>
</body>
</html>"""


def build_mcdonalds_html(bg_path: Path) -> str:
    """#25 McDonald's Style HTML"""
    return f"""<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
  @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@400;700;900&display=swap');
  * {{ margin: 0; padding: 0; box-sizing: border-box; }}
  body {{
    width: 1080px;
    height: 1080px;
    overflow: hidden;
    font-family: 'Pretendard', 'Noto Sans KR', sans-serif;
  }}
  .container {{
    width: 1080px;
    height: 1080px;
    position: relative;
    background-image: url('file://{bg_path}');
    background-size: cover;
    background-position: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
  }}
  .top-block {{
    width: 100%;
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 60px 80px 30px;
  }}
  .headline {{
    font-size: 96px;
    font-weight: 900;
    color: #FFFFFF;
    line-height: 1.1;
    letter-spacing: -2px;
    text-align: center;
    white-space: pre-line;
    text-shadow: 2px 4px 12px rgba(0,0,0,0.3);
  }}
  .bottom-block {{
    width: 100%;
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 20px 80px 60px;
    gap: 40px;
  }}
  .sub {{
    font-size: 64px;
    font-weight: 700;
    color: #292929;
    line-height: 1.2;
    text-align: center;
    letter-spacing: -1px;
  }}
  .cta-btn {{
    background: #FFC72C;
    color: #292929;
    font-size: 48px;
    font-weight: 700;
    padding: 24px 80px;
    border-radius: 60px;
    letter-spacing: -0.5px;
    white-space: nowrap;
  }}
</style>
</head>
<body>
<div class="container">
  <div class="top-block">
    <div class="headline">월급 제자리걸음?<br>이제 바꾸면 되잖아!</div>
  </div>
  <div class="bottom-block">
    <div class="sub">T.O.P 사업단과 함께 시작하세요</div>
    <div class="cta-btn">지금 시작하기</div>
  </div>
</div>
</body>
</html>"""


def build_hyundai_html(bg_path: Path) -> str:
    """#26 Hyundai Style HTML"""
    return f"""<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
  @import url('https://fonts.googleapis.com/css2?family=Noto+Sans+KR:wght@300;400;700;900&display=swap');
  * {{ margin: 0; padding: 0; box-sizing: border-box; }}
  body {{
    width: 1080px;
    height: 1080px;
    overflow: hidden;
    font-family: 'Pretendard', 'Noto Sans KR', sans-serif;
  }}
  .container {{
    width: 1080px;
    height: 1080px;
    position: relative;
    background-image: url('file://{bg_path}');
    background-size: cover;
    background-position: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0;
  }}
  .content {{
    text-align: center;
    padding: 0 100px;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 48px;
  }}
  .eyebrow {{
    font-size: 28px;
    font-weight: 300;
    color: #00D4FF;
    letter-spacing: 6px;
    text-transform: uppercase;
  }}
  .headline {{
    font-size: 96px;
    font-weight: 900;
    color: #F5F7FA;
    line-height: 1.1;
    letter-spacing: -2px;
    white-space: pre-line;
    text-align: center;
  }}
  .divider {{
    width: 80px;
    height: 2px;
    background: #00D4FF;
  }}
  .sub {{
    font-size: 64px;
    font-weight: 300;
    color: #C0C8D0;
    line-height: 1.3;
    letter-spacing: -0.5px;
    text-align: center;
  }}
  .cta {{
    position: absolute;
    bottom: 80px;
    left: 50%;
    transform: translateX(-50%);
    border: 2px solid #00D4FF;
    color: #00D4FF;
    font-size: 40px;
    font-weight: 400;
    padding: 20px 72px;
    letter-spacing: 3px;
    text-transform: uppercase;
    white-space: nowrap;
  }}
</style>
</head>
<body>
<div class="container">
  <div class="content">
    <div class="eyebrow">T.O.P 사업단</div>
    <div class="headline">열심히는 하는데,<br>월급은 제자리걸음?</div>
    <div class="divider"></div>
    <div class="sub">이제 변속할 시간입니다</div>
  </div>
  <div class="cta">T.O.P 확인하기</div>
</div>
</body>
</html>"""


# ─────────────────────────────────────────────────────────────────────────────
# HTML → PNG 캡처
# ─────────────────────────────────────────────────────────────────────────────

def capture_html_to_png(html_content: str, output_path: Path) -> bool:
    """Playwright로 HTML을 1080x1080 PNG로 캡처"""
    html_path = output_path.parent / "_overlay_temp.html"
    html_path.write_text(html_content, encoding="utf-8")

    try:
        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.resolve()}", 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")
                size_kb = output_path.stat().st_size / 1024
                print(f"  [캡처] 완료: {output_path.name} ({size_kb:.0f} KB)")
                return True
            finally:
                browser.close()
    except Exception as e:
        print(f"  [캡처] 오류: {e}")
        return False
    finally:
        if html_path.exists():
            html_path.unlink()


# ─────────────────────────────────────────────────────────────────────────────
# 컨셉별 생성
# ─────────────────────────────────────────────────────────────────────────────

def generate_concept(concept_id: str, token: str) -> bool:
    """단일 컨셉 이미지 생성"""
    cfg = CONCEPTS[concept_id]
    output_dir: Path = cfg["output_dir"]
    output_dir.mkdir(parents=True, exist_ok=True)

    bg_path = output_dir / "bg_temp.jpg"
    sample_path = output_dir / "sample.png"
    style = cfg["style"]

    print(f"\n{'='*60}")
    print(f"[컨셉 #{concept_id}] 생성 시작")
    print(f"{'='*60}")
    start = time.time()

    # 1. 배경 생성
    bg_ok = generate_background(token, cfg["bg_prompt"], bg_path)

    if bg_ok:
        bg_for_html = bg_path
    else:
        # 배경 생성 실패 시 단색 fallback
        print(f"  [배경] 배경 생성 실패, 단색 fallback 사용")
        bg_for_html = None

    # 2. HTML 빌드
    if style == "apple":
        if bg_for_html:
            html = build_apple_html(bg_for_html)
        else:
            html = build_apple_html_solid()
    elif style == "mcdonalds":
        if bg_for_html:
            html = build_mcdonalds_html(bg_for_html)
        else:
            html = build_mcdonalds_html_solid()
    elif style == "hyundai":
        if bg_for_html:
            html = build_hyundai_html(bg_for_html)
        else:
            html = build_hyundai_html_solid()
    else:
        print(f"  [오류] 알 수 없는 스타일: {style}")
        return False

    # 3. HTML → PNG 캡처
    ok = capture_html_to_png(html, sample_path)

    # 임시 배경 파일 정리
    if bg_path.exists():
        bg_path.unlink()

    elapsed = time.time() - start
    if ok:
        print(f"[컨셉 #{concept_id}] 완료: {sample_path} ({elapsed:.1f}초)")
    else:
        print(f"[컨셉 #{concept_id}] 실패 ({elapsed:.1f}초)")

    return ok


def build_apple_html_solid() -> str:
    """Apple Style - 순수 CSS 배경 (fallback)"""
    return """<!DOCTYPE html>
<html><head><meta charset="UTF-8">
<style>
  * { margin: 0; padding: 0; box-sizing: border-box; }
  body { width: 1080px; height: 1080px; overflow: hidden;
    font-family: 'Pretendard', 'Noto Sans KR', -apple-system, sans-serif; }
  .container { width: 1080px; height: 1080px; position: relative;
    background: #F5F5F7; display: flex; flex-direction: column;
    align-items: center; justify-content: center; }
  .headline { font-size: 84px; font-weight: 600; color: #1D1D1F;
    line-height: 1.15; letter-spacing: -2px; text-align: center;
    margin-bottom: 36px; }
  .sub { font-size: 64px; font-weight: 400; color: #86868B;
    line-height: 1.3; letter-spacing: -1px; text-align: center; }
  .cta { position: absolute; bottom: 80px; left: 50%; transform: translateX(-50%);
    font-size: 40px; color: #0066CC; white-space: nowrap; }
</style></head><body>
<div class="container">
  <div class="headline">열심히는 하는데,<br>월급은 제자리걸음?</div>
  <div class="sub">이제 다른 방법을 찾아볼 때입니다</div>
  <div class="cta">더 알아보기 →</div>
</div></body></html>"""


def build_mcdonalds_html_solid() -> str:
    """McDonald's Style - 순수 CSS 배경 (fallback)"""
    return """<!DOCTYPE html>
<html><head><meta charset="UTF-8">
<style>
  * { margin: 0; padding: 0; box-sizing: border-box; }
  body { width: 1080px; height: 1080px; overflow: hidden;
    font-family: 'Pretendard', 'Noto Sans KR', sans-serif; }
  .container { width: 1080px; height: 1080px; position: relative;
    display: flex; flex-direction: column; }
  .top-block { flex: 1; background: #DA291C; display: flex;
    align-items: center; justify-content: center; padding: 60px 80px 30px; }
  .headline { font-size: 96px; font-weight: 900; color: #FFFFFF;
    line-height: 1.1; letter-spacing: -2px; text-align: center; }
  .bottom-block { flex: 1; background: #FFC72C; display: flex;
    flex-direction: column; align-items: center; justify-content: center;
    padding: 20px 80px 60px; gap: 40px; }
  .sub { font-size: 64px; font-weight: 700; color: #292929;
    text-align: center; letter-spacing: -1px; }
  .cta-btn { background: #FFC72C; border: 4px solid #292929; color: #292929;
    font-size: 48px; font-weight: 700; padding: 24px 80px;
    border-radius: 60px; }
</style></head><body>
<div class="container">
  <div class="top-block">
    <div class="headline">월급 제자리걸음?<br>이제 바꾸면 되잖아!</div>
  </div>
  <div class="bottom-block">
    <div class="sub">T.O.P 사업단과 함께 시작하세요</div>
    <div class="cta-btn">지금 시작하기</div>
  </div>
</div></body></html>"""


def build_hyundai_html_solid() -> str:
    """Hyundai Style - 순수 CSS 배경 (fallback)"""
    return """<!DOCTYPE html>
<html><head><meta charset="UTF-8">
<style>
  * { margin: 0; padding: 0; box-sizing: border-box; }
  body { width: 1080px; height: 1080px; overflow: hidden;
    font-family: 'Pretendard', 'Noto Sans KR', sans-serif; }
  .container { width: 1080px; height: 1080px; position: relative;
    background: #0D0F12; display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 0; }
  .content { text-align: center; padding: 0 100px; display: flex;
    flex-direction: column; align-items: center; gap: 48px; }
  .eyebrow { font-size: 28px; font-weight: 300; color: #00D4FF;
    letter-spacing: 6px; text-transform: uppercase; }
  .headline { font-size: 96px; font-weight: 900; color: #F5F7FA;
    line-height: 1.1; letter-spacing: -2px; text-align: center; }
  .divider { width: 80px; height: 2px; background: #00D4FF; }
  .sub { font-size: 64px; font-weight: 300; color: #C0C8D0;
    line-height: 1.3; text-align: center; }
  .cta { position: absolute; bottom: 80px; left: 50%;
    transform: translateX(-50%); border: 2px solid #00D4FF;
    color: #00D4FF; font-size: 40px; font-weight: 400;
    padding: 20px 72px; letter-spacing: 3px; text-transform: uppercase;
    white-space: nowrap; }
</style></head><body>
<div class="container">
  <div class="content">
    <div class="eyebrow">T.O.P 사업단</div>
    <div class="headline">열심히는 하는데,<br>월급은 제자리걸음?</div>
    <div class="divider"></div>
    <div class="sub">이제 변속할 시간입니다</div>
  </div>
  <div class="cta">T.O.P 확인하기</div>
</div></body></html>"""


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

def main():
    import argparse
    parser = argparse.ArgumentParser(description="컨셉 #24~#26 하이브리드 이미지 생성")
    parser.add_argument("--concept", choices=["24", "25", "26", "all"], default="all")
    args = parser.parse_args()

    print("=" * 60)
    print("컨셉 이미지 생성 시작 (Gemini 배경 + HTML 오버레이)")
    print("=" * 60)

    # 인증 토큰
    try:
        token = get_auth_token()
    except Exception as e:
        print(f"[오류] 인증 실패: {e}")
        print("[fallback] CSS 단색 배경으로 진행합니다...")
        token = None

    concepts = ["24", "25", "26"] if args.concept == "all" else [args.concept]
    results = {}

    for cid in concepts:
        ok = generate_concept(cid, token)
        results[cid] = ok

    print("\n" + "=" * 60)
    print("생성 결과")
    print("=" * 60)
    for cid, ok in results.items():
        status = "성공" if ok else "실패"
        path = CONCEPTS[cid]["output_dir"] / "sample.png"
        print(f"  #{cid}: {status} → {path}")


if __name__ == "__main__":
    main()
