# 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.expo_push_notification_service import ExpoPushNotificationService
from app.models.user import User
import logging

logger = logging.getLogger('adimsayar')

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"
        
        # 메시지 내용 미리보기 생성 (최대 50자)
        preview = content[:50] + ("..." if len(content) > 50 else "")
        
        # Expo 푸시 알림 전송
        ExpoPushNotificationService.send_push_to_user(
            db=db,
            user_id=receiver_id,
            title=f"New message from {sender_name}",
            message=preview,
            data={
                "type": "message",
                "sender_id": sender_id,
                "message_id": message.id,
                "conversation_id": sender_id,
                "is_chat": True
            },
            notification_type="new_message"
        )
        logger.info(f"Message notification sent: user {sender_id} to {receiver_id}")
    except Exception as e:
        # 푸시 알림 전송 실패시에도 메시지 자체는 이미 저장됨
        logger.error(f"Message push notification failed: {str(e)}")
    
    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