package org.xyzh.message.service.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xyzh.api.message.MessageService;
import org.xyzh.common.core.domain.ResultDomain;
import org.xyzh.common.core.page.PageDomain;
import org.xyzh.common.core.page.PageParam;
import org.xyzh.common.dto.message.*;
import org.xyzh.common.utils.IDUtils;
import org.xyzh.message.mapper.MessageMapper;
import org.xyzh.message.mapper.MessageTargetMapper;
import org.xyzh.message.mapper.MessageUserMapper;
import org.xyzh.system.mapper.DepartmentMapper;
import org.xyzh.system.mapper.UserMapper;

import java.util.*;

/**
 * 消息服务实现类
 *
 * @description 消息通知模块的服务实现
 * @filename MessageServiceImpl.java
 * @author Claude
 * @copyright xyzh
 * @since 2025-11-13
 */
@Service
public class MessageServiceImpl implements MessageService {

    private static final Logger logger = LoggerFactory.getLogger(MessageServiceImpl.class);

    @Autowired
    private MessageMapper messageMapper;

    @Autowired
    private MessageTargetMapper messageTargetMapper;

    @Autowired
    private MessageUserMapper messageUserMapper;

    @Autowired
    private DepartmentMapper departmentMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private MessageSendService messageSendService;

    /**
     * 创建消息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDomain<TbSysMessage> createMessage(TbSysMessage message) {
        ResultDomain<TbSysMessage> rt =  new ResultDomain<>();
        try {
            // 1. 获取当前用户信息（从Session或SecurityContext获取）
            String currentUserID = getCurrentUserID();
            String currentDeptID = getCurrentUserDeptID();

            // 2. 设置消息主体基本信息
            if (message.getID() == null) {
                message.setID(IDUtils.generateID());
            }
            if (message.getMessageID() == null) {
                message.setMessageID(IDUtils.generateID());
            }
            message.setSenderID(currentUserID);
            message.setSenderDeptID(currentDeptID);

            // 设置状态
            if (message.getStatus() == null) {
                if ("immediate".equals(message.getSendMode())) {
                    message.setStatus("sending");
                } else {
                    message.setStatus("pending");
                }
            }

            if (message.getTargetUserCount() == null) {
                message.setTargetUserCount(0);
            }
            if (message.getRetryCount() == null) {
                message.setRetryCount(0);
            }
            if (message.getMaxRetryCount() == null) {
                message.setMaxRetryCount(3);
            }
            message.setCreator(currentUserID);
            message.setCreateTime(new Date());
            message.setUpdateTime(new Date());
            message.setDeleted(false);

            // 保存消息主体
            messageMapper.insertMessage(message);

            // 3. 保存接收对象配置
            List<TbSysMessageTarget> targets = message.getTargets();
            if (targets != null && !targets.isEmpty()) {
                for (TbSysMessageTarget target : targets) {
                    // 权限校验：scopeDeptID必须是当前部门或子部门
                    if (!isCurrentOrSubDept(currentDeptID, target.getScopeDeptID())) {
                        rt.fail("无权向该部门发送消息");
                        return rt;
                    }

                    if (target.getID() == null) {
                        target.setID(IDUtils.generateID());
                    }
                    target.setMessageID(message.getMessageID());
                    target.setCreator(currentUserID);
                    target.setCreateTime(new Date());
                    target.setUpdateTime(new Date());
                    target.setDeleted(false);
                }
                messageTargetMapper.batchInsert(targets);

                // 4. 解析接收对象，生成用户消息列表
                List<TbSysMessageUser> userMessages = resolveTargetUsers(message.getMessageID(), targets, currentUserID);
                if (!userMessages.isEmpty()) {
                    messageUserMapper.batchInsert(userMessages);
                }

                // 5. 更新目标用户总数
                message.setTargetUserCount(userMessages.size());
                messageMapper.updateMessage(message);

                // 6. 如果是立即发送，异步发送消息
                if ("immediate".equals(message.getSendMode())) {
                    messageSendService.sendMessageAsync(message.getMessageID());
                }
            }

            rt.success("创建成功", message);
            return rt;

        } catch (Exception e) {
            logger.error("创建消息失败", e);
            rt.fail("创建消息失败：" + e.getMessage());
            return rt;
        }
    }

    /**
     * 更新消息（仅允许更新草稿状态的消息）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDomain<TbSysMessage> updateMessage(TbSysMessage message) {
        ResultDomain<TbSysMessage> rt =  new ResultDomain<>();
        try {
            // 查询原消息
            TbSysMessage existingMessage = messageMapper.selectMessageById(message.getMessageID());
            if (existingMessage == null || existingMessage.getDeleted()) {
                rt.fail("消息不存在");
                return rt;
            }

            // 只允许更新草稿状态的消息
            if (!"draft".equals(existingMessage.getStatus())) {
                rt.fail("只能更新草稿状态的消息");
                return rt;
            }

            message.setUpdateTime(new Date());
            message.setUpdater(getCurrentUserID());
            messageMapper.updateMessage(message);
            rt.success("更新成功", message);
            return rt;

        } catch (Exception e) {
            logger.error("更新消息失败", e);
            rt.fail("更新消息失败："+e.getMessage());
            return rt;
        }
    }

    /**
     * 删除消息（逻辑删除）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDomain<TbSysMessage> deleteMessage(String messageID) {
        ResultDomain<TbSysMessage> rt = new ResultDomain<>();
        try {
            TbSysMessage message = messageMapper.selectMessageById(messageID);

            if (message == null || message.getDeleted()) {
                rt.fail("消息不存在");
                return rt;
            }

            int result = messageMapper.deleteMessage(messageID);
            if (result > 0) {
                // 同时删除关联的接收对象和用户消息
                messageTargetMapper.deleteByMessageID(messageID);
                rt.success("删除成功", message);
            } else {
                rt.fail("删除失败");
            }
            return rt;

        } catch (Exception e) {
            logger.error("删除消息失败", e);
            rt.fail("删除消息失败：" + e.getMessage());
            return rt;
        }
    }

    /**
     * 根据ID查询消息详情
     */
    @Override
    public ResultDomain<MessageVO> getMessageById(String messageID) {
        ResultDomain<MessageVO> rt = new ResultDomain<>();
        try {
            MessageVO messageVO = messageMapper.selectMessageDetail(messageID);
            if (messageVO == null) {
                rt.fail("消息不存在");
                return rt;
            }

            // 查询接收对象列表
            List<TbSysMessageTarget> targets = messageTargetMapper.selectByMessageID(messageID);
            messageVO.setTargets(targets);

            // 查询用户接收记录
            List<MessageUserVO> userMessages = messageUserMapper.selectByMessageID(messageID);
            messageVO.setUserMessages(userMessages);

            rt.success("查询成功", messageVO);
            return rt;

        } catch (Exception e) {
            logger.error("查询消息详情失败", e);
            rt.fail("查询消息详情失败：" + e.getMessage());
            return rt;
        }
    }

    /**
     * 分页查询消息列表（管理端）
     */
    @Override
    public ResultDomain<MessageVO> getMessagePage(TbSysMessage filter, PageParam pageParam) {
        ResultDomain<MessageVO> rt = new ResultDomain<>();
        try {
            if (filter == null) {
                filter = new TbSysMessage();
            }
            filter.setDeleted(false);
            
            if (pageParam == null) {
                pageParam = new PageParam();
            }

            String currentDeptID = getCurrentUserDeptID();
            
            List<MessageVO> list = messageMapper.selectMessagePage(filter, currentDeptID);
            int total = messageMapper.countMessage(filter, currentDeptID);
            
            PageDomain<MessageVO> pageDomain = new PageDomain<>();
            pageDomain.setDataList(list);
            pageParam.setTotalElements(total);
            pageParam.setTotalPages((int) Math.ceil((double) total / pageParam.getPageSize()));
            pageDomain.setPageParam(pageParam);
            
            rt.success("查询成功", pageDomain);
            return rt;

        } catch (Exception e) {
            logger.error("查询消息列表失败", e);
            rt.fail("查询消息列表失败：" + e.getMessage());
            return rt;
        }
    }

    /**
     * 发送消息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDomain<TbSysMessage> sendMessage(String messageID) {
        ResultDomain<TbSysMessage> rt = new ResultDomain<>();
        try {
            TbSysMessage message = messageMapper.selectMessageById(messageID);

            if (message == null || message.getDeleted()) {
                rt.fail("消息不存在");
                return rt;
            }

            // 更新状态为发送中
            message.setStatus("sending");
            message.setActualSendTime(new Date());
            message.setUpdateTime(new Date());
            messageMapper.updateMessage(message);

            // 异步发送
            messageSendService.sendMessageAsync(messageID);

            rt.success("发送成功", message);
            return rt;

        } catch (Exception e) {
            logger.error("发送消息失败", e);
            rt.fail("发送消息失败：" + e.getMessage());
            return rt;
        }
    }

    /**
     * 立即发送（将定时消息改为立即发送）
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDomain<TbSysMessage> sendNow(String messageID) {
        ResultDomain<TbSysMessage> rt = new ResultDomain<>();
        try {
            TbSysMessage message = messageMapper.selectMessageById(messageID);

            if (message == null || message.getDeleted()) {
                rt.fail("消息不存在");
                return rt;
            }

            if (!"pending".equals(message.getStatus())) {
                rt.fail("只能立即发送待发送状态的消息");
                return rt;
            }

            // 更新为立即发送模式
            message.setSendMode("immediate");
            message.setStatus("sending");
            message.setActualSendTime(new Date());
            message.setUpdateTime(new Date());
            messageMapper.updateMessage(message);

            // 异步发送
            messageSendService.sendMessageAsync(messageID);

            rt.success("立即发送成功", message);
            return rt;

        } catch (Exception e) {
            logger.error("立即发送消息失败", e);
            rt.fail("立即发送消息失败：" + e.getMessage());
            return rt;
        }
    }

    /**
     * 取消定时消息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDomain<TbSysMessage> cancelMessage(String messageID) {
        ResultDomain<TbSysMessage> rt = new ResultDomain<>();
        try {
            TbSysMessage message = messageMapper.selectMessageById(messageID);

            if (message == null || message.getDeleted()) {
                rt.fail("消息不存在");
                return rt;
            }

            if (!"pending".equals(message.getStatus())) {
                rt.fail("只能取消待发送状态的消息");
                return rt;
            }

            message.setStatus("cancelled");
            message.setUpdateTime(new Date());
            messageMapper.updateMessage(message);

            rt.success("取消成功", message);
            return rt;

        } catch (Exception e) {
            logger.error("取消消息失败", e);
            rt.fail("取消消息失败：" + e.getMessage());
            return rt;
        }
    }

    /**
     * 修改定时发送时间
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDomain<TbSysMessage> rescheduleMessage(String messageID, Date scheduledTime) {
        ResultDomain<TbSysMessage> rt = new ResultDomain<>();
        try {
            TbSysMessage message = messageMapper.selectMessageById(messageID);

            if (message == null || message.getDeleted()) {
                rt.fail("消息不存在");
                return rt;
            }

            if (!"pending".equals(message.getStatus())) {
                rt.fail("只能修改待发送状态的消息");
                return rt;
            }

            message.setScheduledTime(scheduledTime);
            message.setUpdateTime(new Date());
            messageMapper.updateMessage(message);

            rt.success("修改成功", message);
            return rt;

        } catch (Exception e) {
            logger.error("修改定时时间失败", e);
            rt.fail("修改定时时间失败：" + e.getMessage());
            return rt;
        }
    }

    /**
     * 重试失败消息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDomain<TbSysMessage> retryMessage(String messageID) {
        ResultDomain<TbSysMessage> rt = new ResultDomain<>();
        try {
            TbSysMessage message = messageMapper.selectMessageById(messageID);

            if (message == null || message.getDeleted()) {
                rt.fail("消息不存在");
                return rt;
            }

            if (!"failed".equals(message.getStatus())) {
                rt.fail("只能重试失败状态的消息");
                return rt;
            }

            // 重置状态
            message.setStatus("sending");
            message.setRetryCount(message.getRetryCount() + 1);
            message.setUpdateTime(new Date());
            messageMapper.updateMessage(message);

            // 异步发送
            messageSendService.sendMessageAsync(messageID);

            rt.success("重试成功", message);
            return rt;

        } catch (Exception e) {
            logger.error("重试消息失败", e);
            rt.fail("重试消息失败：" + e.getMessage());
            return rt;
        }
    }

    // ================== 用户消息相关方法 ==================

    @Override
    public ResultDomain<MessageUserVO> getMyMessagesPage(MessageUserVO filter, PageParam pageParam) {
        ResultDomain<MessageUserVO> rt = new ResultDomain<>();
        try {
            if (filter == null) {
                filter = new MessageUserVO();
            }

            if (pageParam == null) {
                pageParam = new PageParam();
            }

            String currentUserID = getCurrentUserID();

            // 使用新的动态查询方法
            List<MessageUserVO> list = messageUserMapper.selectMyMessagesWithDynamicTargets(currentUserID, filter);

            PageDomain<MessageUserVO> pageDomain = new PageDomain<>();
            pageDomain.setDataList(list);
            pageParam.setTotalElements(list.size());
            pageParam.setTotalPages((int) Math.ceil((double) list.size() / pageParam.getPageSize()));
            pageDomain.setPageParam(pageParam);

            rt.success("查询成功", pageDomain);
            return rt;

        } catch (Exception e) {
            logger.error("查询我的消息失败", e);
            rt.fail("查询我的消息失败：" + e.getMessage());
            return rt;
        }
    }

    @Override
    public ResultDomain<MessageUserVO> getMyMessageDetail(String messageID) {
        ResultDomain<MessageUserVO> rt = new ResultDomain<>();
        try {
            String currentUserID = getCurrentUserID();
            MessageUserVO messageUserVO = messageUserMapper.selectOrCreateUserMessage(currentUserID, messageID);

            if (messageUserVO == null) {
                rt.fail("消息不存在");
                return rt;
            }

            // 如果用户消息记录不存在（id 为 null），创建新记录
            if (messageUserVO.getId() == null) {
                logger.info("用户首次查看消息，创建用户消息记录：userID={}, messageID={}", currentUserID, messageID);

                TbSysMessageUser userMessage = new TbSysMessageUser();
                userMessage.setID(IDUtils.generateID());
                userMessage.setMessageID(messageID);
                userMessage.setUserID(currentUserID);
                userMessage.setSendMethod("system"); // 默认发送方式
                userMessage.setIsRead(false); // 初始为未读
                userMessage.setSendStatus("success");
                userMessage.setCreator(currentUserID);
                userMessage.setCreateTime(new Date());
                userMessage.setUpdateTime(new Date());
                userMessage.setDeleted(false);

                // 插入新记录
                messageUserMapper.insertIfNotExists(userMessage);

                // 重新查询以获取完整信息
                messageUserVO = messageUserMapper.selectMyMessageDetail(currentUserID, messageID);
            }

            rt.success("查询成功", messageUserVO);
            return rt;

        } catch (Exception e) {
            logger.error("查询消息详情失败", e);
            rt.fail("查询消息详情失败：" + e.getMessage());
            return rt;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDomain<TbSysMessageUser> markAsRead(String messageID) {
        ResultDomain<TbSysMessageUser> rt = new ResultDomain<>();
        try {
            String currentUserID = getCurrentUserID();

            // 先尝试更新已有记录
            int result = messageUserMapper.markAsRead(currentUserID, messageID);

            // 如果没有更新任何记录，说明用户消息记录不存在，需要先插入
            if (result == 0) {
                logger.info("用户消息记录不存在，创建新记录：userID={}, messageID={}", currentUserID, messageID);

                TbSysMessageUser userMessage = new TbSysMessageUser();
                userMessage.setID(IDUtils.generateID());
                userMessage.setMessageID(messageID);
                userMessage.setUserID(currentUserID);
                userMessage.setSendMethod("system"); // 默认发送方式
                userMessage.setIsRead(true); // 直接设置为已读
                userMessage.setSendStatus("success");
                userMessage.setCreator(currentUserID);
                userMessage.setCreateTime(new Date());
                userMessage.setUpdateTime(new Date());
                userMessage.setDeleted(false);

                // 插入新记录
                int insertResult = messageUserMapper.insertIfNotExists(userMessage);

                if (insertResult > 0) {
                    // 插入成功后再次标记为已读（设置 read_time）
                    messageUserMapper.markAsRead(currentUserID, messageID);
                    result = 1;
                }
            }

            if (result > 0) {
                // 更新消息的已读数量
                messageMapper.incrementReadCount(messageID);
                TbSysMessageUser messageUser = new TbSysMessageUser();
                rt.success("标记成功", messageUser);
            } else {
                rt.fail("标记失败");
            }
            return rt;

        } catch (Exception e) {
            logger.error("标记已读失败", e);
            rt.fail("标记已读失败：" + e.getMessage());
            return rt;
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDomain<Integer> batchMarkAsRead(List<String> messageIDs) {
        ResultDomain<Integer> rt = new ResultDomain<>();
        try {
            String currentUserID = getCurrentUserID();
            int count = messageUserMapper.batchMarkAsRead(currentUserID, messageIDs);

            // 更新每条消息的已读数量
            for (String messageID : messageIDs) {
                messageMapper.incrementReadCount(messageID);
            }

            rt.success("批量标记成功", count);
            return rt;

        } catch (Exception e) {
            logger.error("批量标记已读失败", e);
            rt.fail("批量标记已读失败：" + e.getMessage());
            return rt;
        }
    }

    @Override
    public ResultDomain<Integer> getUnreadCount() {
        ResultDomain<Integer> rt = new ResultDomain<>();
        try {
            String currentUserID = getCurrentUserID();
            // 使用动态计算方法，统计用户应该看到的所有未读消息
            Integer count = messageUserMapper.countUnreadWithDynamicTargets(currentUserID);
            rt.success("查询成功", count != null ? count : 0);
            return rt;

        } catch (Exception e) {
            logger.error("查询未读数量失败", e);
            rt.fail("查询未读数量失败：" + e.getMessage());
            return rt;
        }
    }

    // ================== 辅助方法 ==================

    @Override
    public ResultDomain<Map<String, Object>> getTargetDepts() {
        ResultDomain<Map<String, Object>> rt = new ResultDomain<>();
        // TODO: 实现获取可选部门树
        rt.success("查询成功", new HashMap<>());
        return rt;
    }

    @Override
    public ResultDomain<Map<String, Object>> getTargetRoles() {
        ResultDomain<Map<String, Object>> rt = new ResultDomain<>();
        // TODO: 实现获取可选角色列表
        rt.success("查询成功", new HashMap<>());
        return rt;
    }

    @Override
    public ResultDomain<Map<String, Object>> getTargetUsers() {
        ResultDomain<Map<String, Object>> rt = new ResultDomain<>();
        // TODO: 实现获取可选用户列表
        rt.success("查询成功", new HashMap<>());
        return rt;
    }

    // ================== 私有辅助方法 ==================

    /**
     * 解析接收对象，生成用户消息列表
     */
    private List<TbSysMessageUser> resolveTargetUsers(String messageID, List<TbSysMessageTarget> targets, String creator) {
        Set<String> userIDSet = new HashSet<>();
        Map<String, String> userMethodMap = new HashMap<>();

        for (TbSysMessageTarget target : targets) {
            List<String> userIDs = new ArrayList<>();

            switch (target.getTargetType()) {
                case "dept":
                    // 查询该部门及所有子部门的用户
                    userIDs = userMapper.selectUserIdsByDeptId(target.getTargetID());
                    logger.info("部门 {} 解析到 {} 个用户", target.getTargetID(), userIDs.size());
                    break;
                case "role":
                    // 查询scopeDeptID及子部门中该角色的用户
                    String scopeDeptID = target.getScopeDeptID();
                    if (scopeDeptID == null || scopeDeptID.isEmpty()) {
                        logger.warn("角色目标缺少 scopeDeptID，跳过：{}", target.getTargetID());
                        break;
                    }
                    userIDs = userMapper.selectUserIdsByDeptRole(scopeDeptID, target.getTargetID());
                    logger.info("部门 {} 中角色 {} 解析到 {} 个用户", scopeDeptID, target.getTargetID(), userIDs.size());
                    break;
                case "user":
                    userIDs.add(target.getTargetID());
                    break;
            }

            for (String userID : userIDs) {
                userIDSet.add(userID);
                userMethodMap.put(userID, target.getSendMethod());
            }
        }

        // 生成用户消息列表
        List<TbSysMessageUser> userMessages = new ArrayList<>();
        for (String userID : userIDSet) {
            TbSysMessageUser userMessage = new TbSysMessageUser();
            userMessage.setID(IDUtils.generateID());
            userMessage.setMessageID(messageID);
            userMessage.setUserID(userID);
            userMessage.setSendMethod(userMethodMap.get(userID));
            userMessage.setIsRead(false);
            userMessage.setSendStatus("pending");
            userMessage.setCreator(creator);
            userMessage.setCreateTime(new Date());
            userMessage.setUpdateTime(new Date());
            userMessage.setDeleted(false);
            userMessages.add(userMessage);
        }

        logger.info("消息 {} 共解析到 {} 个目标用户", messageID, userMessages.size());
        return userMessages;
    }

    /**
     * 检查目标部门是否是当前部门或子部门
     */
    private boolean isCurrentOrSubDept(String currentDeptID, String targetDeptID) {
        // TODO: 实现部门层级检查
        return true;
    }

    /**
     * 获取当前用户ID
     */
    private String getCurrentUserID() {
        // TODO: 从SecurityContext或Session获取
        return "1";
    }

    /**
     * 获取当前用户部门ID
     */
    private String getCurrentUserDeptID() {
        // TODO: 从SecurityContext或Session获取
        return "root_department";
    }
}
