package com.wzj.soopin.im.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.wzj.soopin.content.service.VlogService;
import com.wzj.soopin.im.converter.SysMessageConvert;
import com.wzj.soopin.im.converter.SysMessageTemplateConvert;
import com.wzj.soopin.im.domain.SysMessage;
import com.wzj.soopin.im.domain.SysMessageTemplate;
import com.wzj.soopin.im.domain.SysMessageUser;
import com.wzj.soopin.im.domain.bo.SysMessageBo;
import com.wzj.soopin.im.domain.event.MessageEvent;
import com.wzj.soopin.im.domain.vo.SysMessageVo;
import com.wzj.soopin.im.mapper.SysMessageMapper;
import com.wzj.soopin.im.mapper.SysMessageUserMapper;
import com.wzj.soopin.im.service.ISysMessageService;
import com.wzj.soopin.im.service.ISysMessageTemplateService;
import com.wzj.soopin.member.service.IMemberService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import org.apache.commons.text.StringSubstitutor;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.PageQuery;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import com.wzj.soopin.im.enums.MessageActionEnum;
import org.dromara.system.domain.vo.SysUserVo;
import org.dromara.system.service.ISysTenantService;
import org.dromara.system.service.ISysUserService;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 消息Service业务层处理
 *
 * @author ruoyi
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class SysMessageServiceImpl extends ServiceImpl<SysMessageMapper, SysMessage> implements ISysMessageService {

    private final SysMessageMapper messageMapper;
    private final SysMessageUserMapper messageUserMapper;
    private final ApplicationEventPublisher eventPublisher;
    private final ISysUserService userService;
    private final ISysMessageTemplateService templateService;
    private final SysMessageConvert messageConvert;
    private final SysMessageTemplateConvert templateConvert;
    private final IMemberService memberService;
    private final ISysTenantService sysTenantService;
    private final VlogService vlogService;

    @Override
    public TableDataInfo<SysMessageVo> selectPageMessageList(SysMessageBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<SysMessage> lqw = new LambdaQueryWrapper<>();
        lqw.like(StringUtils.isNotBlank(bo.getTitle()), SysMessage::getTitle, bo.getTitle())
            .eq(StringUtils.isNotBlank(bo.getMsgType()), SysMessage::getMsgType, bo.getMsgType())
//            .eq(StringUtils.isNotBlank(bo.getStatus()), SysMessage::getStatus, bo.getStatus())
            .orderByDesc(SysMessage::getCreateTime);
        Page<SysMessage> page = messageMapper.selectPage(pageQuery.build(), lqw);
        List<SysMessageVo> records = MapstructUtils.convert(page.getRecords(), SysMessageVo.class);
        Page<SysMessageVo> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        voPage.setRecords(records);
        return TableDataInfo.build(voPage);
    }

    @Override
    public Page<SysMessageVo> selectUnreadMessagesPage(Long userId, Page<SysMessage> page) {
        LambdaQueryWrapper<SysMessage> lqw = new LambdaQueryWrapper<>();
        lqw.inSql(SysMessage::getId,
                "SELECT message_id FROM sys_message_user WHERE user_id = " + userId + " AND is_read = 0")
            .orderByDesc(SysMessage::getCreateTime);

        Page<SysMessage> messagePage = messageMapper.selectPage(page, lqw);
        Page<SysMessageVo> voPage = new Page<>(messagePage.getCurrent(), messagePage.getSize(), messagePage.getTotal());
        voPage.setRecords(MapstructUtils.convert(messagePage.getRecords(), SysMessageVo.class));
        return voPage;
    }

    @Override
    public Page<SysMessageVo> selectReadMessagesPage(Long userId, Page<SysMessage> page) {
        LambdaQueryWrapper<SysMessage> lqw = new LambdaQueryWrapper<>();
        lqw.inSql(SysMessage::getId,
                "SELECT message_id FROM sys_message_user WHERE user_id = " + userId + " AND is_read = 1")
            .orderByDesc(SysMessage::getCreateTime);

        Page<SysMessage> messagePage = messageMapper.selectPage(page, lqw);
        Page<SysMessageVo> voPage = new Page<>(messagePage.getCurrent(), messagePage.getSize(), messagePage.getTotal());
        voPage.setRecords(MapstructUtils.convert(messagePage.getRecords(), SysMessageVo.class));
        return voPage;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int sendMessageToUser(SysMessageBo message, Long userId) {
        // 新增：通过模板类型编号查找并渲染模板（轻量变量替换）
        if (StringUtils.isNotBlank(message.getTemplateType())) {
            SysMessageTemplate template = templateService.selectByTemplateType(message.getTemplateType());
            if (template == null) {
                throw new RuntimeException("消息模板不存在，templateType=" + message.getTemplateType());
            }
            Map<String, Object> params = message.getTemplateParams();
            String content = StringSubstitutor.replace(template.getContent(), params == null ? new java.util.HashMap<>() : params);
            message.setContent(content);
        }


        //加一个约定
        // 保存消息
        SysMessage entity = messageConvert.toPo(message);
        Date scheduledTime = entity.getScheduledTime();
        entity.setStatus("1"); // 已发送
        messageMapper.insert(entity);
        // 检查消息与用户关联是否已存在
        LambdaQueryWrapper<SysMessageUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysMessageUser::getMessageId, entity.getId())
            .eq(SysMessageUser::getUserId, userId);
        int count = Math.toIntExact(messageUserMapper.selectCount(queryWrapper));
        int rows = 0;
        if (count == 0) {
            SysMessageUser messageUser = new SysMessageUser();
            messageUser.setMessageId(entity.getId());
            messageUser.setUserId(userId);
            messageUser.setIsRead(false);
            rows = messageUserMapper.insert(messageUser);
        } else {
            log.info("消息与用户关联已存在，跳过创建: messageId={}, userId={}", entity.getId(), userId);
            rows = 1;
        }
        // 发送WebSocket消息
        if (rows > 0) {
            SysMessageVo messageVo = MapstructUtils.convert(entity, SysMessageVo.class);
            eventPublisher.publishEvent(new MessageEvent(this, messageVo, userId));
        }
        return rows;
//        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int sendMessageToUsers(SysMessage message, SysMessageTemplate template, List<String> userIds) {
        if (userIds == null || userIds.isEmpty()) {
            return 0;
        }
        // 保存消息
        Date scheduledTime = message.getScheduledTime();
//        if (scheduledTime != null && scheduledTime.after(new Date())) {
//            entity.setStatus("0"); // 未发送
//            messageMapper.insert(entity);
//            // 批量创建消息用户关联
//            int count = 0;
//            List<Long> validUserIds = new ArrayList<>();
//            Map<Long, String> userIdStrMap = new HashMap<>();
//            for (String userIdStr : userIds) {
//                if (StringUtils.isBlank(userIdStr)) {
//                    continue;
//                }
//                try {
//                    Long userId = Long.parseLong(userIdStr);
//                    validUserIds.add(userId);
//                    userIdStrMap.put(userId, userIdStr);
//                } catch (NumberFormatException e) {
//                    log.error("无法将String类型的用户ID转换为Long: {}", userIdStr);
//                }
//            }
//            if (!validUserIds.isEmpty()) {
//                LambdaQueryWrapper<SysMessageUser> queryWrapper = new LambdaQueryWrapper<>();
//                queryWrapper.eq(SysMessageUser::getMessageId, entity.getId())
//                    .in(SysMessageUser::getUserId, validUserIds);
//                List<SysMessageUser> existingRecords = messageUserMapper.selectList(queryWrapper);
//                Set<Long> existingUserIds = existingRecords.stream()
//                    .map(SysMessageUser::getUserId)
//                    .collect(Collectors.toSet());
//                log.info("已存在的消息关联记录数: {}", existingUserIds.size());
//                for (Long userId : validUserIds) {
//                    if (!existingUserIds.contains(userId)) {
//                        try {
//                            SysMessageUser messageUser = new SysMessageUser();
//                            messageUser.setMessageId(entity.getId());
//                            messageUser.setUserId(userId);
//                            messageUser.setIsRead(false);
//                            int rows = messageUserMapper.insert(messageUser);
//                            if (rows > 0) {
//                                count++;
//                            }
//                        } catch (Exception e) {
//                            log.error("创建消息用户关联失败: messageId={}, userId={}, error={}",
//                                entity.getId(), userId, e.getMessage());
//                        }
//                    } else {
//                        log.info("消息与用户关联已存在，跳过创建: messageId={}, userId={}", entity.getId(), userId);
//                        count++;
//                    }
//                }
//            }
//            // 定时消息不发布事件
//            return count;
//        } else {

        // 批量创建消息用户关联
        int count = 0;
        List<Long> validUserIds = new ArrayList<>();
        Map<Long, String> userIdStrMap = new HashMap<>();
        for (String userIdStr : userIds) {
            if (StringUtils.isBlank(userIdStr)) {
                continue;
            }
            try {
                Long userId = Long.parseLong(userIdStr);
                validUserIds.add(userId);
                userIdStrMap.put(userId, userIdStr);
            } catch (NumberFormatException e) {
                log.error("无法将String类型的用户ID转换为Long: {}", userIdStr);
            }
        }
        if (!validUserIds.isEmpty()) {
            LambdaQueryWrapper<SysMessageUser> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(SysMessageUser::getMessageId, message.getId())
                .in(SysMessageUser::getUserId, validUserIds);
            List<SysMessageUser> existingRecords = messageUserMapper.selectList(queryWrapper);
            Set<Long> existingUserIds = existingRecords.stream()
                .map(SysMessageUser::getUserId)
                .collect(Collectors.toSet());
            log.info("已存在的消息关联记录数: {}", existingUserIds.size());
            for (Long userId : validUserIds) {
                if (!existingUserIds.contains(userId)) {
                    try {
                        SysMessageUser messageUser = new SysMessageUser();
                        messageUser.setMessageId(message.getId());
                        messageUser.setUserId(userId);
                        messageUser.setIsRead(false);
                        int rows = messageUserMapper.insert(messageUser);
                        if (rows > 0) {
                            count++;
                        }
                    } catch (Exception e) {
                        log.error("创建消息用户关联失败: messageId={}, userId={}, error={}",
                            message.getId(), userId, e.getMessage());
                    }
                } else {
                    log.info("消息与用户关联已存在，跳过创建: messageId={}, userId={}", message.getId(), userId);
                    count++;
                }
            }
        }
        // 最后只发送一次批量事件通知
        if (count > 0) {

            SysMessageVo messageVo = MapstructUtils.convert(message, SysMessageVo.class);
            //获取模板信息，将模板的content作为参数传给消息
            messageVo.setTemplate(templateConvert.toVO(template));
            for (Long userId : validUserIds) {

                messageVo.setContent(buildContent(template.getContent(), messageVo.getParams()));
                messageVo.setExt(buildContent(template.getExt(), messageVo.getParams()));

                eventPublisher.publishEvent(new MessageEvent(this, messageVo, userId));
            }
        }
        return count;
//        }
    }

//    @Override
//    @Transactional(rollbackFor = Exception.class)
//    public int sendAutoMessage(SysMessageBo message, List<Long> userIds) {
//        message.setMsgType("AUTO");
//        return sendMessageToUsers(message, userIds.stream().map(String::valueOf).collect(Collectors.toList()));
//    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int markAsRead(Long messageId, Long userId) {
        LambdaQueryWrapper<SysMessageUser> lqw = new LambdaQueryWrapper<>();
        lqw.eq(SysMessageUser::getMessageId, messageId)
            .eq(SysMessageUser::getUserId, userId);
        SysMessageUser messageUser = new SysMessageUser();
        messageUser.setIsRead(true);
        return messageUserMapper.update(messageUser, lqw);
    }

    @Override
    public TableDataInfo<SysMessageVo> selectPageUnreadMessages(Long userId, PageQuery pageQuery) {
        Page<SysMessageVo> page = messageMapper.selectPageUnreadMessages(pageQuery.build(), userId);
        return TableDataInfo.build(page);
    }

    @Override
    public TableDataInfo<SysMessageVo> selectPageReadMessages(Long userId, PageQuery pageQuery) {
        LambdaQueryWrapper<SysMessage> lqw = new LambdaQueryWrapper<>();
//        lqw.eq(SysMessage::getStatus, "0")
//            .inSql(SysMessage::getId,
//                "SELECT message_id FROM sys_message_user WHERE user_id = " + userId + " AND is_read = 1")
//            .orderByDesc(SysMessage::getCreateTime);
//
        Page<SysMessage> page = new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize());
        Page<SysMessage> resultPage = messageMapper.selectPage(page, lqw);
        List<SysMessageVo> records = MapstructUtils.convert(resultPage.getRecords(), SysMessageVo.class);
        Page<SysMessageVo> voPage = new Page<>(resultPage.getCurrent(), resultPage.getSize(), resultPage.getTotal());
        voPage.setRecords(records);
        return TableDataInfo.build(voPage);
    }

    @Override
    public List<SysMessageVo> selectMessageList(SysMessageBo message) {
        LambdaQueryWrapper<SysMessage> lqw = new LambdaQueryWrapper<>();
        lqw.eq(StringUtils.isNotBlank(message.getMsgType()), SysMessage::getMsgType, message.getMsgType())
            .eq(StringUtils.isNotBlank(message.getSubType()), SysMessage::getSubType, message.getSubType())
            .orderByDesc(SysMessage::getCreateTime);
        return MapstructUtils.convert(messageMapper.selectList(lqw), SysMessageVo.class);
    }

    @Override
    public SysMessageVo selectMessageById(Long id) {
        return MapstructUtils.convert(messageMapper.selectById(id), SysMessageVo.class);
    }

    @Override
    public int insertMessage(SysMessageBo message) {
        return messageMapper.insert(messageConvert.toPo(message));
    }

    @Override
    public int updateMessage(SysMessageBo message) {
        return messageMapper.updateById(messageConvert.toPo(message));
    }

    @Override
    public int deleteMessageByIds(Long[] ids) {
        return messageMapper.deleteBatchIds(List.of(ids));
    }

    @Override
    public int deleteMessageById(Long id) {
        return messageMapper.deleteById(id);
    }

    @Override
    public LambdaQueryWrapper<SysMessage> toWrapper(SysMessageBo bo) {
        LambdaQueryWrapper<SysMessage> lqw = new LambdaQueryWrapper<>();
        lqw.like(StringUtils.isNotBlank(bo.getTitle()), SysMessage::getTitle, bo.getTitle())
            .eq(StringUtils.isNotBlank(bo.getMsgType()), SysMessage::getMsgType, bo.getMsgType())
            .orderByDesc(SysMessage::getCreateTime);
        return lqw;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int sendMessageToUserByStringId(SysMessageBo message, String userId) {
        if (StringUtils.isBlank(userId)) {
            return 0;
        }

        try {
            Long userIdLong = Long.parseLong(userId);
            return sendMessageToUser(message, userIdLong);
        } catch (NumberFormatException e) {
            log.error("无法将String类型的用户ID转换为Long: {}", userId);

            // 尝试以字符串形式发送
            // 保存消息
            SysMessage entity = messageConvert.toPo(message);
            messageMapper.insert(entity);

            // 发送事件通知
            SysMessageVo messageVo = MapstructUtils.convert(entity, SysMessageVo.class);
            eventPublisher.publishEvent(MessageEvent.createWithStringUserId(this, messageVo, userId));

            return 1;
        }
    }

    @Override
    public List<SysMessage> getScheduledMessagesToSend(java.util.Date now) {
        return this.lambdaQuery()
            .eq(SysMessage::getStatus, "0")
            .le(SysMessage::getScheduledTime, now)
            .list();
    }

    @Override
    public void updateMessageStatus(Long messageId, String status) {
        this.lambdaUpdate()
            .eq(SysMessage::getId, messageId)
            .set(SysMessage::getStatus, status)
            .update();
    }

    @Override
    public SysMessage selectEntityById(Long id) {
        return messageMapper.selectById(id);
    }

    @Override
    public boolean send(SysMessageBo bo) {
        SysMessageTemplate template = templateService.getById(bo.getTemplateId());
        if (template != null) {
            // 使用模板的标题和内容
            bo.setTemplate(template);
        } else {
            throw new ServiceException("未找到指定的消息模板");
        }

        // 验证发送范围是否为空
        Integer sendScope = bo.getSendScope();
        if (sendScope == null) {
            throw new ServiceException("发送范围不能为空");
        }

        // 处理接收者
        List<String> idList = new ArrayList<>();

        switch (sendScope) {
            case 1: // all
                idList = processAllIds(bo.getIdList());

                break;
            case 2: // 指定用户
                idList = processUserIds(bo.getIdList());
                break;
            case 3: // 指定会员
                idList = processMemberIds(bo.getIdList());
                break;
            case 4: // 指定租户
                idList = processTenantIds(bo.getIdList());
                break;
            default:
                throw new ServiceException("不支持的消息类型");
        }

        // 如果没有找到接收者，返回失败
        if (idList.isEmpty()) {
            throw new ServiceException("未找到消息接收者");
        }

        //构建发送者
        MessageActionEnum actionEnum = MessageActionEnum.getByCode(template.getAction());
        //根据用户名获取发送者
        bo.setSenderId(actionEnum.name());

        SysMessage message = messageConvert.toPo(bo);
        message.setStatus("1"); // 已发送
        message.setTitle(template.getTitle());
        message.setContent(template.getContent());
        message.setSendScope(sendScope);
        message.setTemplateId(template.getId());

        //构建content


        //获取模板信息
        messageMapper.insert(message);

        // 判断是否为定时消息，若是则注册SnailJob单次任务
        if (bo.getScheduledTime() != null && bo.getScheduledTime().after(new java.util.Date())) {

            registSnailJob(bo, idList);
        } else {
            //推送消息
            sendMessageToUsers(message, template, idList);
        }
        return true;
    }

    private String buildContent(String orgMsg, Map<String, Object> params) {
        for (String key : params.keySet()) {
            orgMsg = orgMsg.replaceAll("\\$\\{" + key + "\\}",  params.get(key).toString());
        }
        return orgMsg;
    }

    private List<String> processAllIds(List<Long> idList) {
        return null;
    }

    private List<String> processUserIds(List<Long> idList) {
        // 角色ID列表转换为用户ID列表
        return idList.stream().map(String::valueOf).toList();
    }

    private List<String> processMemberIds(List<Long> idList) {
        // 会员ID列表转换为用户ID列表
        return idList.stream().map(String::valueOf).toList();

    }

    private List<String> processTenantIds(List<Long> idList) {
        // 租户ID列表转换为用户ID列表

        List<SysUserVo> users = userService.selectUserByIds(idList, null);
        return users.stream().map(SysUserVo::getUserId).map(String::valueOf).toList();
    }

    private boolean registSnailJob(SysMessageBo bo, List<String> idList) {
        // 先保存消息，获取ID
        // 创建SnailJob单次任务
//         SnailJobApiUtil.createSingleJob(null, bo.getScheduledTime());
//        // 关联用户
//        for (String userId : idList) {
//            org.dromara.system.domain.SysMessageUser messageUser = new org.dromara.system.domain.SysMessageUser();
//            messageUser.setMessageId(bo.getId());
//            messageUser.setUserId(Long.valueOf(userId));
//            messageUser.setIsRead(false);
//            // 这里假设有messageUserMapper可用，实际应通过service或mapper注入
//            // messageUserMapper.insert(messageUser);
//        }
        return true;
    }


}
