import uuid
from typing import Callable, List, Dict, Optional
from .message import Message
from .user import User
from .store.sqlitestore import SQLiteStorage


class ChatRoom:
    """聊天室核心类"""
    
    def __init__(self, name: str, storage: SQLiteStorage = None, room_id: str = None):
        """
        Args:
            name: 聊天室名称
            storage: 存储后端，默认使用SQLiteStorage
            room_id: 房间ID
        """
        self.name = name
        self.room_id = room_id or str(uuid.uuid4())
        self._storage = storage or SQLiteStorage()
        self._participants: Dict[str, User] = {}
        
        # 回调函数
        self._on_message_cb = None
        self._on_join_cb = None
        self._on_leave_cb = None
    
    # ===== 参与者操作 =====
    def add(self, user_id: str, name: str, port: str = "memory") -> bool:
        """添加参与者"""
        if user_id in self._participants:
            return False
        
        p = User(user_id, name, port)
        self._participants[user_id] = p
        
        if self._on_join_cb:
            self._on_join_cb(p)
        
        return True
    
    def remove(self, user_id: str) -> bool:
        """移除参与者"""
        if user_id not in self._participants:
            return False
        
        p = self._participants.pop(user_id)
        
        if self._on_leave_cb:
            self._on_leave_cb(p)
        
        return True
    
    def participants(self) -> List[User]:
        """获取所有参与者"""
        return list(self._participants.values())
    
    def get(self, user_id: str) -> Optional[User]:
        """获取指定参与者"""
        return self._participants.get(user_id)
    
    # ===== 消息操作 =====
    def send(self, sender_id: str, content: str, **kwargs) -> bool:
        """发送消息（广播给所有人）"""
        if sender_id not in self._participants:
            return False
        
        sender = self._participants[sender_id]
        
        # 构造消息
        msg = Message(
            sender_id=sender_id,
            sender_name=sender.name,
            content=content,
            room_id=self.room_id,
            **kwargs
        )
        
        # 存储到数据库
        self._storage.add(msg)
        
        # 广播给其他人
        for pid, p in self._participants.items():
            if pid != sender_id and p._callback:
                # 直接创建消息对象并触发回调，避免循环调用
                p_msg = Message(
                    sender_id=sender_id,
                    sender_name=sender.name,
                    content=content,
                    room_id=self.room_id,
                    **kwargs
                )
                p._callback(p_msg)
        
        if self._on_message_cb:
            self._on_message_cb(msg)
        
        return True
    
    def send_to(self, sender_id: str, content: str, recipient_id: str, **kwargs) -> bool:
        """私聊消息"""
        if sender_id not in self._participants or recipient_id not in self._participants:
            return False
        
        sender = self._participants[sender_id]
        recipient = self._participants[recipient_id]
        
        # 将 private 标记添加到 metadata 中
        metadata = kwargs.pop('metadata', {})
        metadata['private'] = True
        
        msg = Message(
            sender_id=sender_id,
            sender_name=sender.name,
            content=content,
            room_id=self.room_id,
            metadata=metadata,
            **kwargs
        )
        
        # 存储
        self._storage.add(msg)
        
        # 只发给接收者
        if recipient._callback:
            # 直接创建消息对象并触发回调，避免循环调用
            p_msg = Message(
                sender_id=sender_id,
                sender_name=sender.name,
                content=content,
                room_id=self.room_id,
                metadata=metadata,
                **kwargs
            )
            recipient._callback(p_msg)
        return True
    
    # ===== 历史消息 =====
    def history(self, limit: int = 100, before: Optional[int] = None) -> List[Message]:
        """获取历史消息"""
        return self._storage.get_recent(self.room_id, limit, before)
    
    def history_by_sender(self, sender_id: str, limit: int = 100) -> List[Message]:
        """获取特定发送者的历史消息"""
        return self._storage.get_by_sender(self.room_id, sender_id, limit)
    
    def get_message_by_id(self, msg_id: str) -> Optional[Message]:
        """根据ID获取消息"""
        return self._storage.get_by_id(msg_id)
    
    def get_replies(self, msg_id: str, limit: int = 50) -> List[Message]:
        """获取某条消息的回复"""
        return self._storage.get_replies(self.room_id, msg_id, limit)
    
    def clear_history(self):
        """清空历史消息"""
        self._storage.clear(self.room_id)
    
    def history_count(self) -> int:
        """获取历史消息总数"""
        return self._storage.count(self.room_id)
    
    # ===== 消息删除 =====
    def delete_message(self, msg_id: str) -> bool:
        """删除单条消息"""
        return self._storage.delete(msg_id)
    
    def delete_user_messages(self, sender_id: str) -> int:
        """删除某人的所有消息"""
        return self._storage.delete_by_sender(self.room_id, sender_id)
    
    # ===== 内部处理 =====
    def _handle_receive(self, participant_id: str, msg: Message):
        """处理从端口收到的消息"""
        if participant_id not in self._participants:
            return
        
        sender = self._participants[participant_id]
        
        # 设置消息属性
        msg.sender_id = participant_id
        msg.sender_name = sender.name
        msg.room_id = self.room_id
        
        # 存储
        self._storage.add(msg)
        
        # 广播给其他人
        for pid, p in self._participants.items():
            if pid != participant_id and p._callback:
                # 直接创建消息对象并触发回调，避免循环调用
                # 确保 metadata 是可序列化的
                safe_metadata = {k: v for k, v in msg.metadata.items() if isinstance(v, (str, int, float, bool, list, dict, type(None)))} if msg.metadata else {}
                p_msg = Message(
                    sender_id=participant_id,
                    sender_name=sender.name,
                    content=msg.content,
                    room_id=self.room_id,
                    metadata=safe_metadata
                )
                p._callback(p_msg)
    
    # ===== 回调设置 =====
    def on_message(self, callback: Callable[[Message], None]):
        """消息回调"""
        self._on_message_cb = callback
    
    def on_join(self, callback: Callable[[User], None]):
        """加入回调"""
        self._on_join_cb = callback
    
    def on_leave(self, callback: Callable[[User], None]):
        """离开回调"""
        self._on_leave_cb = callback
    
    # ===== 生命周期 =====
    def start(self):
        """启动聊天室"""
        pass
    
    def stop(self):
        """停止聊天室"""
        self._storage.close()
    
    def clear_all(self):
        """清空所有数据库文件"""
        self._storage.clear_all()
    
    def __repr__(self):
        """报告信息字符串表示"""
        return f"ChatRoom({self.name}, {len(self._participants)}人, {self.history_count()}条消息)"