import pytest
from fastchatrooms.user import User
from fastchatrooms.message import Message
from fastchatrooms.chatroom import ChatRoom
from fastchatrooms.store.sqlitestore import SQLiteStorage


class TestUser:
    """测试 User 类"""
    
    def test_user_creation(self):
        """测试用户创建"""
        user = User('123', 'Test User')
        assert user._id == '123'
        assert user.name == 'Test User'
        assert user.porttype == 'memory'
        assert user._callback is None
        assert isinstance(user.jointime, int)
    
    def test_to_dict(self):
        """测试 to_dict 方法"""
        user = User('123', 'Test User')
        user_dict = user.to_dict()
        assert user_dict['_id'] == '123'
        assert user_dict['name'] == 'Test User'
        assert user_dict['port'] == 'memory'
        assert isinstance(user_dict['jointime'], int)
    
    def test_send(self):
        """测试 send 方法"""
        user = User('123', 'Test User')
        received_msg = None
        
        def callback(msg):
            nonlocal received_msg
            received_msg = msg
        
        user.on_receive(callback)
        result = user.send('Hello')
        assert result is True
        assert received_msg is not None
        assert received_msg.content == 'Hello'
    
    def test_send_no_callback(self):
        """测试没有回调时的 send 方法"""
        user = User('123', 'Test User')
        result = user.send('Hello')
        assert result is False


class TestMessage:
    """测试 Message 类"""
    
    def test_message_creation(self):
        """测试消息创建"""
        msg = Message(sender_id='123', sender_name='Test User', content='Hello')
        assert msg.sender_id == '123'
        assert msg.sender_name == 'Test User'
        assert msg.content == 'Hello'
        assert msg.msg_type == 'text'
        assert isinstance(msg.timestamp, int)
        assert msg.reply_to is None
        assert msg.room_id == ''
        assert isinstance(msg.metadata, dict)
    
    def test_to_dict(self):
        """测试 to_dict 方法"""
        msg = Message(sender_id='123', sender_name='Test User', content='Hello')
        msg_dict = msg.to_dict()
        assert msg_dict['sender_id'] == '123'
        assert msg_dict['sender_name'] == 'Test User'
        assert msg_dict['content'] == 'Hello'
        assert msg_dict['msg_type'] == 'text'
        assert isinstance(msg_dict['timestamp'], int)
        assert msg_dict['reply_to'] is None
        assert msg_dict['room_id'] == ''
        assert isinstance(msg_dict['metadata'], dict)
    
    def test_from_dict(self):
        """测试 from_dict 方法"""
        msg_dict = {
            'sender_id': '123',
            'sender_name': 'Test User',
            'content': 'Hello',
            'msg_type': 'text',
            'timestamp': 1234567890,
            'reply_to': None,
            'room_id': 'room123',
            'metadata': {'key': 'value'}
        }
        msg = Message.from_dict(msg_dict)
        assert msg.sender_id == '123'
        assert msg.sender_name == 'Test User'
        assert msg.content == 'Hello'
        assert msg.msg_type == 'text'
        assert msg.timestamp == 1234567890
        assert msg.reply_to is None
        assert msg.room_id == 'room123'
        assert msg.metadata == {'key': 'value'}
    
    def test_reply(self):
        """测试 reply 方法"""
        msg = Message(sender_id='123', sender_name='Test User', content='Hello', room_id='room123')
        reply_msg = msg.reply('Hello back', '456')
        assert reply_msg.sender_id == '456'
        assert reply_msg.content == 'Hello back'
        assert reply_msg.reply_to == msg._id
        assert reply_msg.room_id == 'room123'


class TestChatRoom:
    """测试 ChatRoom 类"""
    
    def setup_method(self):
        """设置测试环境"""
        self.chatroom = ChatRoom('Test Room')
    
    def test_chatroom_creation(self):
        """测试聊天室创建"""
        assert self.chatroom.name == 'Test Room'
        assert isinstance(self.chatroom.room_id, str)
        assert len(self.chatroom._participants) == 0
        assert self.chatroom._on_message_cb is None
        assert self.chatroom._on_join_cb is None
        assert self.chatroom._on_leave_cb is None
    
    def test_add_user(self):
        """测试添加用户"""
        result = self.chatroom.add('123', 'Test User')
        assert result is True
        assert '123' in self.chatroom._participants
        assert self.chatroom._participants['123'].name == 'Test User'
    
    def test_add_existing_user(self):
        """测试添加已存在的用户"""
        self.chatroom.add('123', 'Test User')
        result = self.chatroom.add('123', 'Test User')
        assert result is False
    
    def test_remove_user(self):
        """测试移除用户"""
        self.chatroom.add('123', 'Test User')
        result = self.chatroom.remove('123')
        assert result is True
        assert '123' not in self.chatroom._participants
    
    def test_remove_nonexistent_user(self):
        """测试移除不存在的用户"""
        result = self.chatroom.remove('123')
        assert result is False
    
    def test_participants(self):
        """测试获取所有参与者"""
        self.chatroom.add('123', 'Test User 1')
        self.chatroom.add('456', 'Test User 2')
        participants = self.chatroom.participants()
        assert len(participants) == 2
        assert any(p.name == 'Test User 1' for p in participants)
        assert any(p.name == 'Test User 2' for p in participants)
    
    def test_get_user(self):
        """测试获取指定参与者"""
        self.chatroom.add('123', 'Test User')
        user = self.chatroom.get('123')
        assert user is not None
        assert user.name == 'Test User'
    
    def test_get_nonexistent_user(self):
        """测试获取不存在的参与者"""
        user = self.chatroom.get('123')
        assert user is None
    
    def test_send_message(self):
        """测试发送消息"""
        self.chatroom.add('123', 'Test User')
        result = self.chatroom.send('123', 'Hello everyone')
        assert result is True
        messages = self.chatroom.history()
        assert len(messages) == 1
        assert messages[0].content == 'Hello everyone'
    
    def test_send_message_nonexistent_user(self):
        """测试发送消息给不存在的用户"""
        result = self.chatroom.send('123', 'Hello everyone')
        assert result is False
    
    def test_send_to(self):
        """测试私聊消息"""
        self.chatroom.add('123', 'Test User 1')
        self.chatroom.add('456', 'Test User 2')
        result = self.chatroom.send_to('123', 'Hello private', '456')
        assert result is True
        messages = self.chatroom.history()
        assert len(messages) == 1
        assert messages[0].content == 'Hello private'
    
    def test_send_to_nonexistent_user(self):
        """测试私聊消息给不存在的用户"""
        self.chatroom.add('123', 'Test User 1')
        result = self.chatroom.send_to('123', 'Hello private', '456')
        assert result is False
    
    def test_history(self):
        """测试获取历史消息"""
        self.chatroom.add('123', 'Test User')
        for i in range(5):
            self.chatroom.send('123', f'Message {i}')
        messages = self.chatroom.history()
        assert len(messages) == 5
        assert messages[0].content == 'Message 0'
        assert messages[-1].content == 'Message 4'
    
    def test_history_by_sender(self):
        """测试获取特定发送者的历史消息"""
        self.chatroom.add('123', 'Test User 1')
        self.chatroom.add('456', 'Test User 2')
        self.chatroom.send('123', 'Message from 123')
        self.chatroom.send('456', 'Message from 456')
        self.chatroom.send('123', 'Another message from 123')
        messages = self.chatroom.history_by_sender('123')
        assert len(messages) == 2
        assert all(msg.sender_id == '123' for msg in messages)
    
    def test_get_message_by_id(self):
        """测试根据ID获取消息"""
        self.chatroom.add('123', 'Test User')
        self.chatroom.send('123', 'Hello')
        messages = self.chatroom.history()
        msg_id = messages[0]._id
        msg = self.chatroom.get_message_by_id(msg_id)
        assert msg is not None
        assert msg._id == msg_id
    
    def test_get_message_by_nonexistent_id(self):
        """测试根据不存在的ID获取消息"""
        msg = self.chatroom.get_message_by_id('nonexistent')
        assert msg is None
    
    def test_clear_history(self):
        """测试清空历史消息"""
        self.chatroom.add('123', 'Test User')
        self.chatroom.send('123', 'Hello')
        assert len(self.chatroom.history()) == 1
        self.chatroom.clear_history()
        assert len(self.chatroom.history()) == 0
    
    def test_history_count(self):
        """测试获取历史消息总数"""
        self.chatroom.add('123', 'Test User')
        assert self.chatroom.history_count() == 0
        self.chatroom.send('123', 'Hello')
        assert self.chatroom.history_count() == 1
    
    def test_delete_message(self):
        """测试删除单条消息"""
        self.chatroom.add('123', 'Test User')
        self.chatroom.send('123', 'Hello')
        messages = self.chatroom.history()
        msg_id = messages[0]._id
        result = self.chatroom.delete_message(msg_id)
        assert result is True
        assert len(self.chatroom.history()) == 0
    
    def test_delete_user_messages(self):
        """测试删除某人的所有消息"""
        self.chatroom.add('123', 'Test User 1')
        self.chatroom.add('456', 'Test User 2')
        self.chatroom.send('123', 'Message from 123')
        self.chatroom.send('456', 'Message from 456')
        self.chatroom.send('123', 'Another message from 123')
        count = self.chatroom.delete_user_messages('123')
        assert count == 2
        messages = self.chatroom.history()
        assert len(messages) == 1
        assert messages[0].sender_id == '456'


class TestSQLiteStorage:
    """测试 SQLiteStorage 类"""
    
    def setup_method(self):
        """设置测试环境"""
        self.storage = SQLiteStorage('./test_data')
    
    def test_add_message(self):
        """测试添加消息"""
        msg = Message(sender_id='123', sender_name='Test User', content='Hello', room_id='room123')
        result = self.storage.add(msg)
        assert result is True
    
    def test_get_recent(self):
        """测试获取最近消息"""
        room_id = 'room123'
        for i in range(5):
            msg = Message(sender_id='123', sender_name='Test User', content=f'Message {i}', room_id=room_id)
            self.storage.add(msg)
        messages = self.storage.get_recent(room_id)
        assert len(messages) == 5
    
    def test_get_by_id(self):
        """测试根据ID获取消息"""
        msg = Message(sender_id='123', sender_name='Test User', content='Hello', room_id='room123')
        self.storage.add(msg)
        retrieved_msg = self.storage.get_by_id(msg._id)
        assert retrieved_msg is not None
        assert retrieved_msg._id == msg._id
    
    def test_get_by_sender(self):
        """测试获取特定发送者的消息"""
        room_id = 'room123'
        for i in range(3):
            msg = Message(sender_id='123', sender_name='Test User', content=f'Message {i}', room_id=room_id)
            self.storage.add(msg)
        messages = self.storage.get_by_sender(room_id, '123')
        assert len(messages) == 3
    
    def test_get_replies(self):
        """测试获取某条消息的回复"""
        room_id = 'room123'
        parent_msg = Message(sender_id='123', sender_name='Test User', content='Hello', room_id=room_id)
        self.storage.add(parent_msg)
        for i in range(2):
            reply_msg = Message(sender_id='456', sender_name='Another User', content=f'Reply {i}', room_id=room_id, reply_to=parent_msg._id)
            self.storage.add(reply_msg)
        replies = self.storage.get_replies(room_id, parent_msg._id)
        assert len(replies) == 2
    
    def test_delete(self):
        """测试删除单条消息"""
        msg = Message(sender_id='123', sender_name='Test User', content='Hello', room_id='room123')
        self.storage.add(msg)
        result = self.storage.delete(msg._id)
        assert result is True
    
    def test_delete_by_sender(self):
        """测试删除指定发送者的所有消息"""
        room_id = 'room123'
        for i in range(3):
            msg = Message(sender_id='123', sender_name='Test User', content=f'Message {i}', room_id=room_id)
            self.storage.add(msg)
        count = self.storage.delete_by_sender(room_id, '123')
        assert count == 3
    
    def test_delete_all(self):
        """测试删除指定房间的所有消息"""
        room_id = 'room123'
        for i in range(3):
            msg = Message(sender_id='123', sender_name='Test User', content=f'Message {i}', room_id=room_id)
            self.storage.add(msg)
        count = self.storage.delete_all(room_id)
        assert count == 3
    
    def test_clear(self):
        """测试清空指定房间的消息"""
        room_id = 'room123'
        for i in range(3):
            msg = Message(sender_id='123', sender_name='Test User', content=f'Message {i}', room_id=room_id)
            self.storage.add(msg)
        self.storage.clear(room_id)
        messages = self.storage.get_recent(room_id)
        assert len(messages) == 0
    
    def test_count(self):
        """测试获取消息总数"""
        room_id = 'room123'
        assert self.storage.count(room_id) == 0
        for i in range(3):
            msg = Message(sender_id='123', sender_name='Test User', content=f'Message {i}', room_id=room_id)
            self.storage.add(msg)
        assert self.storage.count(room_id) == 3
    
    def teardown_method(self):
        """清理测试环境"""
        # 关闭所有数据库连接
        self.storage.close()
        # 清理测试目录
        import shutil
        import os
        if os.path.exists('./test_data'):
            # 等待一段时间，确保文件锁被释放
            import time
            time.sleep(0.1)
            shutil.rmtree('./test_data')
