"""Simple messaging model for RateRight Australian Construction Marketplace"""
from datetime import datetime, timezone
from sqlalchemy import Enum as SQLEnum
from enum import Enum

from ..extensions import db
from .base import BaseModel


class MessageStatus(Enum):
    """Message status enumeration"""
    SENT = "sent"
    DELIVERED = "delivered" 
    READ = "read"


class Message(BaseModel):
    """Simple message model for async messaging between users"""
    
    __tablename__ = "messages"
    
    # Sender and receiver
    sender_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    receiver_id = db.Column(db.Integer, db.ForeignKey('users.id'), nullable=False)
    
    # Name snapshot (preserved even after user deletion for message history)
    sender_name = db.Column(db.String(200), nullable=True)  # "FirstName LastName" at time of sending
    
    # Message content
    text = db.Column(db.Text, nullable=False)
    
    @property
    def content(self):
        """Alias for text to match API expectations"""
        return self.text
    
    @content.setter
    def content(self, value):
        """Setter for content alias"""
        self.text = value
    
    @property
    def message_type(self):
        """Message type (always 'text' for now)"""
        return 'text'
    
    # Status tracking
    status = db.Column(SQLEnum(MessageStatus), default=MessageStatus.SENT, nullable=False)
    read_at = db.Column(db.DateTime)
    
    # Optional context linking
    contract_id = db.Column(db.Integer, db.ForeignKey('contracts.id'), nullable=True)
    job_id = db.Column(db.Integer, db.ForeignKey('jobs.id'), nullable=True)
    
    # Relationships
    sender = db.relationship('User', foreign_keys=[sender_id], backref=db.backref('sent_messages', lazy=True, order_by='Message.created_at.desc()'))
    receiver = db.relationship('User', foreign_keys=[receiver_id], backref=db.backref('received_messages', lazy=True, order_by='Message.created_at.desc()'))
    
    # Optional relationships for context
    contract = db.relationship('Contract', backref=db.backref('messages', lazy=True))
    job = db.relationship('Job', backref=db.backref('messages', lazy=True))
    
    # Indexes for performance
    __table_args__ = (
        db.Index('idx_message_receiver_status', 'receiver_id', 'status'),
        db.Index('idx_message_sender_receiver', 'sender_id', 'receiver_id'),
        db.Index('idx_message_created_at', 'created_at'),
    )
    
    def mark_as_read(self):
        """Mark message as read"""
        if self.status != MessageStatus.READ:
            self.status = MessageStatus.READ
            self.read_at = datetime.now(timezone.utc)
            db.session.commit()
    
    def mark_as_delivered(self):
        """Mark message as delivered"""
        if self.status == MessageStatus.SENT:
            self.status = MessageStatus.DELIVERED
            db.session.commit()
    
    def get_sender_name(self):
        """Get sender name - uses snapshot if available, falls back to user object"""
        if self.sender_name:
            return self.sender_name
        if self.sender:
            return f"{self.sender.first_name} {self.sender.last_name}"
        return "Unknown User"
    
    @property
    def is_read(self):
        """Check if message has been read"""
        return self.status == MessageStatus.READ
    
    @property
    def is_delivered(self):
        """Check if message has been delivered"""
        return self.status in [MessageStatus.DELIVERED, MessageStatus.READ]
    
    def to_dict(self, include_sender_info=True, include_receiver_info=False):
        """Convert message to dictionary for JSON serialization"""
        result = {
            'id': self.id,
            'text': self.text,
            'status': self.status.value,
            'is_read': self.is_read,
            'created_at': self.created_at.isoformat() if self.created_at else None,
            'read_at': self.read_at.isoformat() if self.read_at else None,
            'contract_id': self.contract_id,
            'job_id': self.job_id,
        }
        
        # Include sender information if requested
        if include_sender_info and self.sender:
            result['sender'] = {
                'id': self.sender.id,
                'name': self.get_sender_name(),  # Use snapshot if available
                'role': self.sender.role
            }
        else:
            result['sender_id'] = self.sender_id
        
        # Include receiver information if requested
        if include_receiver_info and self.receiver:
            result['receiver'] = {
                'id': self.receiver.id,
                'name': f"{self.receiver.first_name} {self.receiver.last_name}",
                'role': self.receiver.role
            }
        else:
            result['receiver_id'] = self.receiver_id
        
        # Include file attachments
        from .file_upload import FileUpload
        attachments = FileUpload.query.filter_by(message_id=self.id, is_deleted=False).all()
        if attachments:
            result['attachments'] = [{
                'id': f.id,
                'url': f.public_url,
                'original_filename': f.original_filename,
                'file_type': f.file_type,
                'file_size': f.file_size
            } for f in attachments]
        else:
            result['attachments'] = []
            
        return result
    
    def __repr__(self):
        return f"<Message {self.id}: {self.sender_id} -> {self.receiver_id}>"


class Conversation:
    """Helper class to get conversation between two users (not stored in DB)"""
    
    def __init__(self, user1_id, user2_id):
        self.user1_id = min(user1_id, user2_id)  # Normalize order
        self.user2_id = max(user1_id, user2_id)
    
    def can_send_messages(self):
        """Check if both users are active and not deleted"""
        from ..models.user import User
        user1 = User.query.get(self.user1_id)
        user2 = User.query.get(self.user2_id)
        
        if not user1 or not user2:
            return False
        
        # Check if either user is deleted or inactive
        if user1.is_deleted or user2.is_deleted:
            return False
        
        if not user1.is_active or not user2.is_active:
            return False
        
        return True
    
    def get_deleted_user_info(self):
        """Get information about which user(s) are deleted"""
        from ..models.user import User
        user1 = User.query.get(self.user1_id)
        user2 = User.query.get(self.user2_id)
        
        info = {
            'user1_deleted': user1.is_deleted if user1 else True,
            'user2_deleted': user2.is_deleted if user2 else True,
            'conversation_disabled': not self.can_send_messages()
        }
        
        return info
    
    @classmethod
    def get_conversation_id(cls, user1_id, user2_id):
        """Get conversation ID (helper method for API compatibility)"""
        return f"{min(user1_id, user2_id)}-{max(user1_id, user2_id)}"
    
    def get_messages(self, limit=50, offset=0):
        """Get messages in conversation with pagination"""
        return Message.query.filter(
            db.or_(
                db.and_(Message.sender_id == self.user1_id, Message.receiver_id == self.user2_id),
                db.and_(Message.sender_id == self.user2_id, Message.receiver_id == self.user1_id)
            )
        ).order_by(Message.created_at.desc()).offset(offset).limit(limit).all()
    
    def get_unread_count(self, for_user_id):
        """Get count of unread messages for specific user in this conversation"""
        return Message.query.filter(
            Message.receiver_id == for_user_id,
            Message.sender_id == (self.user2_id if for_user_id == self.user1_id else self.user1_id),
            Message.status != MessageStatus.READ
        ).count()
    
    def mark_all_as_read(self, for_user_id):
        """Mark all messages as read for specific user in this conversation"""
        messages = Message.query.filter(
            Message.receiver_id == for_user_id,
            Message.sender_id == (self.user2_id if for_user_id == self.user1_id else self.user1_id),
            Message.status != MessageStatus.READ
        ).all()
        
        for message in messages:
            message.mark_as_read()
        
        return len(messages)
