# src/routes/portone_webhook.py
from flask import Blueprint, request, jsonify, current_app
import os
import hmac
import hashlib
import json
from datetime import datetime
from src.models.subscription import db, Subscription, PaymentMethod
from src.models.user import User

portone_webhook_bp = Blueprint('portone_webhook', __name__)

# 포트원 웹훅 설정
PORTONE_WEBHOOK_CONFIG = {
    'secret_key': os.getenv('PORTONE_WEBHOOK_SECRET_KEY'),
    'base_url': os.getenv('PORTONE_BASE_URL', 'https://api.portone.io')
}

# @portone_webhook_bp.route('/api/v2/payments/webhook', methods=['POST'])
# def portone_webhook():
#     """포트원 웹훅 수신 및 처리"""
#     try:
#         # 웹훅 데이터 파싱
#         webhook_data = request.get_json()
        
#         if not webhook_data:
#             current_app.logger.error('웹훅 데이터가 비어있습니다.')
#             return jsonify({'error': 'Invalid webhook data'}), 400

#         # 웹훅 서명 검증
#         if not verify_webhook_signature(request):
#             current_app.logger.error('웹훅 서명 검증 실패')
#             return jsonify({'error': 'Invalid signature'}), 401

#         # 웹훅 이벤트 타입 확인
#         event_type = webhook_data.get('eventType')
#         payment_id = webhook_data.get('paymentId')
        
#         if not event_type or not payment_id:
#             current_app.logger.error('웹훅 데이터 형식 오류')
#             return jsonify({'error': 'Invalid webhook format'}), 400

#         current_app.logger.info(f'포트원 웹훅 수신: {event_type} - {payment_id}')

#         # 이벤트 타입별 처리
#         if event_type == 'PAYMENT_STATUS_CHANGED':
#             handle_payment_status_changed(webhook_data)
#         elif event_type == 'PAYMENT_COMPLETED':
#             handle_payment_completed(webhook_data)
#         elif event_type == 'PAYMENT_FAILED':
#             handle_payment_failed(webhook_data)
#         elif event_type == 'PAYMENT_CANCELLED':
#             handle_payment_cancelled(webhook_data)
#         else:
#             current_app.logger.info(f'처리하지 않는 이벤트 타입: {event_type}')

#         return jsonify({'success': True, 'message': 'Webhook processed successfully'})

#     except Exception as e:
#         current_app.logger.error(f'웹훅 처리 실패: {str(e)}')
#         return jsonify({'error': 'Webhook processing failed'}), 500

# def verify_webhook_signature(request):
#     """포트원 웹훅 서명 검증"""
#     try:
#         # 포트원 웹훅 시크릿 키 확인
#         secret_key = PORTONE_WEBHOOK_CONFIG['secret_key']
#         if not secret_key:
#             current_app.logger.warning('포트원 웹훅 시크릿 키가 설정되지 않았습니다.')
#             return True  # 개발 환경에서는 검증 건너뛰기

#         # 웹훅 서명 헤더 확인
#         signature = request.headers.get('PortOne-Signature')
#         if not signature:
#             current_app.logger.error('포트원 웹훅 서명이 없습니다.')
#             return False

#         # 요청 본문
#         body = request.get_data()
        
#         # HMAC-SHA256으로 서명 생성
#         expected_signature = hmac.new(
#             secret_key.encode('utf-8'),
#             body,
#             hashlib.sha256
#         ).hexdigest()

#         # 서명 비교
#         if hmac.compare_digest(signature, expected_signature):
#             return True
#         else:
#             current_app.logger.error('웹훅 서명이 일치하지 않습니다.')
#             return False

#     except Exception as e:
#         current_app.logger.error(f'웹훅 서명 검증 중 오류: {str(e)}')
#         return False

# def handle_payment_status_changed(webhook_data):
#     """결제 상태 변경 처리"""
#     try:
#         payment_id = webhook_data.get('paymentId')
#         status = webhook_data.get('data', {}).get('status')
        
#         if not payment_id or not status:
#             current_app.logger.error('결제 상태 변경 데이터 누락')
#             return

#         current_app.logger.info(f'결제 상태 변경: {payment_id} -> {status}')
        
#         # 구독 상태 업데이트
#         subscription = Subscription.query.filter_by(payment_id=payment_id).first()
#         if subscription:
#             if status == 'PAID':
#                 subscription.status = 'active'
#             elif status == 'FAILED':
#                 subscription.status = 'failed'
#             elif status == 'CANCELLED':
#                 # 크레딧 기준 구독자인 경우 남은 크레딧 사용 완료 처리
#                 try:
#                     from src.models.user import SubscriptionType
#                     from src.utils.credit_manager import consume_all_remaining_credits
                    
#                     user = User.query.get(subscription.user_id)
#                     if user and user.subscription_type == SubscriptionType.CREDIT:
#                         credit_result = consume_all_remaining_credits(
#                             user_id=subscription.user_id,
#                             description='구독 취소로 인한 남은 크레딧 사용 완료',
#                             reference_id=str(subscription.id),
#                             reference_type='subscription_cancellation'
#                         )
#                         if credit_result.get('success'):
#                             current_app.logger.info(f'[handle_payment_status_changed] 남은 크레딧 사용 완료: {credit_result.get("consumed", 0)} 크레딧')
#                         else:
#                             current_app.logger.warning(f'[handle_payment_status_changed] 남은 크레딧 사용 실패: {credit_result.get("error")}')
#                 except Exception as e:
#                     current_app.logger.warning(f'[handle_payment_status_changed] 크레딧 사용 처리 실패(무시): {str(e)}')
                
#                 subscription.status = 'cancelled'
            
#             subscription.updated_at = datetime.now()
#             db.session.commit()
            
#             current_app.logger.info(f'구독 상태 업데이트 완료: {subscription.id} -> {subscription.status}')

#     except Exception as e:
#         current_app.logger.error(f'결제 상태 변경 처리 실패: {str(e)}')
#         db.session.rollback()

# def handle_payment_completed(webhook_data):
#     """결제 완료 처리"""
#     try:
#         payment_id = webhook_data.get('paymentId')
#         payment_data = webhook_data.get('data', {})
        
#         current_app.logger.info(f'결제 완료: {payment_id}')
        
#         # 결제 정보 로깅
#         amount = payment_data.get('amount', {})
#         current_app.logger.info(f'결제 금액: {amount.get("total")} {amount.get("currency")}')
        
#         # 구독 활성화
#         subscription = Subscription.query.filter_by(payment_id=payment_id).first()
#         if subscription:
#             subscription.status = 'active'
#             subscription.updated_at = datetime.now()
#             db.session.commit()
            
#             # 구독 활성화 시 크레딧 추가
#             try:
#                 from src.utils.credit_manager import renew_subscription_credits
#                 credit_result = renew_subscription_credits(subscription.user_id, subscription.id)
#                 if credit_result.get('success'):
#                     current_app.logger.info(f'[handle_payment_completed] 구독 크레딧 추가 완료: user_id={subscription.user_id}, added={credit_result.get("added", 0)}')
#                 else:
#                     current_app.logger.warning(f'[handle_payment_completed] 구독 크레딧 추가 실패: {credit_result.get("error")}')
#             except Exception as e:
#                 current_app.logger.error(f'[handle_payment_completed] 구독 크레딧 추가 중 오류 (무시): {str(e)}')
#                 # 크레딧 추가 실패해도 구독은 성공한 것으로 처리
            
#             current_app.logger.info(f'구독 활성화 완료: {subscription.id}')

#     except Exception as e:
#         current_app.logger.error(f'결제 완료 처리 실패: {str(e)}')
#         db.session.rollback()

# def handle_payment_failed(webhook_data):
#     """결제 실패 처리"""
#     try:
#         payment_id = webhook_data.get('paymentId')
#         failure_reason = webhook_data.get('data', {}).get('failureReason', 'Unknown')
        
#         current_app.logger.warning(f'결제 실패: {payment_id} - {failure_reason}')
        
#         # 구독 상태 업데이트
#         subscription = Subscription.query.filter_by(payment_id=payment_id).first()
#         if subscription:
#             subscription.status = 'failed'
#             subscription.updated_at = datetime.now()
#             db.session.commit()
            
#             current_app.logger.info(f'구독 실패 상태 업데이트: {subscription.id}')

#     except Exception as e:
#         current_app.logger.error(f'결제 실패 처리 실패: {str(e)}')
#         db.session.rollback()

# def handle_payment_cancelled(webhook_data):
#     """결제 취소 처리"""
#     try:
#         payment_id = webhook_data.get('paymentId')
#         cancel_reason = webhook_data.get('data', {}).get('cancelReason', 'User cancelled')
        
#         current_app.logger.info(f'결제 취소: {payment_id} - {cancel_reason}')
        
#         # 구독 상태 업데이트
#         subscription = Subscription.query.filter_by(payment_id=payment_id).first()
#         if subscription:
#             # 크레딧 기준 구독자인 경우 남은 크레딧 사용 완료 처리
#             try:
#                 from src.models.user import SubscriptionType
#                 from src.utils.credit_manager import consume_all_remaining_credits
                
#                 user = User.query.get(subscription.user_id)
#                 if user and user.subscription_type == SubscriptionType.CREDIT:
#                     credit_result = consume_all_remaining_credits(
#                         user_id=subscription.user_id,
#                         description='구독 취소로 인한 남은 크레딧 사용 완료',
#                         reference_id=str(subscription.id),
#                         reference_type='subscription_cancellation'
#                     )
#                     if credit_result.get('success'):
#                         current_app.logger.info(f'[handle_payment_cancelled] 남은 크레딧 사용 완료: {credit_result.get("consumed", 0)} 크레딧')
#                     else:
#                         current_app.logger.warning(f'[handle_payment_cancelled] 남은 크레딧 사용 실패: {credit_result.get("error")}')
#             except Exception as e:
#                 current_app.logger.warning(f'[handle_payment_cancelled] 크레딧 사용 처리 실패(무시): {str(e)}')
            
#             subscription.status = 'cancelled'
#             subscription.updated_at = datetime.now()
#             db.session.commit()
            
#             current_app.logger.info(f'구독 취소 상태 업데이트: {subscription.id}')

#     except Exception as e:
#         current_app.logger.error(f'결제 취소 처리 실패: {str(e)}')
#         db.session.rollback()

# @portone_webhook_bp.route('/api/v2/payments/webhook/test', methods=['POST'])
# def test_webhook():
#     """웹훅 테스트용 엔드포인트 (개발 환경에서만 사용)"""
#     try:
#         webhook_data = request.get_json()
#         current_app.logger.info(f'웹훅 테스트 데이터: {json.dumps(webhook_data, indent=2)}')
        
#         return jsonify({
#             'success': True,
#             'message': 'Webhook test received',
#             'data': webhook_data
#         })
        
#     except Exception as e:
#         current_app.logger.error(f'웹훅 테스트 실패: {str(e)}')
#         return jsonify({'error': 'Webhook test failed'}), 500
