# app/services/message_service.py
from typing import List
from sqlalchemy.orm import Session
from sqlalchemy import func, case
from app.models.message import Message
from app.services.push_notification_service import PushNotificationService
from app.models.user import User
import logging
import asyncio

logger = logging.getLogger('adimsayar')

async def create_message(db: Session, sender_id: int, receiver_id: int, content: str) -> Message:
    """
    Creates a new message record in the database and sends a push notification.
    """
    message = Message(sender_id=sender_id, receiver_id=receiver_id, content=content)
    db.add(message)
    db.commit()
    db.refresh(message)
    
    # 메시지를 DB에 저장한 후, 수신자에게 푸시 알림 전송
    try:
        # 발신자 정보 조회
        sender = db.query(User).filter(User.id == sender_id).first()
        logger.info(f"Sender: {sender}")
        if sender:
            sender_name = f"{sender.first_name or ''} {sender.last_name or ''}".strip()
            if not sender_name:
                sender_name = "Someone"
        else:
            logger.error(f"Sender with id {sender_id} not found")
            sender_name = "Someone"
        
        # Check if this is an image message
        is_image = content.startswith("[IMAGE]:")
        
        # 메시지 내용 미리보기 생성 (최대 50자)
        if is_image:
            preview = "Sent an image"
        else:
            preview = content[:50] + ("..." if len(content) > 50 else "")
        
        # 추가 데이터 준비
        notification_data = {
            "type": "message",
            "sender_id": sender_id,
            "message_id": message.id,
            "conversation_id": sender_id,
            "is_chat": True,
            "has_image": is_image,
            "badge": 1,  # 앱 배지 카운트를 위한 값
            "sound": "default"  # iOS, Android에서 사운드 재생을 위한 값
        }
        
        # 통합 푸시 알림 서비스를 통해 알림 전송 (Firebase + Expo)
        success = await PushNotificationService.send_push_to_user(
            db=db,
            user_id=receiver_id,
            title=f"New message from {sender_name}",
            message=preview,
            data=notification_data,
            notification_type="new_message",
            save_to_db=True
        )
        
        if success:
            logger.info(f"Message notification sent successfully: user {sender_id} to {receiver_id}")
        else:
            logger.warning(f"Message notification delivery failed: user {sender_id} to {receiver_id}")
            
    except Exception as e:
        # 푸시 알림 전송 실패시에도 메시지 자체는 이미 저장됨
        logger.error(f"Message push notification failed: {str(e)}", exc_info=True)
    
    return message

def get_messages_between_users(db: Session, user1_id: int, user2_id: int) -> List[Message]:
    """
    Retrieves all messages exchanged between two users, ordered by sent time.
    """
    return db.query(Message).filter(
        ((Message.sender_id == user1_id) & (Message.receiver_id == user2_id)) |
        ((Message.sender_id == user2_id) & (Message.receiver_id == user1_id))
    ).order_by(Message.sent_at).all()

def get_unread_messages(db: Session, receiver_id: int) -> List[Message]:
    """
    Retrieves all unread messages for the receiver.
    """
    return db.query(Message).filter(
        Message.receiver_id == receiver_id,
        Message.is_read == False
    ).order_by(Message.sent_at).all()

def mark_messages_as_read(db: Session, receiver_id: int, sender_id: int):
    """
    Marks all messages from a specific sender as read for the given receiver.
    """
    messages = db.query(Message).filter(
        Message.receiver_id == receiver_id,
        Message.sender_id == sender_id,
        Message.is_read == False
    ).all()
    for msg in messages:
        msg.is_read = True
    db.commit()
    return messages

def get_conversation_threads(db: Session, user_id: int) -> List[Message]:
    """
    Retrieves conversation threads for the given user.
    각 스레드는 대화 상대(친구)와의 최신 메시지를 포함합니다.
    """
    subquery = (
        db.query(
            func.max(Message.sent_at).label("latest_sent_at"),
            # SQLAlchemy의 case() 함수에서는 조건과 값을 positional 인자로 전달합니다.
            case(
                (Message.sender_id == user_id, Message.receiver_id),
                else_=Message.sender_id
            ).label("friend_id")
        )
        .filter(
            (Message.sender_id == user_id) | (Message.receiver_id == user_id)
        )
        .group_by("friend_id")
        .subquery()
    )

    threads = (
        db.query(Message)
        .join(
            subquery,
            (Message.sent_at == subquery.c.latest_sent_at) &
            (
                ((Message.sender_id == user_id) & (Message.receiver_id == subquery.c.friend_id)) |
                ((Message.receiver_id == user_id) & (Message.sender_id == subquery.c.friend_id))
            )
        )
        .order_by(Message.sent_at.desc())
        .all()
    )
    return threads