package com.ylx.message.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ylx.common.core.domain.model.WxLoginUser;
import com.ylx.common.exception.ServiceException;
import com.ylx.common.utils.SecurityUtils;
import com.ylx.message.domain.MessageContent;
import com.ylx.message.domain.UserMessage;
import com.ylx.message.domain.dto.MessageDetailDTO;
import com.ylx.message.domain.vo.MessageCategoryVO;
import com.ylx.message.domain.vo.MessageDetailVO;
import com.ylx.message.mapper.MessageContentMapper;
import com.ylx.message.mapper.UserMessageMapper;
import com.ylx.message.service.IMessageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class MessageServiceImpl implements IMessageService {

    @Resource
    private MessageContentMapper messageContentMapper;
    @Resource
    private UserMessageMapper userMessageMapper;

    /** 消息未读状态 */
    private static final int READ_STATUS_UNREAD = 0;
    /** 消息已读状态 */
    private static final int READ_STATUS_READ = 1;
    /** 未删除状态 */
    private static final int NOT_DELETE = 0;

    /**
     * 🔴 获取用户未读消息数（小红点核心接口）
     * 联合索引 idx_user_read(user_id, is_read) 保证高效查询
     */
    public long getUnreadCount(Long userId) {
        return userMessageMapper.selectCount(
                new LambdaQueryWrapper<UserMessage>()
                        .eq(UserMessage::getUserId, userId)
                        .eq(UserMessage::getIsRead, READ_STATUS_UNREAD)
        );
    }

    /**
     * 发送消息（由订单、营销等业务模块调用）
     */
    @Transactional(rollbackFor = Exception.class)
    public void sendMessage(Long userId, String triggerEvent, Map<String, Object> variables) {
        // 1. 查找消息配置
        MessageContent config = messageContentMapper.selectOne(
                new LambdaQueryWrapper<MessageContent>()
                        .eq(MessageContent::getTriggerEvent, triggerEvent)
                        .eq(MessageContent::getIsDelete, NOT_DELETE)
        );
        if (ObjectUtil.isNull(config)) {
            log.warn("未找到触发事件[{}]对应的消息配置", triggerEvent);
            return;
        }

        // 2. 渲染个性化内容
        String content = renderTemplate(config.getContentTemplate(), variables);
        String jumpPage = renderTemplate(config.getJumpPage(), variables);

        // 3. 生成用户消息（默认未读，触发小红点）
        UserMessage userMsg = new UserMessage();
        userMsg.setUserId(userId);
        userMsg.setMessageContentId(config.getId());
        userMsg.setIsRead(READ_STATUS_UNREAD);
        userMsg.setTitle(config.getTitle());
        userMsg.setPersonalizedContent(content);
        userMsg.setPersonalizedJumpPage(jumpPage);
        userMessageMapper.insert(userMsg);
    }

    /**
     * 标记单条消息已读（点击消息时调用，消除对应小红点）
     */
    public void markAsRead(Long messageId) {

        // 获取当前登录用户
        WxLoginUser wxLoginUser = getCurrentWxLoginUser();

        Long userId = Long.parseLong(wxLoginUser.getId());

        userMessageMapper.update(null,
                new LambdaUpdateWrapper<UserMessage>()
                        .eq(UserMessage::getId, messageId)
                        .eq(UserMessage::getUserId, userId) // 🔒 安全校验，防止越权操作他人消息
                        .eq(UserMessage::getIsRead, READ_STATUS_UNREAD)       // 仅更新未读记录，避免重复更新
                        .eq(UserMessage::getIsDelete, NOT_DELETE)
                        .set(UserMessage::getIsRead, READ_STATUS_READ)
        );
    }

    @Override
    public List<MessageCategoryVO> getCategoryCards() {

        // 获取当前登录用户
        WxLoginUser wxLoginUser = getCurrentWxLoginUser();

        Long userId = Long.parseLong(wxLoginUser.getId());
        return userMessageMapper.selectLatestByCategory(userId);
    }

    @Override
    public Page<MessageDetailVO> getCategoryMessages(MessageDetailDTO dto) {

        // 获取当前登录用户
        WxLoginUser wxLoginUser = getCurrentWxLoginUser();

        Long userId = Long.parseLong(wxLoginUser.getId());

        Page<MessageDetailVO> page = new Page<>(dto.getCurrent(), dto.getSize());
        dto.setUserId(userId);
        return this.userMessageMapper.selectMessageListByCategory(page, dto);
    }

    /**
     * 模板变量替换
     */
    private String renderTemplate(String template, Map<String, Object> vars) {
        if (StrUtil.isBlank(template) || vars == null || vars.isEmpty()) {
            return template;
        }

        String result = template;
        for (Map.Entry<String, Object> entry : vars.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            // 安全转换为字符串：null → "", 非字符串对象调用 toString()
            String strValue = value == null ? "" : String.valueOf(value);
            result = result.replace("{" + key + "}", strValue);
        }
        return result;
    }

    private WxLoginUser getCurrentWxLoginUser() {
        WxLoginUser loginUser = SecurityUtils.getWxLoginUser();
        if (ObjectUtil.isNull(loginUser)) {
            throw new ServiceException("用户未登录或登录已过期");
        }
        return loginUser;
    }
}
