package com.zhentao.service;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zhentao.constant.ChatConstants;
import com.zhentao.dto.WsMessage;
import com.zhentao.entity.ChatConversation;
import com.zhentao.entity.ChatMessage;
import com.zhentao.handler.ChatWebSocketHandler;
import com.zhentao.repository.ChatConversationMapper;
import com.zhentao.repository.ChatMessageMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 聊天消息服务（MySQL版本）
 */
@Service
public class ChatMessageService {

    @Autowired
    private ChatMessageMapper chatMessageMapper;

    @Autowired
    private ChatConversationMapper conversationMapper;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    // @Autowired(required = false)
    // private RabbitTemplate rabbitTemplate;

    @Autowired
    private ChatWebSocketHandler webSocketHandler;

    @Autowired
    private OnlineUserService onlineUserService;
    
    @Autowired
    private com.zhentao.mapper.UsersMapper usersMapper;
    
    @Autowired(required = false)
    private com.zhentao.repository.ChatMessageMongoRepository mongoRepository;

    /**
     * 保存并转发消息
     */
    public void saveAndForwardMessage(WsMessage wsMessage, WebSocketSession senderSession) {
        try {
            // 1. 构建ChatMessage实体
            ChatMessage chatMessage = buildChatMessage(wsMessage);
            
            // 2. 直接保存到MySQL（不使用RabbitMQ）
            chatMessageMapper.insert(chatMessage);
            
            // 3. 发送ACK给发送者
            WsMessage ackMessage = new WsMessage();
            ackMessage.setType(ChatConstants.WsMessageType.ACK);
            ackMessage.setMessageId(wsMessage.getMessageId());
            ackMessage.setTimestamp(System.currentTimeMillis());
            sendToSession(senderSession, ackMessage);
            
            // 4. 转发给接收者
            forwardMessageToReceiver(wsMessage);
            
            // 5. 更新会话信息
            updateConversation(chatMessage);
            
            // 6. 增加未读数
            incrementUnreadCount(chatMessage.getToUserId(), chatMessage.getFromUserId());
            
        } catch (Exception e) {
            System.err.println("保存并转发消息失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 构建ChatMessage实体
     */
    private ChatMessage buildChatMessage(WsMessage wsMessage) {
        ChatMessage chatMessage = new ChatMessage();
        chatMessage.setMessageId(wsMessage.getMessageId());
        chatMessage.setConversationId(ChatMessage.generateConversationId(
            wsMessage.getFromUserId(), wsMessage.getToUserId()
        ));
        chatMessage.setFromUserId(wsMessage.getFromUserId());
        chatMessage.setToUserId(wsMessage.getToUserId());
        chatMessage.setMessageType(wsMessage.getMessageType());
        chatMessage.setContent(wsMessage.getContent());
        chatMessage.setMediaUrl(wsMessage.getMediaUrl());
        chatMessage.setThumbnailUrl(wsMessage.getThumbnailUrl());
        chatMessage.setMediaSize(wsMessage.getMediaSize());
        chatMessage.setDuration(wsMessage.getDuration());
        chatMessage.setSendStatus(ChatConstants.SendStatus.SENDING);
        chatMessage.setSendTime(new Date());
        chatMessage.setRetryCount(0);
        chatMessage.setIsRecalled(0);
        chatMessage.setExtraData(wsMessage.getExtraData() != null ? JSONUtil.toJsonStr(wsMessage.getExtraData()) : null);
        chatMessage.setCreateTime(new Date());
        chatMessage.setUpdateTime(new Date());
        return chatMessage;
    }

    /**
     * 转发消息给接收者
     */
    private void forwardMessageToReceiver(WsMessage wsMessage) {
        if (onlineUserService.isUserOnline(wsMessage.getToUserId())) {
            // 用户在线，直接推送
            webSocketHandler.sendMessageToUser(wsMessage.getToUserId(), wsMessage);
            
            // 更新消息状态为已送达
            updateMessageStatus(wsMessage.getMessageId(), ChatConstants.SendStatus.DELIVERED);
        } else {
            // 用户离线，消息会在用户上线时推送
            System.out.println("用户 " + wsMessage.getToUserId() + " 离线，消息将在上线后推送");
        }
    }

    /**
     * 更新消息状态
     */
    public void updateMessageStatus(String messageId, Integer status) {
        UpdateWrapper<ChatMessage> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("message_id", messageId)
                    .set("send_status", status)
                    .set("update_time", new Date());
        
        if (status == ChatConstants.SendStatus.DELIVERED) {
            updateWrapper.set("deliver_time", new Date());
        } else if (status == ChatConstants.SendStatus.READ) {
            updateWrapper.set("read_time", new Date());
        }
        
        chatMessageMapper.update(null, updateWrapper);
    }

    /**
     * 更新会话信息
     */
    private void updateConversation(ChatMessage message) {
        // 更新发送者的会话
        updateUserConversation(message.getFromUserId(), message.getToUserId(), message, false);
        
        // 更新接收者的会话
        updateUserConversation(message.getToUserId(), message.getFromUserId(), message, true);
    }

    /**
     * 更新用户会话
     */
    private void updateUserConversation(Long userId, Long targetUserId, ChatMessage message, boolean incrementUnread) {
        ChatConversation conversation = conversationMapper.selectByUserIdAndTargetUserId(userId, targetUserId);
        
        if (conversation == null) {
            // 创建新会话
            conversation = new ChatConversation();
            conversation.setUserId(userId);
            conversation.setTargetUserId(targetUserId);
            
            // 根据userId判断应该使用哪个用户的信息
            if (userId.equals(message.getFromUserId())) {
                // 当前用户是发送者，对方是接收者
                conversation.setTargetUserName(message.getToUserName());
                conversation.setTargetUserAvatar(null);  // 可以后续补充
            } else {
                // 当前用户是接收者，对方是发送者
                conversation.setTargetUserName(message.getFromUserName());
                conversation.setTargetUserAvatar(message.getFromUserAvatar());
            }
            
            conversation.setUnreadCount(incrementUnread ? 1 : 0);
        } else if (incrementUnread) {
            // 增加未读数
            conversation.setUnreadCount(conversation.getUnreadCount() + 1);
        }
        
        // 更新最后消息信息
        conversation.setLastMessage(getMessagePreview(message));
        conversation.setLastMessageType(message.getMessageType());
        conversation.setLastMessageTime(message.getSendTime());
        conversation.setUpdateTime(new Date());
        
        // 保存或更新
        if (conversation.getId() == null) {
            conversationMapper.insert(conversation);
        } else {
            conversationMapper.updateById(conversation);
        }
        
        // 清除会话列表缓存
        clearConversationListCache(userId);
    }

    /**
     * 获取消息预览文本
     */
    private String getMessagePreview(ChatMessage message) {
        switch (message.getMessageType()) {
            case ChatConstants.MessageType.TEXT:
                return message.getContent();
            case ChatConstants.MessageType.IMAGE:
                return "[图片]";
            case ChatConstants.MessageType.VOICE:
                return "[语音]";
            case ChatConstants.MessageType.VIDEO:
                return "[视频]";
            case ChatConstants.MessageType.FILE:
                return "[文件]";
            default:
                return "[未知消息]";
        }
    }

    /**
     * 增加未读数
     */
    private void incrementUnreadCount(Long userId, Long fromUserId) {
        try {
            String key = ChatConstants.RedisKey.UNREAD_COUNT + userId;
            redisTemplate.opsForHash().increment(key, fromUserId.toString(), 1);
        } catch (Exception e) {
            System.err.println("⚠️ Redis 更新未读数失败: " + e.getMessage());
        }
    }

    /**
     * 标记消息为已读
     */
    public void markMessagesAsRead(Long userId, Long targetUserId) {
        // 1. 更新MySQL中的消息状态
        chatMessageMapper.updateMessagesToRead(userId, targetUserId);
        
        // 2. 清空未读数（Redis）
        try {
            String key = ChatConstants.RedisKey.UNREAD_COUNT + userId;
            redisTemplate.opsForHash().delete(key, targetUserId.toString());
        } catch (Exception e) {
            System.err.println("⚠️ Redis 清空未读数失败: " + e.getMessage());
        }
        
        // 3. 更新会话未读数（MySQL）
        conversationMapper.clearUnreadCount(userId, targetUserId);
        
        // 4. 清除会话列表缓存
        clearConversationListCache(userId);
        
        // 5. 发送已读回执给对方
        WsMessage readReceipt = new WsMessage();
        readReceipt.setType(ChatConstants.WsMessageType.READ_RECEIPT);
        readReceipt.setFromUserId(userId);
        readReceipt.setToUserId(targetUserId);
        readReceipt.setTimestamp(System.currentTimeMillis());
        webSocketHandler.sendMessageToUser(targetUserId, readReceipt);
    }

    /**
     * 推送离线消息
     */
    public void pushOfflineMessages(Long userId, WebSocketSession session) {
        try {
            // 查询离线消息（最多500条）
            List<ChatMessage> offlineMessages = chatMessageMapper.selectOfflineMessages(
                userId, 
                ChatConstants.Limit.MAX_OFFLINE_MESSAGES
            );
            
            if (!offlineMessages.isEmpty()) {
                System.out.println("推送 " + offlineMessages.size() + " 条离线消息给用户 " + userId);
                
                for (ChatMessage message : offlineMessages) {
                    WsMessage wsMessage = convertToWsMessage(message);
                    sendToSession(session, wsMessage);
                    
                    // 更新为已送达
                    updateMessageStatus(message.getMessageId(), ChatConstants.SendStatus.DELIVERED);
                }
            }
        } catch (Exception e) {
            System.err.println("推送离线消息失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 撤回消息
     */
    public void recallMessage(String messageId, Long userId, WebSocketSession session) {
        try {
            ChatMessage message = chatMessageMapper.selectByMessageId(messageId);
            
            if (message == null) {
                sendError(session, "消息不存在");
                return;
            }
            
            if (!message.getFromUserId().equals(userId)) {
                sendError(session, "只能撤回自己的消息");
                return;
            }
            
            // 检查时间限制（2分钟内）
            long diff = System.currentTimeMillis() - message.getSendTime().getTime();
            if (diff > ChatConstants.TimeLimit.MESSAGE_RECALL_TIME) {
                sendError(session, "超过撤回时间限制");
                return;
            }
            
            // 更新消息为已撤回
            chatMessageMapper.recallMessage(messageId);
            
            // 通知接收者
            WsMessage recallNotice = new WsMessage();
            recallNotice.setType(ChatConstants.WsMessageType.RECALL);
            recallNotice.setMessageId(messageId);
            recallNotice.setFromUserId(userId);
            recallNotice.setToUserId(message.getToUserId());
            recallNotice.setTimestamp(System.currentTimeMillis());
            
            webSocketHandler.sendMessageToUser(message.getToUserId(), recallNotice);
            
            System.out.println("消息已撤回: " + messageId);
            
        } catch (Exception e) {
            System.err.println("撤回消息失败: " + e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 查询会话消息列表（分页）
     */
    public IPage<ChatMessage> getConversationMessages(Long userId, Long targetUserId, int page, int size) {
        String conversationId = ChatMessage.generateConversationId(userId, targetUserId);
        Page<ChatMessage> pageParam = new Page<>(page + 1, size);
        return chatMessageMapper.selectByConversationId(pageParam, conversationId);
    }
    
    /**
     * 使用游标分页查询会话消息（性能更好）
     * 基于lastMessageId向前查询，避免OFFSET的性能问题
     */
    public IPage<ChatMessage> getConversationMessagesWithCursor(Long userId, Long targetUserId, 
                                                                 String lastMessageId, int size) {
        String conversationId = ChatMessage.generateConversationId(userId, targetUserId);
        
        // 获取lastMessageId对应的消息
        ChatMessage lastMessage = chatMessageMapper.selectByMessageId(lastMessageId);
        if (lastMessage == null) {
            // 如果找不到lastMessage，返回最新的消息
            Page<ChatMessage> pageParam = new Page<>(1, size);
            return chatMessageMapper.selectByConversationId(pageParam, conversationId);
        }
        
        // 查询比lastMessage更早的消息
        QueryWrapper<ChatMessage> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("conversation_id", conversationId)
                    .lt("id", lastMessage.getId())  // 使用自增ID比较，性能更好
                    .orderByDesc("id")
                    .last("LIMIT " + size);
        
        List<ChatMessage> messages = chatMessageMapper.selectList(queryWrapper);
        
        // 构造分页结果
        Page<ChatMessage> page = new Page<>(1, size);
        page.setRecords(messages);
        page.setTotal(messages.size());
        
        return page;
    }

    /**
     * 转换为WsMessage
     */
    private WsMessage convertToWsMessage(ChatMessage chatMessage) {
        WsMessage wsMessage = new WsMessage();
        wsMessage.setType(ChatConstants.WsMessageType.CHAT);
        wsMessage.setMessageId(chatMessage.getMessageId());
        wsMessage.setFromUserId(chatMessage.getFromUserId());
        wsMessage.setToUserId(chatMessage.getToUserId());
        wsMessage.setMessageType(chatMessage.getMessageType());
        wsMessage.setContent(chatMessage.getContent());
        wsMessage.setMediaUrl(chatMessage.getMediaUrl());
        wsMessage.setThumbnailUrl(chatMessage.getThumbnailUrl());
        wsMessage.setMediaSize(chatMessage.getMediaSize());
        wsMessage.setDuration(chatMessage.getDuration());
        wsMessage.setTimestamp(chatMessage.getSendTime().getTime());
        if (chatMessage.getExtraData() != null) {
            @SuppressWarnings("unchecked")
            Map<String, Object> extraDataMap = JSONUtil.toBean(chatMessage.getExtraData(), java.util.Map.class);
            wsMessage.setExtraData(extraDataMap);
        }
        return wsMessage;
    }

    /**
     * 发送消息到WebSocket会话
     */
    private void sendToSession(WebSocketSession session, WsMessage message) {
        if (session != null && session.isOpen()) {
            try {
                String json = JSONUtil.toJsonStr(message);
                session.sendMessage(new TextMessage(json));
            } catch (IOException e) {
                System.err.println("发送消息失败: " + e.getMessage());
            }
        }
    }

    /**
     * 发送错误消息
     */
    private void sendError(WebSocketSession session, String errorMessage) {
        WsMessage error = new WsMessage();
        error.setType(ChatConstants.WsMessageType.ERROR);
        error.setErrorMessage(errorMessage);
        error.setTimestamp(System.currentTimeMillis());
        sendToSession(session, error);
    }

    /**
     * 清除会话列表缓存
     */
    private void clearConversationListCache(Long userId) {
        try {
            String key = ChatConstants.RedisKey.CONVERSATION_LIST + userId;
            redisTemplate.delete(key);
        } catch (Exception e) {
            System.err.println("⚠️ Redis 清除缓存失败: " + e.getMessage());
        }
    }
    
    /**
     * 根据messageId查询消息
     */
    public ChatMessage getMessageByMessageId(String messageId) {
        QueryWrapper<ChatMessage> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("message_id", messageId);
        return chatMessageMapper.selectOne(queryWrapper);
    }
    
    /**
     * 保存聊天消息（用于TIM消息同步）
     * 三重存储：MySQL + MongoDB
     */
    public void saveChatMessage(ChatMessage chatMessage) {
        // 1. 保存到MySQL
        chatMessageMapper.insert(chatMessage);
        System.out.println("✅ 消息已保存到MySQL: " + chatMessage.getMessageId());
        
        // 2. 同时保存到MongoDB（异步，失败不影响主流程）
        saveToMongoDB(chatMessage);
    }
    
    /**
     * 保存消息到MongoDB
     */
    private void saveToMongoDB(ChatMessage chatMessage) {
        if (mongoRepository == null) {
            System.out.println("⚠️ MongoDB未配置，跳过MongoDB存储");
            return;
        }
        
        try {
            // 转换为MongoDB实体
            com.zhentao.entity.ChatMessageMongo mongoMessage = new com.zhentao.entity.ChatMessageMongo();
            mongoMessage.setMessageId(chatMessage.getMessageId());
            mongoMessage.setConversationId(chatMessage.getConversationId());
            mongoMessage.setFromUserId(chatMessage.getFromUserId());
            mongoMessage.setFromUserName(chatMessage.getFromUserName());
            mongoMessage.setFromUserAvatar(chatMessage.getFromUserAvatar());
            mongoMessage.setToUserId(chatMessage.getToUserId());
            mongoMessage.setToUserName(chatMessage.getToUserName());
            mongoMessage.setMessageType(chatMessage.getMessageType());
            mongoMessage.setContent(chatMessage.getContent());
            mongoMessage.setMediaUrl(chatMessage.getMediaUrl());
            mongoMessage.setThumbnailUrl(chatMessage.getThumbnailUrl());
            mongoMessage.setMediaSize(chatMessage.getMediaSize());
            mongoMessage.setDuration(chatMessage.getDuration());
            mongoMessage.setSendStatus(chatMessage.getSendStatus());
            mongoMessage.setSendTime(chatMessage.getSendTime());
            mongoMessage.setDeliverTime(chatMessage.getDeliverTime());
            mongoMessage.setReadTime(chatMessage.getReadTime());
            mongoMessage.setSource("TIM");
            mongoMessage.setCreatedAt(new java.util.Date());
            mongoMessage.setUpdatedAt(new java.util.Date());
            
            // 保存到MongoDB
            mongoRepository.save(mongoMessage);
            System.out.println("✅ 消息已同步到MongoDB: " + chatMessage.getMessageId());
            
        } catch (Exception e) {
            // MongoDB存储失败不影响主流程
            System.err.println("⚠️ MongoDB存储失败（不影响主流程）: " + e.getMessage());
        }
    }
    
    /**
     * 更新或创建会话（用于TIM消息同步）
     */
    public void updateOrCreateConversation(Long fromUserId, Long toUserId, String content, 
                                           Integer messageType, Date sendTime) {
        // 更新发送者的会话
        updateUserConversationSimple(fromUserId, toUserId, content, messageType, sendTime, false);
        
        // 更新接收者的会话
        updateUserConversationSimple(toUserId, fromUserId, content, messageType, sendTime, true);
    }
    
    /**
     * 更新用户会话（简化版，用于TIM同步）
     */
    private void updateUserConversationSimple(Long userId, Long targetUserId, String content,
                                             Integer messageType, Date sendTime, boolean incrementUnread) {
        ChatConversation conversation = conversationMapper.selectByUserIdAndTargetUserId(userId, targetUserId);
        
        if (conversation == null) {
            // 创建新会话
            conversation = new ChatConversation();
            conversation.setUserId(userId);
            conversation.setTargetUserId(targetUserId);
            
            // 查询目标用户信息
            try {
                com.zhentao.pojo.Users targetUser = usersMapper.selectById(targetUserId.intValue());
                if (targetUser != null) {
                    conversation.setTargetUserName(targetUser.getNickname());
                    conversation.setTargetUserAvatar(targetUser.getAvatarUrl());
                } else {
                    conversation.setTargetUserName("用户" + targetUserId);
                }
            } catch (Exception e) {
                conversation.setTargetUserName("用户" + targetUserId);
            }
            
            conversation.setUnreadCount(incrementUnread ? 1 : 0);
            
            // 设置创建时间（必填字段）
            conversation.setCreateTime(new Date());
        } else {
            // 更新现有会话
            if (incrementUnread) {
                conversation.setUnreadCount(conversation.getUnreadCount() + 1);
            }
        }
        
        // 更新最后消息信息
        conversation.setLastMessage(getMessagePreviewSimple(content, messageType));
        conversation.setLastMessageType(messageType);
        conversation.setLastMessageTime(sendTime);
        conversation.setUpdateTime(new Date());
        
        // 保存或更新
        if (conversation.getId() == null) {
            conversationMapper.insert(conversation);
        } else {
            conversationMapper.updateById(conversation);
        }
        
        // 清除缓存
        clearConversationListCache(userId);
    }
    
    /**
     * 获取消息预览（简化版）
     */
    private String getMessagePreviewSimple(String content, Integer messageType) {
        switch (messageType) {
            case 1: // TEXT
                return content;
            case 2: // IMAGE
                return "[图片]";
            case 3: // VOICE
                return "[语音]";
            case 4: // VIDEO
                return "[视频]";
            case 5: // FILE
                return "[文件]";
            default:
                return "[未知消息]";
        }
    }
}
