from sqlalchemy.orm import Session, joinedload
from sqlalchemy import and_, or_, desc
from typing import List, Optional, Dict, Any
from datetime import datetime

from ..models.notification import Notification
from ..models.user import User

def notification_to_dict(n: Notification) -> Dict[str, Any]:
    """Convert Notification ORM object to dictionary for template compatibility"""
    if not n:
        return None
    
    sender_name = n.sender.name if n.sender else "Sistema"
    recipient_name = n.recipient.name if n.recipient else "Usuario"
    
    return {
        "id": n.id,
        "created_at": n.created_at,
        "title": n.title,
        "body": n.body,
        "sender_id": n.sender_id,
        "recipient_id": n.recipient_id,
        "reservation_id": n.reservation_id,
        "is_read": n.is_read,
        "sender_name": sender_name,
        "recipient_name": recipient_name,
        "deleted_by_sender": n.deleted_by_sender,
        "deleted_by_recipient": n.deleted_by_recipient
    }

def get_notifications_for_user(db: Session, user_id: int) -> List[Dict[str, Any]]:
    """Get received notifications for a user"""
    notifications = db.query(Notification).options(
        joinedload(Notification.sender)
    ).filter(
        Notification.recipient_id == user_id,
        or_(Notification.deleted_by_recipient == 0, Notification.deleted_by_recipient.is_(None))
    ).order_by(desc(Notification.created_at)).all()
    
    return [notification_to_dict(n) for n in notifications]

def get_notifications_sent_by_user(db: Session, sender_id: int) -> List[Dict[str, Any]]:
    """Get notifications sent by a user"""
    notifications = db.query(Notification).options(
        joinedload(Notification.recipient)
    ).filter(
        Notification.sender_id == sender_id,
        or_(Notification.deleted_by_sender == 0, Notification.deleted_by_sender.is_(None))
    ).order_by(desc(Notification.created_at)).all()
    
    return [notification_to_dict(n) for n in notifications]

def get_notifications_sent_by_user_to_user(db: Session, sender_id: int, recipient_id: int) -> List[Dict[str, Any]]:
    """Get notifications sent by a user to a specific recipient"""
    notifications = db.query(Notification).options(
        joinedload(Notification.recipient)
    ).filter(
        Notification.sender_id == sender_id,
        Notification.recipient_id == recipient_id,
        or_(Notification.deleted_by_sender == 0, Notification.deleted_by_sender.is_(None)),
        or_(Notification.deleted_by_recipient == 0, Notification.deleted_by_recipient.is_(None))
    ).order_by(desc(Notification.created_at)).all()
    
    return [notification_to_dict(n) for n in notifications]

def get_unread_notifications_count(db: Session, user_id: int) -> int:
    """Count unread notifications for a user"""
    return db.query(Notification).filter(
        Notification.recipient_id == user_id,
        Notification.is_read == 0,
        or_(Notification.deleted_by_recipient == 0, Notification.deleted_by_recipient.is_(None))
    ).count()

def get_unread_notifications_for_user(db: Session, user_id: int) -> List[Dict[str, Any]]:
    """Get unread notifications for a user"""
    notifications = db.query(Notification).options(
        joinedload(Notification.sender)
    ).filter(
        Notification.recipient_id == user_id,
        Notification.is_read == 0,
        or_(Notification.deleted_by_recipient == 0, Notification.deleted_by_recipient.is_(None))
    ).order_by(desc(Notification.created_at)).all()
    
    return [notification_to_dict(n) for n in notifications]

def create_notification(
    db: Session, 
    recipient_id: int, 
    title: str, 
    body: str, 
    sender_id: Optional[int] = None, 
    reservation_id: Optional[int] = None
) -> Notification:
    """Create a new notification"""
    notification = Notification(
        recipient_id=recipient_id,
        title=title,
        body=body,
        sender_id=sender_id,
        reservation_id=reservation_id,
        is_read=0,
        created_at=datetime.now().strftime('%Y-%m-%dT%H:%M:%S')
    )
    db.add(notification)
    db.commit()
    db.refresh(notification)
    return notification

def mark_notification_as_read(db: Session, notification_id: int, user_id: int) -> bool:
    """Mark a notification as read for a recipient"""
    notification = db.query(Notification).filter(
        Notification.id == notification_id, 
        Notification.recipient_id == user_id
    ).first()
    
    if notification:
        notification.is_read = 1
        db.commit()
        return True
    return False

def delete_notification(
    db: Session, 
    notification_id: int, 
    user_id: int, 
    user_role: str,
    target_recipient_id: Optional[int] = None
) -> bool:
    """
    Delete notification logic based on user role and ownership.
    Returns True if deleted/updated, False otherwise.
    """
    notification = db.query(Notification).filter(Notification.id == notification_id).first()
    if not notification:
        return False
        
    sender_id = notification.sender_id
    recipient_id = notification.recipient_id
    
    # Logic from main.py
    if user_id == recipient_id:
        notification.deleted_by_recipient = 1
    elif sender_id is not None and user_id == sender_id:
        if target_recipient_id is not None and int(target_recipient_id) == recipient_id:
            notification.deleted_by_sender = 1
            notification.deleted_by_recipient = 1
        else:
            notification.deleted_by_sender = 1
    elif user_role in ("docente", "admin") and target_recipient_id is not None and int(target_recipient_id) == recipient_id:
         notification.deleted_by_recipient = 1
    else:
        return False
        
    db.commit()
    return True

def delete_notifications_by_user(db: Session, user_id: int):
    """Delete all notifications sent or received by user"""

    db.query(Notification).filter(
        or_(Notification.sender_id == user_id, Notification.recipient_id == user_id)
    ).delete(synchronize_session=False)
    db.commit()
