import json
import logging
import requests
from typing import List, Dict, Optional, Any, Union
from sqlalchemy.orm import Session
from app.models.notification import Notification
from app.services.device_token_service import DeviceTokenService
from app.core.config import settings
from google.oauth2 import service_account
from google.auth.transport.requests import AuthorizedSession

logger = logging.getLogger('adimsayar')

class PushNotificationService:
    @staticmethod
    def _get_access_token():
        """Firebase 서비스 계정으로 액세스 토큰을 생성합니다."""
        credentials = service_account.Credentials.from_service_account_info(
            {
                "type": "service_account",
                "project_id": settings.FIREBASE_PROJECT_ID,
                "private_key": settings.FIREBASE_PRIVATE_KEY,
                "client_email": settings.FIREBASE_CLIENT_EMAIL,
                "token_uri": "https://oauth2.googleapis.com/token",
            },
            scopes=['https://www.googleapis.com/auth/firebase.messaging']
        )
        return credentials.token

    @staticmethod
    def send_push_to_user(
        db: Session, 
        user_id: int, 
        title: str, 
        message: str, 
        data: Dict[str, Any] = None,
        notification_type: str = "general"
    ) -> bool:
        """
        Firebase를 통해 사용자에게 푸시 알림을 보내고, 동시에 DB에 알림을 저장합니다.
        """
        try:
            # 사용자의 디바이스 토큰 조회
            device_tokens = DeviceTokenService.get_user_device_tokens(db, user_id)
            
            if not device_tokens:
                logger.info(f"사용자 ID {user_id}에 대한 활성화된 디바이스 토큰이 없습니다.")
                # 디바이스 토큰이 없어도 DB에는 알림 저장
                PushNotificationService._save_notification_to_db(
                    db, user_id, title, message, data, notification_type
                )
                return True
            
            # 푸시 알림 전송
            token_values = [token.device_token for token in device_tokens]
            success = PushNotificationService._send_firebase_push(token_values, title, message, data)
            
            # DB에 알림 저장
            PushNotificationService._save_notification_to_db(
                db, user_id, title, message, data, notification_type
            )
            
            return success
        
        except Exception as e:
            logger.error(f"푸시 알림 전송 오류: {str(e)}")
            return False
    
    @staticmethod
    def _send_firebase_push(
        tokens: List[str], 
        title: str, 
        message: str, 
        data: Dict[str, Any] = None
    ) -> bool:
        """FCM HTTP v1 API를 사용하여 푸시 알림을 전송합니다."""
        try:
            if not tokens:
                logger.warning("푸시 알림을 보낼 토큰이 없습니다.")
                return False

            # 액세스 토큰 획득
            access_token = PushNotificationService._get_access_token()
            
            # API 엔드포인트
            project_id = settings.FIREBASE_PROJECT_ID
            url = f"https://fcm.googleapis.com/v1/projects/{project_id}/messages:send"
            
            # 헤더 설정
            headers = {
                'Authorization': f'Bearer {access_token}',
                'Content-Type': 'application/json',
            }

            # 성공한 전송 수를 추적
            success_count = 0

            # 각 토큰에 대해 개별적으로 메시지 전송
            for token in tokens:
                payload = {
                    "message": {
                        "token": token,
                        "notification": {
                            "title": title,
                            "message": message
                        },
                        "data": data or {},
                        "android": {
                            "priority": "high",
                            "notification": {
                                "sound": "default"
                            }
                        },
                        "apns": {
                            "payload": {
                                "aps": {
                                    "sound": "default"
                                }
                            }
                        }
                    }
                }

                response = requests.post(url, headers=headers, json=payload)
                
                if response.status_code == 200:
                    success_count += 1
                    logger.info(f"푸시 알림 전송 성공: {token[:10]}...")
                else:
                    logger.warning(f"푸시 알림 전송 실패: {token[:10]}... - {response.text}")

            logger.info(f"푸시 알림 전송 결과: 성공 {success_count}/{len(tokens)}")
            return success_count > 0

        except Exception as e:
            logger.error(f"Firebase 푸시 알림 전송 중 오류 발생: {str(e)}")
            return False
    
    @staticmethod
    def _save_notification_to_db(
        db: Session, 
        user_id: int, 
        title: str, 
        message: str, 
        data: Dict[str, Any] = None,
        notification_type: str = "general"
    ) -> Notification:
        """
        알림을 데이터베이스에 저장합니다.
        """
        try:
            # 기존 NotificationService.create_notification 활용
            from app.services.notification_service import NotificationService
            
            notification = NotificationService.create_notification(
                db=db,
                user_id=user_id,
                notif_type=notification_type,
                title=title,
                message=message,
                data=data
            )
            
            # 커밋
            db.commit()
            db.refresh(notification)
            
            logger.info(f"사용자 ID {user_id}에 대한 알림이 DB에 저장되었습니다. (ID: {notification.id})")
            return notification
            
        except Exception as e:
            db.rollback()
            logger.error(f"알림 DB 저장 오류: {str(e)}")
            raise 