from flask import Blueprint, request, jsonify, session, current_app, make_response
from src.models.user import db, User
from src.models.subscription import UserProfile, OAuthAccount, OAuthProvider
import requests
import json
import os
from datetime import datetime, timedelta
import re
import secrets
import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
from werkzeug.security import generate_password_hash
import hashlib
import base64
from urllib.parse import urlencode, quote
from src.config.env_loader import env
from src.utils.user_ref import (
    get_user_by_session_value,
    allocate_unique_user_id_from_email,
    allocate_unique_user_id_oauth,
    resolve_user_ref,
)

auth_bp = Blueprint('auth', __name__)

# 비밀번호 재설정 코드 저장용 (실제로는 Redis나 데이터베이스 사용 권장)
password_reset_codes = {}

# 이메일 인증 코드 저장용 (실제로는 Redis나 데이터베이스 사용 권장)
email_verification_codes = {}

def verify_hcaptcha(token):
    """hCaptcha 토큰 검증"""
    try:
        # hCaptcha 검증 API 호출
        response = requests.post('https://hcaptcha.com/siteverify', data={
            'secret': os.getenv('HCAPTCHA_SECRET_KEY', '0x0000000000000000000000000000000000000000'),  # 테스트용 시크릿 키
            'response': token
        })
        
        result = response.json()
        print(f"hCaptcha 검증 결과: {result}")
        
        return result.get('success', False)
    except Exception as e:
        print(f"hCaptcha 검증 오류: {str(e)}")
        return False

# 환경에 따라 URL 동적 설정
def get_front_url():
    """프론트엔드 URL 반환 (환경별)"""
    front_url = os.environ.get('FRONT_URL')
    if front_url:
        return front_url
    # 환경 변수가 없으면 환경에 따라 기본값 설정
    if env.is_production:
        return 'https://mlink.sellmall.co.kr'
    return 'http://localhost:3001'

# OAuth 설정
OAUTH_CONFIG = {
    'kakao': {
        'client_id': os.getenv('KAKAO_CLIENT_ID'),
        'client_secret': os.getenv('KAKAO_CLIENT_SECRET'),
        'redirect_uri': os.getenv('KAKAO_REDIRECT_URI', f'{get_front_url()}/auth/oauth/kakao/callback'),
        'auth_url': 'https://kauth.kakao.com/oauth/authorize',
        'token_url': 'https://kauth.kakao.com/oauth/token',
        'user_info_url': 'https://kapi.kakao.com/v2/user/me'
    },
    'naver': {
        'client_id': os.getenv('NAVER_CLIENT_ID'),
        'client_secret': os.getenv('NAVER_CLIENT_SECRET'),
        'redirect_uri': os.getenv('NAVER_REDIRECT_URI', f'{get_front_url()}/auth/oauth/naver/callback'),
        'auth_url': 'https://nid.naver.com/oauth2.0/authorize',
        'token_url': 'https://nid.naver.com/oauth2.0/token',
        'user_info_url': 'https://openapi.naver.com/v1/nid/me',
        "scope": [],
    },
    'google': {
        'client_id': os.getenv('GOOGLE_CLIENT_ID'),
        'client_secret': os.getenv('GOOGLE_CLIENT_SECRET'),
        'redirect_uri': os.getenv('GOOGLE_REDIRECT_URI', f'{get_front_url()}/auth/oauth/google/callback'),
        'auth_url': 'https://accounts.google.com/o/oauth2/v2/auth',
        'token_url': 'https://oauth2.googleapis.com/token',
        'user_info_url': 'https://www.googleapis.com/oauth2/v2/userinfo',
        "scope": ["email", "profile"],
    }
}

# 환경변수 검증
def validate_oauth_config():
    """OAuth 설정 검증"""
    missing_vars = []
    
    for provider, config in OAUTH_CONFIG.items():
        if not config['client_id']:
            missing_vars.append(f'{provider.upper()}_CLIENT_ID')
        if not config['client_secret']:
            missing_vars.append(f'{provider.upper()}_CLIENT_SECRET')
    
    if missing_vars:
        print(f"⚠️  OAuth 환경변수가 설정되지 않았습니다: {', '.join(missing_vars)}")
        print("📝 .env 파일을 생성하고 필요한 환경변수를 설정해주세요.")
        return False
    
    print("✅ OAuth 환경변수가 모두 설정되었습니다.")
    return True

# 애플리케이션 시작 시 환경변수 검증
validate_oauth_config()

def _generate_state():
    # 매 요청마다 다른 값
    return os.urandom(16).hex()

@auth_bp.route('/api/auth/oauth/<provider>/login', methods=['GET'])
def oauth_login(provider):
    """OAuth 로그인 URL 생성"""
    if provider not in OAUTH_CONFIG:
        return jsonify({'error': '지원하지 않는 OAuth 제공자입니다.'}), 400
    
    # 기존 사용자 세션 정보만 삭제 (OAuth state는 유지하기 위해)
    # 다른 계정으로 로그인하기 위해 기존 사용자 정보 제거
    if 'user_id' in session:
        del session['user_id']
    if 'username' in session:
        del session['username']
    
    config = OAUTH_CONFIG[provider]

    # state 생성 & 세션에 저장 (콜백에서 이 값 검증 필요)
    state = _generate_state()
    session[f'oauth_state_{provider}'] = state

    # 공통 파라미터
    params = {
        "client_id": config["client_id"],
        "redirect_uri": config["redirect_uri"],  # 아래에서 urlencode로 전체를 처리
        "response_type": "code",
        "state": state,
    }
    # provider별 옵션
    if provider == "google":
        # scope를 공백으로 join 후 전체를 urlencode에 태움
        params["scope"] = " ".join(config.get("scope", ["email", "profile"]))
        params["access_type"] = "offline"  # refresh_token 받기 위함
        # 필요하면 prompt=consent 추가
        # params["prompt"] = "consent"
    elif provider == "naver":
        # 네이버는 위에 있는 값들로 충분. scope 필요하면 추가
        pass

    # 최종 URL
    query = urlencode(params, quote_via=quote)
    auth_url = f"{config['auth_url']}?{query}"

    return jsonify({'auth_url': auth_url})
    

# 처리된 코드를 추적하기 위한 전역 변수 (실제 운영에서는 Redis나 DB 사용 권장)
processed_codes = set()

@auth_bp.route('/api/auth/oauth/<provider>/callback', methods=['GET', 'POST'])
def oauth_callback(provider):
    """OAuth 콜백 처리"""
    print(f"=== OAuth 콜백 시작: {provider} ===")
    print(f"요청 메서드: {request.method}")
    print(f"요청 헤더: {dict(request.headers)}")
    
    if provider not in OAUTH_CONFIG:
        print(f"지원하지 않는 OAuth 제공자: {provider}")
        return jsonify({'error': '지원하지 않는 OAuth 제공자입니다.'}), 400
    
    # GET 요청의 경우 query string에서 code 추출, POST의 경우 body에서 추출
    if request.method == 'GET':
        code = request.args.get('code')
        state = request.args.get('state')
        error = request.args.get('error')
        
        # GET 요청에서 받은 state를 세션에 저장 (네이버용)
        if state and provider == 'naver':
            session[f'oauth_state_{provider}'] = state
        
        if error:
            print(f"OAuth 에러: {error}")
            # GET 요청인 경우 HTML 에러 페이지 반환 (이미 request.method == 'GET' 블록 안에 있음)
            html = f"""
                <!DOCTYPE html>
                <html lang="ko">
                <head>
                    <meta charset="UTF-8">
                    <meta name="viewport" content="width=device-width, initial-scale=1.0">
                    <title>로그인 실패</title>
                    <style>
                        body {{
                            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
                            display: flex;
                            justify-content: center;
                            align-items: center;
                            min-height: 100vh;
                            margin: 0;
                            background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
                            color: #333;
                        }}
                        .container {{
                            background: white;
                            border-radius: 16px;
                            padding: 40px;
                            box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
                            text-align: center;
                            max-width: 400px;
                            width: 90%;
                        }}
                        .error-icon {{
                            width: 80px;
                            height: 80px;
                            margin: 0 auto 20px;
                            background: #ef4444;
                            border-radius: 50%;
                            display: flex;
                            align-items: center;
                            justify-content: center;
                            font-size: 40px;
                            color: white;
                        }}
                        h1 {{
                            margin: 0 0 10px;
                            font-size: 24px;
                            font-weight: 600;
                            color: #1f2937;
                        }}
                        p {{
                            margin: 0 0 20px;
                            color: #6b7280;
                            font-size: 14px;
                        }}
                    </style>
                </head>
                <body>
                    <div class="container">
                        <div class="error-icon">✕</div>
                        <h1>로그인 실패</h1>
                        <p>인증 과정에서 오류가 발생했습니다.</p>
                        <script>
                            if (window.opener) {{
                                setTimeout(() => {{
                                    window.close();
                                }}, 5000);
                            }}
                        </script>
                    </div>
                    </body>
                </html>
                """
            return html, 400, {'Content-Type': 'text/html; charset=utf-8'}
    else:
        data = request.get_json() or {}
        code = data.get('code')
        state = data.get('state')
        
        # POST 요청에서 state가 없으면 세션에서 가져오기 시도 (네이버용)
        if not state and provider == 'naver':
            state = session.get(f'oauth_state_{provider}')
    
    print(f"요청 데이터: code={'있음' if code else '없음'}, state={state}")
    
    if not code:
        print("인증 코드가 없습니다.")
        # GET 요청인 경우 HTML 에러 페이지 반환
        if request.method == 'GET':
            html = """
            <!DOCTYPE html>
            <html lang="ko">
            <head>
                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <title>로그인 실패</title>
                <style>
                    body {
                        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
                        display: flex;
                        justify-content: center;
                        align-items: center;
                        min-height: 100vh;
                        margin: 0;
                        background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
                        color: #333;
                    }
                    .container {
                        background: white;
                        border-radius: 16px;
                        padding: 40px;
                        box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
                        text-align: center;
                        max-width: 400px;
                        width: 90%;
                    }
                    .error-icon {
                        width: 80px;
                        height: 80px;
                        margin: 0 auto 20px;
                        background: #ef4444;
                        border-radius: 50%;
                        display: flex;
                        align-items: center;
                        justify-content: center;
                        font-size: 40px;
                        color: white;
                    }
                    h1 {
                        margin: 0 0 10px;
                        font-size: 24px;
                        font-weight: 600;
                        color: #1f2937;
                    }
                    p {
                        margin: 0 0 20px;
                        color: #6b7280;
                        font-size: 14px;
                    }
                </style>
            </head>
            <body>
                <div class="container">
                    <div class="error-icon">✕</div>
                    <h1>로그인 실패</h1>
                    <p>인증 코드를 받을 수 없었습니다.</p>
                    <script>
                        if (window.opener) {
                            setTimeout(() => {
                                window.close();
                            }, 5000);
                        }
                    </script>
                </div>
            </body>
            </html>
            """
            return html, 400, {'Content-Type': 'text/html; charset=utf-8'}
        return jsonify({'error': '인증 코드가 없습니다.'}), 400
    
    # 중복 처리 방지
    if code in processed_codes:
        print(f"이미 처리된 코드입니다: {code[:20]}...")
        # POST 요청이고 세션이 유효한 경우 성공 응답 반환
        if request.method == 'POST' and session.get('user_id'):
            print(f"코드가 이미 처리되었지만 세션이 유효합니다. user_id: {session.get('user_id')}")
            try:
                from src.models.user import User
                user = get_user_by_session_value(session.get('user_id'))
                if user:
                    print(f"세션 기반 로그인 성공: user_id={user.user_id}")
                    return jsonify({
                        'message': 'OAuth 로그인 성공',
                        'user': user.to_dict()
                    }), 200
            except Exception as e:
                print(f"세션 기반 사용자 조회 실패: {str(e)}")
        return jsonify({'error': '이미 처리된 인증 코드입니다.'}), 400
    
    # 코드를 처리 중으로 표시
    processed_codes.add(code)
    
    try:
        print(f"OAuth 콜백 처리 시작: {provider}")
        print(f"인증 코드: {code[:20]}...")
        
        # 액세스 토큰 획득
        print("=== 토큰 획득 시작 ===")
        token_data = get_oauth_token(provider, code)
        if not token_data:
            print(f"토큰 획득 실패: {provider}")
            
            # invalid_grant 에러인 경우 (코드가 이미 사용됨)
            # GET 요청에서 이미 처리되었을 수 있으므로 세션 확인
            if request.method == 'POST' and session.get('user_id'):
                print(f"코드가 이미 사용되었지만 세션이 유효합니다. user_id: {session.get('user_id')}")
                # 세션이 유효하면 사용자 정보 조회하여 성공 응답 반환
                try:
                    from src.models.user import User
                    user = get_user_by_session_value(session.get('user_id'))
                    if user:
                        print(f"세션 기반 로그인 성공: user_id={user.user_id}")
                        # 코드 제거하지 않음 (이미 처리됨)
                        return jsonify({
                            'message': 'OAuth 로그인 성공',
                            'user': user.to_dict()
                        }), 200
                except Exception as e:
                    print(f"세션 기반 사용자 조회 실패: {str(e)}")
            
            # 실패 시 코드 제거
            processed_codes.discard(code)
            return jsonify({'error': '토큰 획득에 실패했습니다.'}), 400
        
        print(f"토큰 획득 성공: {provider}")
        print(f"토큰 데이터: {token_data}")
        
        # 사용자 정보 획득
        print("=== 사용자 정보 획득 시작 ===")
        user_info = get_oauth_user_info(provider, token_data['access_token'])
        if not user_info:
            print(f"사용자 정보 획득 실패: {provider}")
            # 실패 시 코드 제거
            processed_codes.discard(code)
            return jsonify({'error': '사용자 정보 획득에 실패했습니다.'}), 400
        
        print(f"사용자 정보 획득 성공: {provider}")
        print(f"사용자 정보: {user_info}")
        
        # 사용자 생성 또는 로그인
        print("=== 사용자 생성/로그인 시작 ===")
        user = create_or_login_oauth_user(provider, user_info, token_data)
        if not user:
            processed_codes.discard(code)
            return jsonify({'error': 'OAuth 로그인 처리에 실패했습니다. 다시 시도해 주세요.'}), 500
        
        # 기존 세션 완전히 정리 (다른 계정으로 로그인하기 위해)
        # OAuth state는 이미 검증 완료되었으므로 삭제해도 됨
        session.clear()
        
        # 새로운 세션에 사용자 정보 저장
        session['user_id'] = user.user_id
        session['username'] = user.username
        # 세션을 명시적으로 저장
        session.permanent = True
        
        print(f"OAuth 로그인 성공: {provider}, user_id: {user.user_id}")
        print(f"세션 정보: user_id={session.get('user_id')}, username={session.get('username')}")
        
        # 성공 시 코드 제거 (메모리 정리)
        processed_codes.discard(code)
        
        # GET 요청인 경우 HTML 페이지 반환 (팝업 창에서 표시)
        if request.method == 'GET':
            # 프론트엔드 URL 가져오기 (환경 변수 또는 기본값)
            front_url = get_front_url()
            
            html = f"""
            <!DOCTYPE html>
            <html lang="ko">
            <head>
                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <title>로그인 완료</title>
                <style>
                    body {{
                        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
                        display: flex;
                        justify-content: center;
                        align-items: center;
                        min-height: 100vh;
                        margin: 0;
                        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                        color: #333;
                    }}
                    .container {{
                        background: white;
                        border-radius: 16px;
                        padding: 40px;
                        box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
                        text-align: center;
                        max-width: 400px;
                        width: 90%;
                    }}
                    .success-icon {{
                        width: 80px;
                        height: 80px;
                        margin: 0 auto 20px;
                        background: #10b981;
                        border-radius: 50%;
                        display: flex;
                        align-items: center;
                        justify-content: center;
                        animation: scaleIn 0.5s ease-out;
                    }}
                    .checkmark {{
                        width: 40px;
                        height: 40px;
                        stroke: white;
                        stroke-width: 4;
                        stroke-linecap: round;
                        stroke-linejoin: round;
                        fill: none;
                    }}
                    @keyframes scaleIn {{
                        from {{
                            transform: scale(0);
                        }}
                        to {{
                            transform: scale(1);
                        }}
                    }}
                    h1 {{
                        margin: 0 0 10px;
                        font-size: 24px;
                        font-weight: 600;
                        color: #1f2937;
                    }}
                    p {{
                        margin: 0 0 20px;
                        color: #6b7280;
                        font-size: 14px;
                    }}
                    .user-info {{
                        background: #f9fafb;
                        border-radius: 8px;
                        padding: 16px;
                        margin: 20px 0;
                        text-align: left;
                    }}
                    .user-info-item {{
                        display: flex;
                        justify-content: space-between;
                        padding: 8px 0;
                        border-bottom: 1px solid #e5e7eb;
                    }}
                    .user-info-item:last-child {{
                        border-bottom: none;
                    }}
                    .label {{
                        font-weight: 500;
                        color: #6b7280;
                        font-size: 13px;
                    }}
                    .value {{
                        color: #1f2937;
                        font-size: 13px;
                    }}
                    .message {{
                        color: #10b981;
                        font-size: 13px;
                        margin-top: 16px;
                        font-weight: 500;
                    }}
                </style>
            </head>
            <body>
                <div class="container">
                    <div class="success-icon">
                        <svg class="checkmark" viewBox="0 0 52 52">
                            <path d="M14.1 27.2l7.1 7.2 16.7-16.8" stroke-dasharray="100" stroke-dashoffset="100">
                                <animate attributeName="stroke-dashoffset" values="100;0" dur="0.6s" fill="freeze"/>
                            </path>
                        </svg>
                    </div>
                    <h1>로그인 완료</h1>
                    <p>성공적으로 로그인되었습니다.</p>
                    <div class="user-info">
                        <div class="user-info-item">
                            <span class="label">이메일</span>
                            <span class="value">{user.email}</span>
                        </div>
                        <div class="user-info-item">
                            <span class="label">사용자명</span>
                            <span class="value">{user.username}</span>
                        </div>
                    </div>
                    <p class="message">잠시 후 창이 자동으로 닫힙니다.</p>
                    <script>
                        // 부모 창에 메시지 전송
                        if (window.opener) {{
                            window.opener.postMessage({{
                                type: 'oauth_callback',
                                code: '{code}',
                                provider: '{provider}',
                                success: true
                            }}, window.location.origin);
                            
                            // 5초 후 창 닫기
                            setTimeout(() => {{
                                window.close();
                            }}, 5000);
                        }} else {{
                            // 팝업이 아닌 경우 메인 페이지로 리다이렉트
                            setTimeout(() => {{
                                window.location.href = '{front_url}';
                            }}, 5000);
                        }}
                    </script>
                </div>
            </body>
            </html>
            """
            return html, 200, {'Content-Type': 'text/html; charset=utf-8'}
        
        # POST 요청인 경우 JSON 반환
        return jsonify({
            'message': 'OAuth 로그인 성공',
            'user': user.to_dict()
        }), 200
        
    except Exception as e:
        print(f"OAuth 로그인 실패: {provider}, error: {str(e)}")
        import traceback
        print(f"에러 상세: {traceback.format_exc()}")
        
        # 중복 이메일 오류인지 확인
        if "Duplicate entry" in str(e) and "user.email" in str(e):
            error_message = "이미 가입된 이메일 주소입니다. 다른 로그인 방법을 사용해주세요."
        else:
            error_message = f'OAuth 로그인 실패: {str(e)}'
        
        # 실패 시 코드 제거
        processed_codes.discard(code)
        
        # GET 요청인 경우 HTML 에러 페이지 반환
        if request.method == 'GET':
            html = f"""
            <!DOCTYPE html>
            <html lang="ko">
            <head>
                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <title>로그인 실패</title>
                <style>
                    body {{
                        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
                        display: flex;
                        justify-content: center;
                        align-items: center;
                        min-height: 100vh;
                        margin: 0;
                        background: linear-gradient(135deg, #f093fb 0%, #f5576c 100%);
                        color: #333;
                    }}
                    .container {{
                        background: white;
                        border-radius: 16px;
                        padding: 40px;
                        box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3);
                        text-align: center;
                        max-width: 400px;
                        width: 90%;
                    }}
                    .error-icon {{
                        width: 80px;
                        height: 80px;
                        margin: 0 auto 20px;
                        background: #ef4444;
                        border-radius: 50%;
                        display: flex;
                        align-items: center;
                        justify-content: center;
                        font-size: 40px;
                        color: white;
                    }}
                    h1 {{
                        margin: 0 0 10px;
                        font-size: 24px;
                        font-weight: 600;
                        color: #1f2937;
                    }}
                    p {{
                        margin: 0 0 20px;
                        color: #6b7280;
                        font-size: 14px;
                    }}
                    .error-message {{
                        background: #fef2f2;
                        border: 1px solid #fecaca;
                        border-radius: 8px;
                        padding: 12px;
                        margin: 20px 0;
                        color: #dc2626;
                        font-size: 13px;
                    }}
                </style>
            </head>
            <body>
                <div class="container">
                    <div class="error-icon">✕</div>
                    <h1>로그인 실패</h1>
                    <div class="error-message">{error_message}</div>
                    <script>
                        if (window.opener) {{
                            setTimeout(() => {{
                                window.close();
                            }}, 5000);
                        }}
                    </script>
                </div>
            </body>
            </html>
            """
            return html, 500, {'Content-Type': 'text/html; charset=utf-8'}
        
        return jsonify({'error': error_message}), 500

def get_oauth_token(provider, code):
    """OAuth 액세스 토큰 획득"""
    config = OAUTH_CONFIG[provider]
    
    # application/x-www-form-urlencoded 형식으로 데이터 준비
    token_data = {
        'client_id': config['client_id'],
        'client_secret': config['client_secret'],
        'code': code,
        'grant_type': 'authorization_code'
    }
    
    if provider == 'kakao':
        token_data['redirect_uri'] = config['redirect_uri']
    elif provider == 'naver':
        # 네이버는 state를 세션에서 가져와야 함
        # 하지만 get_oauth_token 함수는 독립적으로 호출되므로
        # state는 콜백 함수에서 전달받아야 함
        # 일단 기본값 사용 (실제로는 콜백에서 state를 전달해야 함)
        from flask import session
        state = session.get(f'oauth_state_{provider}')
        if state:
            token_data['state'] = state
        else:
            # state가 없으면 기본값 사용 (하지만 네이버는 state 검증을 하므로 문제가 될 수 있음)
            print("경고: 네이버 state가 세션에 없습니다.")
    elif provider == 'google':
        token_data['redirect_uri'] = config['redirect_uri']
    
    # Content-Type 헤더를 application/x-www-form-urlencoded로 설정
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded'
    }
    
    print(f"토큰 요청 데이터: {token_data}")
    print(f"토큰 URL: {config['token_url']}")
    
    response = requests.post(config['token_url'], data=token_data, headers=headers)
    
    print(f"토큰 응답 상태: {response.status_code}")
    print(f"토큰 응답 내용: {response.text}")
    
    if response.status_code == 200:
        token_response = response.json()
        # 네이버는 200 응답이 와도 error 필드가 있으면 실패
        if 'error' in token_response:
            print(f"OAuth 토큰 요청 실패 (200 응답이지만 error 포함): {token_response}")
            return None
        # access_token이 없으면 실패
        if 'access_token' not in token_response:
            print(f"OAuth 토큰 응답에 access_token이 없습니다: {token_response}")
            return None
        return token_response
    elif response.status_code == 400:
        error_data = response.json()
        if error_data.get('error') in ['invalid_grant', 'invalid_request']:
            print("OAuth 코드가 이미 사용되었거나 만료되었습니다.")
            return None
        else:
            print(f"OAuth 토큰 요청 실패: {error_data}")
            return None
    else:
        print(f"토큰 요청 실패: {response.status_code} - {response.text}")
        return None

def get_oauth_user_info(provider, access_token):
    """OAuth 사용자 정보 획득"""
    config = OAUTH_CONFIG[provider]
    
    headers = {}
    if provider == 'kakao':
        headers['Authorization'] = f'Bearer {access_token}'
    elif provider == 'naver':
        headers['Authorization'] = f'Bearer {access_token}'
    elif provider == 'google':
        headers['Authorization'] = f'Bearer {access_token}'
    
    print(f"사용자 정보 요청 URL: {config['user_info_url']}")
    print(f"사용자 정보 요청 헤더: {headers}")
    
    response = requests.get(config['user_info_url'], headers=headers)
    
    print(f"사용자 정보 응답 상태: {response.status_code}")
    print(f"사용자 정보 응답 내용: {response.text}")
    
    if response.status_code == 200:
        return response.json()
    else:
        print(f"사용자 정보 요청 실패: {response.status_code} - {response.text}")
        return None

def create_or_login_oauth_user(provider, user_info, token_data):
    """OAuth 사용자 생성 또는 로그인"""
    provider_enum = OAuthProvider(provider)
    
    # OAuth 제공자별 사용자 정보 추출 (provider_user_id는 DB 비교용으로 항상 str)
    if provider == 'kakao':
        provider_user_id = str(user_info['id'])
        email = user_info.get('kakao_account', {}).get('email')
        username = user_info.get('properties', {}).get('nickname', f'kakao_{provider_user_id}')
    elif provider == 'naver':
        provider_user_id = str(user_info['response']['id'])
        email = user_info['response'].get('email')
        # Naver는 provider_user_id가 길 수 있으므로 해시 처리
        raw_username = user_info['response'].get('nickname', f'naver_{provider_user_id}')
        # username이 너무 길면 해시 처리 (255자 제한)
        if len(raw_username) > 200:
            import hashlib
            username_hash = hashlib.sha256(raw_username.encode()).hexdigest()[:16]
            username = f'naver_{username_hash}'
        else:
            username = raw_username
    elif provider == 'google':
        provider_user_id = str(user_info['id'])
        email = user_info['email']
        raw_username = user_info.get('name', f'google_{provider_user_id}')
        # username이 너무 길면 해시 처리 (255자 제한)
        if len(raw_username) > 200:
            import hashlib
            username_hash = hashlib.sha256(raw_username.encode()).hexdigest()[:16]
            username = f'google_{username_hash}'
        else:
            username = raw_username
    
    # 기존 OAuth 계정 확인
    oauth_account = OAuthAccount.query.filter_by(
        provider=provider_enum,
        provider_user_id=provider_user_id
    ).first()
    
    if oauth_account:
        profile = oauth_account.user_profile
        if profile is None:
            # 손상된 OAuth 행 → 삭제 후 이메일 매칭/신규 가입 로직으로 진행
            print("경고: OAuthAccount에 연결된 UserProfile이 없음 — 레코드 삭제 후 재연결")
            db.session.delete(oauth_account)
            db.session.commit()
        else:
            # 기존 사용자 로그인 (마이그레이션 후 relationship이 비는 경우 대비)
            user = profile.user
            if user is None:
                user = resolve_user_ref(profile.user_id)
            if user is None and email:
                existing = User.query.filter_by(email=email).first()
                if existing:
                    profile.user_id = existing.user_id
                    db.session.flush()
                    user = existing
            if user is None:
                raise ValueError(
                    "OAuth 계정은 있으나 연결된 사용자를 찾을 수 없습니다. "
                    "관리자에게 문의하거나 이메일 로그인을 이용해 주세요."
                )
            oauth_account.access_token = token_data['access_token']
            oauth_account.refresh_token = token_data.get('refresh_token')
            if 'expires_in' in token_data:
                expires_in = token_data.get('expires_in', 0)
                oauth_account.expires_at = datetime.now() + timedelta(seconds=int(token_data['expires_in']))
            oauth_account.updated_at = datetime.now()
            db.session.commit()
            return user
    
    # 이메일 중복 체크
    if email:
        existing_user = User.query.filter_by(email=email).first()
        if existing_user:
            # 기존 사용자가 있으면 해당 사용자와 OAuth 계정 연결
            print(f"기존 이메일 사용자 발견: {email}, 기존 사용자 ID: {existing_user.id}")
            
            # 기존 사용자의 프로필 확인
            profile = existing_user.profile
            if not profile:
                # 프로필이 없으면 생성
                profile = UserProfile(user_id=existing_user.user_id)
                db.session.add(profile)
                db.session.flush()
            
            # OAuth 계정 생성 (기존 사용자와 연결)
            oauth_account = OAuthAccount(
                user_profile_id=profile.id,
                provider=provider_enum,
                provider_user_id=provider_user_id,
                access_token=token_data['access_token'],
                refresh_token=token_data.get('refresh_token')
            )
            if 'expires_in' in token_data:
                # oauth_account.expires_at = datetime.now() + timedelta(seconds=token_data['expires_in'])
                expires_in = token_data.get('expires_in', 0)
                oauth_account.expires_at = datetime.now() + timedelta(seconds=int(token_data['expires_in']))
            
            db.session.add(oauth_account)
            db.session.commit()
            return existing_user
    
    # 새 사용자 생성 (OAuth 사용자는 임시 비밀번호 설정)
    uid = allocate_unique_user_id_oauth(provider, provider_user_id, email)
    eff_email = email if email else f"{uid}@oauth.internal"
    user = User(
        user_id=uid,
        username=username,
        email=eff_email,
        is_active=True,
    )
    # OAuth 사용자를 위한 임시 비밀번호 설정 (실제로는 사용되지 않음)
    user.set_password('oauth_temp_password_' + str(datetime.now().timestamp()))
    db.session.add(user)
    db.session.flush()  # ID 생성
    
    # 사용자 프로필 생성
    profile = UserProfile(user_id=user.user_id)
    db.session.add(profile)
    db.session.flush()
    
    # OAuth 계정 생성
    oauth_account = OAuthAccount(
        user_profile_id=profile.id,
        provider=provider_enum,
        provider_user_id=provider_user_id,
        access_token=token_data['access_token'],
        refresh_token=token_data.get('refresh_token')
    )
    if 'expires_in' in token_data:
        # oauth_account.expires_at = datetime.now() + timedelta(seconds=token_data['expires_in'])
        expires_in = token_data.get('expires_in', 0)
        oauth_account.expires_at = datetime.now() + timedelta(seconds=int(token_data['expires_in']))
    
    db.session.add(oauth_account)
    
    try:
        db.session.commit()
        
        # 신규 OAuth 가입자에게 이벤트 크레딧 지급 (1000 크레딧, 30일 이내 사용)
        try:
            from src.utils.credit_manager import add_signup_bonus
            bonus_result = add_signup_bonus(user.user_id)
            if bonus_result.get('success'):
                print(f"OAuth 회원가입 보너스 크레딧 지급 완료: user_id={user.user_id}, amount=1000")
            else:
                print(f"OAuth 회원가입 보너스 크레딧 지급 실패: {bonus_result.get('error')}")
        except Exception as e:
            print(f"OAuth 회원가입 보너스 크레딧 지급 중 오류 (무시): {str(e)}")
            # 크레딧 지급 실패해도 회원가입은 성공한 것으로 처리
        
    except Exception as e:
        db.session.rollback()
        print(f"OAuth 사용자 생성 중 오류 발생: {str(e)}")
        # 중복 키 오류인지 확인
        if "Duplicate entry" in str(e) and "user.email" in str(e):
            # 이메일 중복 오류 - 기존 사용자 찾기
            existing_user = User.query.filter_by(email=email).first()
            if existing_user:
                print(f"중복 이메일로 인한 오류, 기존 사용자로 로그인: {email}")
                return existing_user
        raise e
    
    return user

def validate_email(email):
    # 더 유연한 이메일 검증 - 다양한 도메인 허용
    pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'
    return re.match(pattern, email) is not None

def validate_password(password):
    # 최소 8자, 영문자와 숫자 포함
    if len(password) < 8:
        return False
    if not re.search(r'[A-Za-z]', password):
        return False
    if not re.search(r'\d', password):
        return False
    return True

@auth_bp.route('/api/auth/register', methods=['POST'])
def register():
    try:
        data = request.get_json()
        
        if not data:
            return jsonify({'error': '데이터가 필요합니다.'}), 400
        
        username = data.get('username', '').strip()
        email = data.get('email', '').strip()
        password = (data.get('password') or '').strip()
        
        # 입력 검증
        if not username or not email or not password:
            return jsonify({'error': '모든 필드를 입력해주세요.'}), 400
        
        if len(username) < 3:
            return jsonify({'error': '사용자명은 3자 이상이어야 합니다.'}), 400
        
        if not validate_email(email):
            return jsonify({'error': '올바른 이메일 형식이 아닙니다.'}), 400
        
        if not validate_password(password):
            return jsonify({'error': '비밀번호는 8자 이상이며 영문자와 숫자를 포함해야 합니다.'}), 400
        
        # 중복 확인
        existing_user = User.query.filter_by(username=username).first()
        if existing_user:
            return jsonify({'error': '이미 사용 중인 사용자명입니다.'}), 400
        
        existing_email = User.query.filter_by(email=email).first()
        if existing_email:
            return jsonify({'error': '이미 사용 중인 이메일입니다.'}), 400
        
        # 새 사용자 생성 (업무 user_id = 이메일 로컬 파트 기준 유니크)
        uid = allocate_unique_user_id_from_email(email, username)
        user = User(user_id=uid, username=username, email=email)
        user.set_password(password)
        
        db.session.add(user)
        db.session.commit()
        
        # 신규 가입자에게 이벤트 크레딧 지급 (1000 크레딧, 30일 이내 사용)
        try:
            from src.utils.credit_manager import add_signup_bonus
            bonus_result = add_signup_bonus(user.user_id)
            if bonus_result.get('success'):
                print(f"회원가입 보너스 크레딧 지급 완료: user_id={user.user_id}, amount=1000")
            else:
                print(f"회원가입 보너스 크레딧 지급 실패: {bonus_result.get('error')}")
        except Exception as e:
            print(f"회원가입 보너스 크레딧 지급 중 오류 (무시): {str(e)}")
            # 크레딧 지급 실패해도 회원가입은 성공한 것으로 처리
        
        return jsonify({
            'message': '회원가입이 완료되었습니다.',
            'user': user.to_dict()
        }), 201
        
    except Exception as e:
        db.session.rollback()
        print(f"회원가입 오류: {str(e)}")  # 서버 로그에 오류 출력
        return jsonify({'error': f'서버 오류가 발생했습니다: {str(e)}'}), 500

@auth_bp.route('/api/auth/login', methods=['POST'])
def login():
    try:
        data = request.get_json()
        
        if not data:
            return jsonify({'error': '데이터가 필요합니다.'}), 400
        
        email = data.get('email', '').strip()
        password = (data.get('password') or '').strip()
        hcaptcha_token = data.get('hcaptcha_token', '')
        
        if not email or not password:
            return jsonify({'error': '이메일과 비밀번호를 입력해주세요.'}), 400
        
        # hCaptcha 검증
        if not hcaptcha_token:
            return jsonify({'error': 'hCaptcha 인증이 필요합니다.'}), 400
        
        if not verify_hcaptcha(hcaptcha_token):
            return jsonify({'error': 'hCaptcha 인증에 실패했습니다.'}), 400
        
        # 사용자 찾기 (이메일로 로그인)
        user = User.query.filter_by(email=email).first()
        
        if not user:
            return jsonify({'error': '이메일 또는 비밀번호가 올바르지 않습니다.'}), 401
        
        # 비밀번호 검증
        if not user.check_password(password):
            return jsonify({'error': '이메일 또는 비밀번호가 올바르지 않습니다.'}), 401
        
        # 기존 세션 정리 (다른 계정으로 로그인하기 위해)
        session.clear()
        
        # 세션에 사용자 정보 저장
        session['user_id'] = user.user_id
        session['username'] = user.username
        
        return jsonify({
            'message': '로그인 성공',
            'user': user.to_dict()
        }), 200
        
    except Exception as e:
        print(f"로그인 오류: {str(e)}")
        return jsonify({'error': '서버 오류가 발생했습니다.'}), 500

@auth_bp.route('/api/auth/logout', methods=['POST'])
def logout():
    try:
        # 세션 완전히 정리
        session.clear()
        # 세션 쿠키도 삭제하기 위해 세션을 무효화
        session.permanent = False
        
        # 응답 생성 및 세션 쿠키 삭제
        response = make_response(jsonify({'message': '로그아웃 되었습니다.'}), 200)
        
        # Flask 기본 세션 쿠키 이름 사용 (app.config.get('SESSION_COOKIE_NAME', 'session'))
        session_cookie_name = current_app.config.get('SESSION_COOKIE_NAME', 'session')
        
        # 세션 쿠키 삭제 (만료일을 과거로 설정)
        # 여러 경로와 도메인 조합으로 삭제 시도
        response.set_cookie(
            session_cookie_name, 
            '', 
            expires=0, 
            max_age=0, 
            path='/', 
            domain=None, 
            secure=False, 
            httponly=True, 
            samesite='Lax'
        )
        # 루트 경로와 현재 경로 모두에서 삭제 시도
        response.set_cookie(
            session_cookie_name, 
            '', 
            expires=0, 
            max_age=0, 
            path='/api', 
            domain=None, 
            secure=False, 
            httponly=True, 
            samesite='Lax'
        )
        
        return response
    except Exception as e:
        # 에러 발생 시에도 세션 정리 시도
        try:
            session.clear()
            response = make_response(jsonify({'error': '서버 오류가 발생했습니다.'}), 500)
            session_cookie_name = current_app.config.get('SESSION_COOKIE_NAME', 'session')
            response.set_cookie(session_cookie_name, '', expires=0, max_age=0, path='/', domain=None, secure=False, httponly=True, samesite='Lax')
            return response
        except:
            return jsonify({'error': '서버 오류가 발생했습니다.'}), 500

@auth_bp.route('/api/auth/me', methods=['GET'])
def get_current_user():
    try:
        user_id = session.get('user_id')
        if not user_id:
            return jsonify({'error': '로그인이 필요합니다.'}), 401
        
        user = get_user_by_session_value(user_id)
        if not user:
            session.clear()
            return jsonify({'error': '사용자를 찾을 수 없습니다.'}), 404
        
        return jsonify({'user': user.to_dict()}), 200
        
    except Exception as e:
        return jsonify({'error': '서버 오류가 발생했습니다.'}), 500

@auth_bp.route('/api/auth/check', methods=['GET'])
def check_auth():
    try:
        user_id = session.get('user_id')
        if user_id:
            user = get_user_by_session_value(user_id)
            if user:
                return jsonify({'authenticated': True, 'user': user.to_dict()}), 200
        
        return jsonify({'authenticated': False}), 200
        
    except Exception as e:
        return jsonify({'error': '서버 오류가 발생했습니다.'}), 500



@auth_bp.route('/api/auth/find-username', methods=['POST'])
def find_username():
    """이메일을 통한 사용자명 찾기"""
    try:
        data = request.get_json()
        
        if not data:
            return jsonify({'error': '데이터가 필요합니다.'}), 400
        
        email = data.get('email', '').strip()
        
        # 입력 검증
        if not email:
            return jsonify({'error': '이메일을 입력해주세요.'}), 400
        
        if not validate_email(email):
            return jsonify({'error': '올바른 이메일 형식이 아닙니다.'}), 400
        
        # 사용자 찾기
        user = User.query.filter_by(email=email).first()
        if not user:
            return jsonify({'error': '해당 이메일로 가입된 계정을 찾을 수 없습니다.'}), 404
        
        # 보안을 위해 사용자명의 일부만 표시
        masked_username = user.username[:2] + '*' * (len(user.username) - 2) if len(user.username) > 2 else user.username
        
        return jsonify({
            'message': '사용자명을 찾았습니다.',
            'username': user.username,  # 실제 환경에서는 masked_username 사용 권장
            'masked_username': masked_username
        }), 200
        
    except Exception as e:
        print(f"아이디 찾기 오류: {str(e)}")
        return jsonify({'error': '서버 오류가 발생했습니다.'}), 500

@auth_bp.route('/api/auth/reset-password', methods=['POST'])
def reset_password():
    """비밀번호 재설정 코드 전송"""
    try:
        data = request.get_json()
        email = data.get('email')
        hcaptcha_token = data.get('hcaptcha_token')
        
        if not email:
            return jsonify({'error': '이메일이 필요합니다.'}), 400
        
        # hCaptcha 검증 임시 비활성화
        # if not hcaptcha_token:
        #     return jsonify({'error': 'hCaptcha 토큰이 필요합니다.'}), 400
        # if not verify_hcaptcha(hcaptcha_token):
        #     return jsonify({'error': 'hCaptcha 인증에 실패했습니다.'}), 400
        
        # 사용자 존재 확인
        user = User.query.filter_by(email=email).first()
        if not user:
            return jsonify({'error': '해당 이메일로 등록된 계정을 찾을 수 없습니다.'}), 404
        
        # 인증 코드 생성 (6자리 숫자)
        verification_code = ''.join([str(secrets.randbelow(10)) for _ in range(6)])
        
        # 인증 코드 저장 (만료 시간: 10분)
        password_reset_codes[email] = {
            'code': verification_code,
            'expires_at': datetime.now() + timedelta(minutes=10),
            'attempts': 0
        }
        
        # 이메일 전송
        try:
            send_reset_email(email, verification_code)
            return jsonify({'message': '인증 코드가 이메일로 전송되었습니다.'}), 200
        except Exception as e:
            print(f"이메일 전송 실패: {e}")
            return jsonify({'error': '이메일 전송에 실패했습니다. 잠시 후 다시 시도해주세요.'}), 500
            
    except Exception as e:
        print(f"비밀번호 재설정 오류: {e}")
        return jsonify({'error': '비밀번호 재설정 처리 중 오류가 발생했습니다.'}), 500

@auth_bp.route('/api/auth/reset-password/confirm', methods=['POST'])
def confirm_reset_password():
    """비밀번호 재설정 확인 및 비밀번호 변경"""
    try:
        data = request.get_json()
        email = data.get('email')
        verification_code = data.get('verification_code')
        new_password = data.get('new_password')
        hcaptcha_token = data.get('hcaptcha_token')
        
        if not all([email, verification_code, new_password]):
            return jsonify({'error': '이메일, 인증 코드, 새 비밀번호가 필요합니다.'}), 400
        
        # 비밀번호 변경 시에는 hCaptcha 검증 생략
        # if not hcaptcha_token:
        #     return jsonify({'error': 'hCaptcha 토큰이 필요합니다.'}), 400
        # if not verify_hcaptcha(hcaptcha_token):
        #     return jsonify({'error': 'hCaptcha 인증에 실패했습니다.'}), 400
        
        # 사용자 존재 확인
        user = User.query.filter_by(email=email).first()
        if not user:
            return jsonify({'error': '해당 이메일로 등록된 계정을 찾을 수 없습니다.'}), 404
        
        # 인증 코드 확인
        reset_data = password_reset_codes.get(email)
        if not reset_data:
            return jsonify({'error': '인증 코드가 만료되었거나 존재하지 않습니다.'}), 400
        
        # 만료 시간 확인
        if datetime.now() > reset_data['expires_at']:
            del password_reset_codes[email]
            return jsonify({'error': '인증 코드가 만료되었습니다.'}), 400
        
        # 시도 횟수 확인 (최대 5회)
        if reset_data['attempts'] >= 5:
            del password_reset_codes[email]
            return jsonify({'error': '인증 코드 시도 횟수를 초과했습니다. 새로운 인증 코드를 요청해주세요.'}), 400
        
        # 인증 코드 검증
        if reset_data['code'] != verification_code:
            reset_data['attempts'] += 1
            return jsonify({'error': '인증 코드가 올바르지 않습니다.'}), 400
        
        # 비밀번호 변경
        user.password_hash = generate_password_hash(new_password)
        db.session.commit()
        
        # 인증 코드 삭제
        del password_reset_codes[email]
        
        return jsonify({'message': '비밀번호가 성공적으로 변경되었습니다.'}), 200
        
    except Exception as e:
        print(f"비밀번호 재설정 확인 오류: {e}")
        return jsonify({'error': '비밀번호 변경 처리 중 오류가 발생했습니다.'}), 500

def send_reset_email(email, verification_code):
    """비밀번호 재설정 이메일 전송"""
    # 이메일 설정 (실제 환경에서는 환경변수로 설정)
    smtp_server = os.getenv('SMTP_SERVER', 'smtp.gmail.com')
    smtp_port = int(os.getenv('SMTP_PORT', '587'))
    smtp_username = os.getenv('SMTP_USERNAME')
    smtp_password = os.getenv('SMTP_PASSWORD')
    
    if not all([smtp_username, smtp_password]):
        print("SMTP 설정이 완료되지 않았습니다. 환경변수를 확인해주세요.")
        return
    
    # 이메일 내용
    subject = "M-Link 비밀번호 재설정"
    body = f"""
    안녕하세요,
    
    M-Link 비밀번호 재설정을 요청하셨습니다.
    
    인증 코드: {verification_code}
    
    이 코드는 10분 후에 만료됩니다.
    본인이 요청하지 않았다면 이 이메일을 무시하세요.
    
    감사합니다.
    M-Link 팀
    """
    
    # 이메일 생성
    msg = MIMEMultipart()
    msg['From'] = smtp_username
    msg['To'] = email
    msg['Subject'] = subject
    
    msg.attach(MIMEText(body, 'plain', 'utf-8'))
    
    # 이메일 전송
    try:
        server = smtplib.SMTP(smtp_server, smtp_port)
        server.starttls()
        server.login(smtp_username, smtp_password)
        server.send_message(msg)
        server.quit()
        print(f"비밀번호 재설정 이메일 전송 완료: {email}")
    except Exception as e:
        print(f"이메일 전송 실패: {e}")
        raise

def send_verification_email(email, verification_code):
    """이메일 인증 코드 전송"""
    # 이메일 설정 (실제 환경에서는 환경변수로 설정)
    smtp_server = os.getenv('SMTP_SERVER', 'smtp.gmail.com')
    smtp_port = int(os.getenv('SMTP_PORT', '587'))
    smtp_username = os.getenv('SMTP_USERNAME')
    smtp_password = os.getenv('SMTP_PASSWORD')
    
    if not all([smtp_username, smtp_password]):
        print("SMTP 설정이 완료되지 않았습니다. 환경변수를 확인해주세요.")
        return False
    
    # 이메일 내용
    subject = "M-Link 이메일 인증"
    body = f"""
    안녕하세요,
    
    M-Link 회원가입을 위한 이메일 인증 코드입니다.
    
    인증 코드: {verification_code}
    
    이 코드는 5분 후에 만료됩니다.
    
    감사합니다.
    M-Link 팀
    """
    
    # 이메일 생성
    msg = MIMEMultipart()
    msg['From'] = smtp_username
    msg['To'] = email
    msg['Subject'] = subject
    
    msg.attach(MIMEText(body, 'plain', 'utf-8'))
    
    # 이메일 전송
    try:
        server = smtplib.SMTP(smtp_server, smtp_port)
        server.starttls()
        server.login(smtp_username, smtp_password)
        server.send_message(msg)
        server.quit()
        print(f"이메일 인증 코드 전송 완료: {email}")
        return True
    except Exception as e:
        print(f"이메일 전송 실패: {e}")
        return False

@auth_bp.route('/api/auth/send-verification', methods=['POST'])
def send_verification():
    """이메일 인증 코드 전송"""
    try:
        data = request.get_json()
        
        if not data:
            return jsonify({'error': '데이터가 필요합니다.'}), 400
        
        email = data.get('email', '').strip()
        username = data.get('username', '').strip()
        password = data.get('password', '').strip()
        hcaptcha_token = data.get('hcaptcha_token', '').strip()
        
        # 입력 검증
        if not email:
            return jsonify({'error': '이메일을 입력해주세요.'}), 400
        
        if not validate_email(email):
            return jsonify({'error': '올바른 이메일 형식이 아닙니다.'}), 400
        
        if not username:
            return jsonify({'error': '사용자명을 입력해주세요.'}), 400
        
        if not password:
            return jsonify({'error': '비밀번호를 입력해주세요.'}), 400
        
        if not validate_password(password):
            return jsonify({'error': '비밀번호는 최소 8자 이상이어야 하며, 영문자와 숫자를 포함해야 합니다.'}), 400
        
        if not hcaptcha_token:
            return jsonify({'error': 'hCaptcha 인증을 완료해주세요.'}), 400
        
        if not verify_hcaptcha(hcaptcha_token):
            return jsonify({'error': 'hCaptcha 인증에 실패했습니다.'}), 400
        
        # 기존 사용자 확인
        existing_user = User.query.filter_by(email=email).first()
        if existing_user:
            return jsonify({'error': '이미 가입된 이메일 주소입니다.'}), 400
        
        existing_username = User.query.filter_by(username=username).first()
        if existing_username:
            return jsonify({'error': '이미 사용 중인 사용자명입니다.'}), 400
        
        # 6자리 인증 코드 생성
        verification_code = ''.join([str(secrets.randbelow(10)) for _ in range(6)])
        
        # 인증 코드 저장 (5분 유효)
        email_verification_codes[email] = {
            'code': verification_code,
            'username': username,
            'password': password,
            'expires_at': datetime.now() + timedelta(minutes=5)
        }
        
        # 이메일 전송
        if send_verification_email(email, verification_code):
            return jsonify({'message': '인증 코드가 이메일로 전송되었습니다.'}), 200
        else:
            return jsonify({'error': '인증 코드 전송에 실패했습니다.'}), 500
        
    except Exception as e:
        print(f"인증 코드 전송 오류: {str(e)}")
        return jsonify({'error': '서버 오류가 발생했습니다.'}), 500

@auth_bp.route('/api/auth/verify-email', methods=['POST'])
def verify_email():
    """이메일 인증 코드 확인 및 회원가입 완료"""
    try:
        data = request.get_json()
        
        if not data:
            return jsonify({'error': '데이터가 필요합니다.'}), 400
        
        email = data.get('email', '').strip()
        verification_code = data.get('verification_code', '').strip()
        
        # 입력 검증
        if not email:
            return jsonify({'error': '이메일을 입력해주세요.'}), 400
        
        if not verification_code:
            return jsonify({'error': '인증 코드를 입력해주세요.'}), 400
        
        # 인증 코드 확인
        if email not in email_verification_codes:
            return jsonify({'error': '인증 코드가 만료되었거나 존재하지 않습니다.'}), 400
        
        stored_data = email_verification_codes[email]
        
        # 만료 시간 확인
        if datetime.now() > stored_data['expires_at']:
            del email_verification_codes[email]
            return jsonify({'error': '인증 코드가 만료되었습니다.'}), 400
        
        # 인증 코드 비교
        if stored_data['code'] != verification_code:
            return jsonify({'error': '인증 코드가 올바르지 않습니다.'}), 400
        
        # 사용자 생성
        uid = allocate_unique_user_id_from_email(email, stored_data['username'])
        user = User(
            user_id=uid,
            username=stored_data['username'],
            email=email,
            password_hash=generate_password_hash(stored_data['password'])
        )
        
        db.session.add(user)
        db.session.commit()
        
        # 신규 가입자에게 이벤트 크레딧 지급 (1000 크레딧, 30일 이내 사용)
        try:
            from src.utils.credit_manager import add_signup_bonus
            bonus_result = add_signup_bonus(user.user_id)
            if bonus_result.get('success'):
                print(f"회원가입 보너스 크레딧 지급 완료: user_id={user.user_id}, amount=1000")
            else:
                print(f"회원가입 보너스 크레딧 지급 실패: {bonus_result.get('error')}")
        except Exception as e:
            print(f"회원가입 보너스 크레딧 지급 중 오류 (무시): {str(e)}")
            # 크레딧 지급 실패해도 회원가입은 성공한 것으로 처리
        
        # 인증 코드 삭제
        del email_verification_codes[email]
        
        # 세션에 사용자 정보 저장
        session['user_id'] = user.user_id
        session['username'] = user.username
        
        return jsonify({
            'message': '회원가입이 완료되었습니다.',
            'user': user.to_dict()
        }), 200
        
    except Exception as e:
        print(f"이메일 인증 오류: {str(e)}")
        return jsonify({'error': '서버 오류가 발생했습니다.'}), 500

@auth_bp.route('/api/auth/verify-user', methods=['POST'])
def verify_user():
    """사용자 존재 여부 확인"""
    try:
        data = request.get_json()
        
        if not data:
            return jsonify({'error': '데이터가 필요합니다.'}), 400
        
        identifier = data.get('identifier', '').strip()  # 사용자명 또는 이메일
        
        # 입력 검증
        if not identifier:
            return jsonify({'error': '사용자명 또는 이메일을 입력해주세요.'}), 400
        
        # 사용자 찾기 (사용자명 또는 이메일로)
        user = None
        if validate_email(identifier):
            user = User.query.filter_by(email=identifier).first()
        else:
            user = User.query.filter_by(username=identifier).first()
        
        if not user:
            return jsonify({'error': '해당 정보로 가입된 계정을 찾을 수 없습니다.'}), 404
        
        return jsonify({
            'message': '사용자를 찾았습니다.',
            'username': user.username,
            'email': user.email[:3] + '*' * (len(user.email.split('@')[0]) - 3) + '@' + user.email.split('@')[1]  # 이메일 마스킹
        }), 200
        
    except Exception as e:
        print(f"사용자 확인 오류: {str(e)}")
        return jsonify({'error': '서버 오류가 발생했습니다.'}), 500


