#!/usr/bin/env python3
"""
setup_auth.py - Firebase Auth 인증 세션 관리

Firebase Admin SDK로 custom token을 생성하고,
Playwright 브라우저에서 signInWithCustomToken을 호출하여 인증 세션을 저장합니다.

Usage:
    python3 setup_auth.py [--output auth/storageState.json] [--uid test-user]
"""

import argparse
import json
import os
import sys
import time


def create_custom_token(uid: str = "test-qc-user") -> str:
    """Firebase Admin SDK로 custom token 생성."""
    try:
        import firebase_admin
        from firebase_admin import auth as firebase_auth, credentials
    except ImportError:
        print("firebase-admin 패키지 필요: pip install firebase-admin", file=sys.stderr)
        return ""

    # 이미 초기화된 앱이 있는지 확인
    try:
        app = firebase_admin.get_app()
    except ValueError:
        cred_path = os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", "")
        if cred_path and os.path.isfile(cred_path):
            cred = credentials.Certificate(cred_path)
        else:
            cred = credentials.ApplicationDefault()
        app = firebase_admin.initialize_app(cred)

    custom_token = firebase_auth.create_custom_token(uid, app=app)
    if isinstance(custom_token, bytes):
        return custom_token.decode("utf-8")
    return str(custom_token)


def save_storage_state(
    base_url: str = "http://localhost:3000",
    custom_token: str = "",
    output_path: str = "",
) -> bool:
    """Playwright로 Firebase signInWithCustomToken 호출 후 storageState 저장."""
    if not output_path:
        output_path = os.path.join(os.path.dirname(__file__), "storageState.json")

    try:
        from playwright.sync_api import sync_playwright
    except ImportError:
        print("playwright 패키지 필요: pip install playwright", file=sys.stderr)
        return False

    os.makedirs(os.path.dirname(os.path.abspath(output_path)), exist_ok=True)

    with sync_playwright() as p:
        browser = p.chromium.launch(headless=True)
        context = browser.new_context()
        page = context.new_page()

        page.goto(base_url)
        page.wait_for_load_state("networkidle")

        # Firebase signInWithCustomToken 실행
        if custom_token:
            page.evaluate(f"""async () => {{
                const {{ getAuth, signInWithCustomToken }} = await import('firebase/auth');
                const auth = getAuth();
                await signInWithCustomToken(auth, '{custom_token}');
            }}""")
            page.wait_for_timeout(3000)

        context.storage_state(path=output_path)
        context.close()
        browser.close()

    return os.path.isfile(output_path)


def verify_storage_state(storage_state_path: str) -> bool:
    """storageState.json 존재 및 유효성 확인."""
    if not os.path.isfile(storage_state_path):
        return False
    try:
        with open(storage_state_path, "r", encoding="utf-8") as f:
            data = json.load(f)
        return "cookies" in data or "origins" in data
    except (json.JSONDecodeError, OSError):
        return False


def check_and_refresh_ttl(
    storage_state_path: str = "",
    max_age_minutes: int = 50,
) -> bool:
    """storageState.json의 TTL 확인. 갱신 필요하면 True 반환.

    - 파일 없으면 True
    - mtime이 max_age_minutes 이상이면 True (갱신 필요)
    - 아직 유효하면 False
    """
    if not storage_state_path:
        storage_state_path = os.path.join(os.path.dirname(__file__), "storageState.json")

    if not os.path.isfile(storage_state_path):
        return True

    mtime = os.path.getmtime(storage_state_path)
    elapsed = time.time() - mtime
    return elapsed >= max_age_minutes * 60


def main() -> None:
    parser = argparse.ArgumentParser(description="Firebase Auth 세션 관리")
    parser.add_argument("--output", default="", help="storageState.json 출력 경로")
    parser.add_argument("--uid", default="test-qc-user", help="Firebase UID")
    parser.add_argument("--base-url", default="http://localhost:3000", help="앱 기본 URL")
    parser.add_argument("--verify-only", action="store_true", help="기존 storageState 유효성만 확인")
    parser.add_argument("--refresh", action="store_true", help="TTL 확인 후 만료 시 storageState 재생성")
    args = parser.parse_args()

    output_path = args.output or os.path.join(os.path.dirname(__file__), "storageState.json")

    if args.refresh:
        needs_refresh = check_and_refresh_ttl(storage_state_path=output_path)
        if not needs_refresh:
            print("[setup_auth] storageState is still valid")
            sys.exit(0)

    if args.verify_only:
        ok = verify_storage_state(output_path)
        print(json.dumps({"valid": ok, "path": output_path}))
        sys.exit(0 if ok else 1)

    print(f"[setup_auth] Custom token 생성 중 (uid={args.uid})...")
    token = create_custom_token(uid=args.uid)
    if not token:
        print(
            "[setup_auth] Custom token 생성 실패. GOOGLE_APPLICATION_CREDENTIALS 환경변수를 확인하세요.",
            file=sys.stderr,
        )
        sys.exit(1)

    print(f"[setup_auth] storageState 저장 중: {output_path}")
    ok = save_storage_state(
        base_url=args.base_url,
        custom_token=token,
        output_path=output_path,
    )

    if ok:
        print(f"[setup_auth] 완료: {output_path}")
    else:
        print("[setup_auth] 실패", file=sys.stderr)
        sys.exit(1)


if __name__ == "__main__":
    main()
