#!/usr/bin/env python3
"""컨셉 #34 한화손해보험 스타일 — 하이브리드 이미지 생성기
Gemini AI 배경 + HTML 텍스트 오버레이 → 1080×1080px PNG
"""

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

import requests
from playwright.sync_api import sync_playwright

# ─── 경로 설정 ───────────────────────────────────────────────────────────────
OUTPUT_DIR = Path("/home/jay/workspace/output/meta-ads/concept-catalog/34-hanwha-style")
BG_PATH = OUTPUT_DIR / "bg.jpg"
TEMPLATE_PATH = OUTPUT_DIR / "template.html"
SAMPLE_PNG = OUTPUT_DIR / "sample.png"
FINAL_PNG = OUTPUT_DIR / "34-hanwha-style.png"

# ─── Gemini API 설정 ──────────────────────────────────────────────────────────
MODEL_ID = "gemini-2.0-flash-preview-image-generation"
FALLBACK_MODEL = "gemini-2.0-flash-exp"
GEMINI_API_BASE = "https://generativelanguage.googleapis.com/v1beta"

GEMINI_PROMPT = (
    "Warm inviting lifestyle background, soft morning light through sheer curtains, "
    "cozy modern Korean home office or cafe environment, wooden desk with coffee cup, "
    "warm golden hour sunlight creating soft bokeh effect, "
    "subtle plants and greenery in soft focus background, "
    "color palette: warm ivory whites (#FFF8F2), soft amber tones, gentle orange highlights, "
    "hints of natural green in background, "
    "no people, no faces, no text, no logos, "
    "emotional warmth and safety, professionally aspirational yet approachable, "
    "1080x1080 pixels, shallow depth of field, natural photography style"
)


def get_gemini_api_key() -> str:
    """GEMINI_API_KEY를 .env 또는 .env.keys에서 로드"""
    import os, re

    key = os.environ.get("GEMINI_API_KEY")
    if key:
        return key

    for env_file in ["/home/jay/workspace/.env", "/home/jay/workspace/.env.keys"]:
        p = Path(env_file)
        if p.exists():
            content = p.read_text(encoding="utf-8")
            m = re.search(r'(?:export\s+)?GEMINI_API_KEY\s*=\s*"?([^"\n]+)"?', content)
            if m:
                return m.group(1).strip()

    raise RuntimeError("GEMINI_API_KEY를 찾을 수 없습니다")


def get_gcloud_token() -> str:
    """gcloud CLI로 access token 획득"""
    import subprocess
    result = subprocess.run(
        ["gcloud", "auth", "print-access-token"],
        capture_output=True, text=True, check=True,
    )
    token = result.stdout.strip()
    if not token:
        raise RuntimeError("빈 토큰 반환")
    return token


def generate_background() -> Path:
    """Gemini API로 배경 이미지 생성"""
    print("─" * 60)
    print("Step 1: Gemini 배경 이미지 생성")
    print("─" * 60)

    # API 키 방식 시도
    try:
        api_key = get_gemini_api_key()
        print(f"  인증: API Key (길이: {len(api_key)})")
        url = f"{GEMINI_API_BASE}/models/gemini-2.0-flash-preview-image-generation:generateContent?key={api_key}"
        headers = {"Content-Type": "application/json"}
        payload = {
            "contents": [{"parts": [{"text": GEMINI_PROMPT}]}],
            "generationConfig": {"responseModalities": ["IMAGE", "TEXT"]},
        }
        print(f"  모델: gemini-2.0-flash-preview-image-generation")
        start = time.time()
        resp = requests.post(url, headers=headers, json=payload, timeout=120)

        if resp.status_code in (400, 404):
            # 모델 이름 변경 시도
            url2 = f"{GEMINI_API_BASE}/models/gemini-2.0-flash-exp:generateContent?key={api_key}"
            print(f"  모델 fallback: gemini-2.0-flash-exp")
            resp = requests.post(url2, headers=headers, json=payload, timeout=120)

        resp.raise_for_status()
        elapsed = time.time() - start

    except Exception as api_err:
        print(f"  API Key 실패: {api_err}. gcloud 토큰으로 재시도...")
        try:
            token = get_gcloud_token()
            print(f"  인증: gcloud Bearer token (길이: {len(token)})")

            # SA 토큰 방식 시도
            try:
                import sys
                sys.path.insert(0, "/home/jay/workspace/tools/ai-image-gen")
                import gcloud_auth
                token = gcloud_auth.get_service_account_token()
                print(f"  인증: SA Bearer token")
            except Exception:
                pass

            for model in ["gemini-2.0-flash-preview-image-generation", "gemini-3.1-flash-image-preview", "gemini-3-pro-image-preview"]:
                url = f"{GEMINI_API_BASE}/models/{model}:generateContent"
                headers = {
                    "Authorization": f"Bearer {token}",
                    "Content-Type": "application/json",
                }
                payload = {
                    "contents": [{"parts": [{"text": GEMINI_PROMPT}]}],
                    "generationConfig": {"responseModalities": ["IMAGE", "TEXT"]},
                }
                print(f"  모델 시도: {model}")
                start = time.time()
                resp = requests.post(url, headers=headers, json=payload, timeout=180)
                if resp.status_code not in (400, 403, 404):
                    resp.raise_for_status()
                    elapsed = time.time() - start
                    break
                print(f"  {model} 실패 (HTTP {resp.status_code})")
            else:
                raise RuntimeError("모든 모델 시도 실패")

        except Exception as e2:
            raise RuntimeError(f"배경 생성 실패: {e2}") from e2

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

    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:
        text_parts = [p.get("text", "") for p in parts if "text" in p]
        raise RuntimeError(f"이미지 데이터 없음. 텍스트: {text_parts[:2]}")

    mime_type = image_part["inlineData"].get("mimeType", "image/jpeg")
    image_bytes = base64.b64decode(image_part["inlineData"]["data"])
    ext = ".jpg" if "jpeg" in mime_type else ".png"
    bg_path = BG_PATH.with_suffix(ext)
    bg_path.write_bytes(image_bytes)

    size_kb = bg_path.stat().st_size / 1024
    print(f"  완료: {bg_path.name} ({size_kb:.0f} KB, {elapsed:.1f}초)")
    return bg_path


def create_html_template(bg_path: Path) -> Path:
    """HTML 텍스트 오버레이 템플릿 생성"""
    print("\n─" * 30)
    print("Step 2: HTML 템플릿 생성")
    print("─" * 60)

    bg_uri = f"file://{bg_path.resolve()}"

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

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

  html, body {{
    width: 1080px;
    height: 1080px;
    overflow: hidden;
    background: #FFF8F2;
  }}

  .canvas {{
    position: relative;
    width: 1080px;
    height: 1080px;
    overflow: hidden;
    font-family: 'Pretendard', 'Noto Sans KR', 'Apple SD Gothic Neo', sans-serif;
  }}

  /* 배경 이미지 레이어 */
  .bg-layer {{
    position: absolute;
    top: 0; left: 0;
    width: 1080px;
    height: 1080px;
    background-image: url('{bg_uri}');
    background-size: cover;
    background-position: center;
  }}

  /* 아이보리 반투명 오버레이 */
  .overlay {{
    position: absolute;
    top: 0; left: 0;
    width: 1080px;
    height: 1080px;
    background: rgba(255, 248, 242, 0.82);
  }}

  /* 콘텐츠 레이어 */
  .content {{
    position: absolute;
    top: 0; left: 0;
    width: 1080px;
    height: 1080px;
    padding: 56px 72px;
    display: flex;
    flex-direction: column;
  }}

  /* 상단 헤더 */
  .header {{
    display: flex;
    justify-content: space-between;
    align-items: center;
    width: 100%;
    margin-bottom: 16px;
  }}

  .brand-name {{
    font-size: 40px;
    font-weight: 400;
    color: #4A4A4A;
    letter-spacing: 0.08em;
  }}

  .header-tag {{
    font-size: 40px;
    font-weight: 500;
    color: #FF6B35;
    letter-spacing: 0.05em;
  }}

  /* 오렌지 상단 구분선 */
  .orange-line {{
    width: 300px;
    height: 4px;
    background: #FF6B35;
    border-radius: 2px;
    margin-bottom: 28px;
    flex-shrink: 0;
  }}

  /* 메인 헤드라인 */
  .main-headline {{
    margin-bottom: 20px;
    flex-shrink: 0;
  }}

  .headline-line1 {{
    font-size: 96px;
    font-weight: 800;
    color: #2C2C2C;
    letter-spacing: -0.01em;
    line-height: 1.15;
    display: block;
  }}

  .headline-line2 {{
    font-size: 96px;
    font-weight: 800;
    color: #FF6B35;
    letter-spacing: -0.015em;
    line-height: 1.15;
    display: block;
  }}

  /* 공감 서브카피 */
  .empathy-copy {{
    font-size: 44px;
    font-weight: 400;
    color: #4A4A4A;
    line-height: 1.45;
    letter-spacing: 0.00em;
    margin-bottom: 24px;
    flex-shrink: 0;
  }}

  /* 해결책 카드 */
  .solution-card {{
    background: #FFFFFF;
    border-left: 5px solid #FF6B35;
    border-radius: 12px;
    padding: 28px 36px;
    margin-bottom: 24px;
    box-shadow: 0 4px 20px rgba(255, 107, 53, 0.10);
    flex-shrink: 0;
  }}

  .solution-main {{
    font-size: 60px;
    font-weight: 700;
    color: #FF6B35;
    letter-spacing: -0.005em;
    line-height: 1.3;
    display: block;
    margin-bottom: 10px;
  }}

  .solution-sub {{
    font-size: 44px;
    font-weight: 400;
    color: #4A4A4A;
    letter-spacing: 0.01em;
    line-height: 1.4;
    display: block;
  }}

  /* 혜택 배지 행 */
  .badges {{
    display: flex;
    flex-wrap: nowrap;
    gap: 12px;
    margin-bottom: 24px;
    flex-shrink: 0;
  }}

  .badge-orange {{
    background: rgba(255, 107, 53, 0.12);
    border: 1.5px solid rgba(255, 107, 53, 0.40);
    color: #FF6B35;
    font-size: 40px;
    font-weight: 600;
    padding: 10px 22px;
    border-radius: 24px;
    display: inline-block;
    letter-spacing: 0.03em;
    white-space: nowrap;
  }}

  .badge-green {{
    background: rgba(43, 168, 96, 0.12);
    border: 1.5px solid rgba(43, 168, 96, 0.40);
    color: #2BA860;
    font-size: 40px;
    font-weight: 600;
    padding: 10px 22px;
    border-radius: 24px;
    display: inline-block;
    letter-spacing: 0.03em;
    white-space: nowrap;
  }}

  /* CTA 버튼 */
  .cta-wrap {{
    margin-bottom: 20px;
    flex-shrink: 0;
  }}

  .cta-btn {{
    display: inline-block;
    background: #FF6B35;
    color: #FFFFFF;
    font-size: 44px;
    font-weight: 700;
    padding: 22px 56px;
    border-radius: 12px;
    letter-spacing: 0.04em;
    box-shadow: 0 6px 24px rgba(255, 107, 53, 0.30);
    white-space: nowrap;
  }}

  /* 하단 가로선 */
  .bottom-line {{
    width: 100%;
    height: 2px;
    background: rgba(255, 107, 53, 0.25);
    margin-bottom: 14px;
    flex-shrink: 0;
  }}

  /* 하단 서브텍스트 */
  .footer-text {{
    font-size: 40px;
    font-weight: 300;
    color: #6B6B6B;
    letter-spacing: 0.03em;
    text-align: center;
    flex-shrink: 0;
  }}
</style>
</head>
<body>
<div class="canvas">
  <!-- 배경 이미지 -->
  <div class="bg-layer"></div>
  <!-- 아이보리 반투명 오버레이 -->
  <div class="overlay"></div>

  <!-- 텍스트 콘텐츠 -->
  <div class="content">

    <!-- 상단 헤더 -->
    <div class="header">
      <span class="brand-name">T.O.P 사업단</span>
      <span class="header-tag">함께 성장하는 팀</span>
    </div>

    <!-- 오렌지 구분선 -->
    <div class="orange-line"></div>

    <!-- 메인 헤드라인 -->
    <div class="main-headline">
      <span class="headline-line1">고객 없어서</span>
      <span class="headline-line2">매일이 전쟁인가요?</span>
    </div>

    <!-- 공감 서브카피 -->
    <div class="empathy-copy">
      지인에게 아쉬운 소리 하고,<br>
      거절받고, 상처받는 영업은 이제 그만.
    </div>

    <!-- 해결책 카드 -->
    <div class="solution-card">
      <span class="solution-main">30여종 무상 DB가 그 전쟁을 끝냅니다</span>
      <span class="solution-sub">설계 매니저 + 서포트 매니저, 당신 곁에</span>
    </div>

    <!-- 혜택 배지 -->
    <div class="badges">
      <span class="badge-orange">1:1 밀착 코칭</span>
      <span class="badge-orange">신입 최대 1,000만원</span>
      <span class="badge-green">무상 DB</span>
    </div>

    <!-- CTA 버튼 -->
    <div class="cta-wrap">
      <span class="cta-btn">T.O.P와 함께 시작하기 →</span>
    </div>

    <!-- 하단 구분선 -->
    <div class="bottom-line"></div>

    <!-- 하단 푸터 -->
    <div class="footer-text">고객도, 성장도 혼자 하지 않습니다 · 인카금융서비스 코스닥 상장</div>

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

    TEMPLATE_PATH.write_text(html, encoding="utf-8")
    print(f"  저장: {TEMPLATE_PATH}")
    return TEMPLATE_PATH


def capture_image(template_path: Path, output_paths: list[Path]) -> None:
    """Playwright로 HTML 스크린샷 → PNG 저장"""
    print("\n─" * 30)
    print("Step 3: Playwright 캡처")
    print("─" * 60)

    template_url = f"file://{template_path.resolve()}"

    with sync_playwright() as p:
        browser = p.chromium.launch(args=["--font-render-hinting=none"])
        try:
            page = browser.new_page(viewport={"width": 1080, "height": 1080})
            page.goto(template_url, wait_until="networkidle")

            # 폰트 로딩 대기
            page.evaluate("() => document.fonts.ready")
            page.wait_for_timeout(2000)

            for out_path in output_paths:
                out_path.parent.mkdir(parents=True, exist_ok=True)
                page.screenshot(path=str(out_path), type="png", clip={"x": 0, "y": 0, "width": 1080, "height": 1080})
                size_kb = out_path.stat().st_size / 1024
                print(f"  저장: {out_path} ({size_kb:.0f} KB)")
        finally:
            browser.close()


def main():
    OUTPUT_DIR.mkdir(parents=True, exist_ok=True)

    print("=" * 60)
    print("컨셉 #34 — 한화손해보험 스타일 이미지 생성")
    print("=" * 60)

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

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

    # Step 3: 캡처
    capture_image(template_path, [SAMPLE_PNG, FINAL_PNG])

    print("\n" + "=" * 60)
    print("완료!")
    print(f"  sample.png  → {SAMPLE_PNG}")
    print(f"  final.png   → {FINAL_PNG}")
    print(f"  template    → {TEMPLATE_PATH}")
    print("=" * 60)


if __name__ == "__main__":
    main()
