package com.tangguo.service.impl;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tangguo.common.constant.ActiveMQConstant;
import com.tangguo.common.domain.OperateDetail;
import com.tangguo.common.domain.PointsDetail;
import com.tangguo.common.exception.ServiceException;
import com.tangguo.domain.BbsPointsSetting;
import com.tangguo.enums.PointsSettingType;
import com.tangguo.mapper.BbsPointsSettingMapper;
import com.tangguo.service.IBbsPointsSettingService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 积分规则配置Service业务层处理
 *
 * @author ruoyi
 * @date 2025-08-29
 */
@Slf4j
@Service
public class BbsPointsSettingServiceImpl extends ServiceImpl<BbsPointsSettingMapper, BbsPointsSetting> implements IBbsPointsSettingService {

    private static final Map<String, BbsPointsSetting> POINTS_SETTING = new HashMap<>(5);

    @Resource
    private BbsPointsSettingMapper bbsPointsSettingMapper;

    @Resource
    private JmsTemplate jmsTemplate;


    /**
     * 初始化积分规则配置缓存
     */
    @PostConstruct
    public void initCachePointsSetting() {
        POINTS_SETTING.clear();
        List<BbsPointsSetting> dbSettings = this.getEnableSettings();
        for (BbsPointsSetting setting : dbSettings) {
            POINTS_SETTING.put(setting.getOperateCode(), setting);
        }
        log.info("=> 初始化积分规则配置缓存完毕，缓存配置数量：{}", POINTS_SETTING.size());
    }


    /**
     * 查询积分规则配置列表
     *
     * @param bbsPointsSetting 积分规则配置
     * @return 积分规则配置
     */
    @Override
    public List<BbsPointsSetting> selectBbsPointsSettingList(BbsPointsSetting bbsPointsSetting) {
	    return this.list();
    }


    /**
     * 查询积分规则配置明细
     *
     * @return 配置明细
     */
    @Override
    public Map<String, List<BbsPointsSetting>> getSettingDetails() {
        List<BbsPointsSetting> settings = this.list();

        List<BbsPointsSetting> addSetting = settings.stream()
            .filter(s -> PointsSettingType.ADD.name().equals(s.getType())).collect(Collectors.toList());
        List<BbsPointsSetting> decSetting = settings.stream()
            .filter(s -> PointsSettingType.DEC.name().equals(s.getType())).collect(Collectors.toList());

        Map<String, List<BbsPointsSetting>> settingMap = new LinkedHashMap<>(2);
        settingMap.put(PointsSettingType.ADD.name(), addSetting);
        settingMap.put(PointsSettingType.DEC.name(), decSetting);
        return settingMap;
    }


    /**
     * 查询积分规则配置
     *
     * @return 规则配置
     */
    @Override
    public List<BbsPointsSetting> getEnableSettings() {
        return this.list(
            Wrappers.lambdaQuery(BbsPointsSetting.class).eq(BbsPointsSetting::getEnableStatus, 1)
        );
    }


    /**
     * 添加积分配置
     *
     * @param setting 积分配置
     */
    @Override
    public void addSetting(BbsPointsSetting setting) {
        long nameCount = this.count(
            Wrappers.lambdaQuery(BbsPointsSetting.class).eq(BbsPointsSetting::getOperateName, setting.getOperateName())
        );
        if (nameCount > 0) {
            throw new ServiceException("新增失败，操作行为名称重复。");
        }

        BbsPointsSetting addSetting = new BbsPointsSetting();
        addSetting.setType(setting.getType());
        addSetting.setAgentName(setting.getAgentName());
        addSetting.setOperateName(setting.getOperateName());
        addSetting.setOperateCode(IdUtil.fastSimpleUUID());
        addSetting.setOperatePoints(setting.getOperatePoints());
        addSetting.setLimitCount(setting.getLimitCount());
        addSetting.setEnableStatus(setting.getEnableStatus());
        this.save(addSetting);
        this.initCachePointsSetting();
    }


    /**
     * 修改积分配置
     *
     * @param setting 积分配置
     */
    @Override
    public void editSetting(BbsPointsSetting setting) {
        BbsPointsSetting dbSetting = this.getById(setting.getId());
        if (Objects.isNull(dbSetting)) {
            throw new ServiceException("修改失败，未查询到当前积分配置数据。");
        }

        if (!dbSetting.getOperateName().equals(setting.getOperateName())) {
            long nameCount = this.count(
                 Wrappers.lambdaQuery(BbsPointsSetting.class).eq(BbsPointsSetting::getOperateName, setting.getOperateName())
            );
            if (nameCount > 0) {
                throw new ServiceException("修改失败，操作行为名称重复。");
            }
        }

        BbsPointsSetting updSetting = new BbsPointsSetting();
        updSetting.setId(dbSetting.getId());
        updSetting.setOperateName(setting.getOperateName());
        updSetting.setOperatePoints(setting.getOperatePoints());
        updSetting.setLimitCount(setting.getLimitCount());
        updSetting.setEnableStatus(setting.getEnableStatus());
        this.updateById(updSetting);
        this.initCachePointsSetting();
    }


    /**
     * 修改积分配置
     *
     * @param settings 积分配置
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void batchEditSetting(List<BbsPointsSetting> settings) {
         List<BbsPointsSetting> updSettings = new ArrayList<>(settings.size());
        for (BbsPointsSetting setting : settings) {
            BbsPointsSetting updSetting = new BbsPointsSetting();
            updSetting.setId(setting.getId());
            updSetting.setOperatePoints(setting.getOperatePoints());
            updSetting.setLimitCount(setting.getLimitCount());
            updSetting.setEnableStatus(setting.getEnableStatus());
            updSettings.add(updSetting);
        }
        this.updateBatchById(updSettings);
        this.initCachePointsSetting();
    }


    /**
     * 删除积分配置
     *
     * @param settingId 配置Id
     */
    @Override
    public void deleteSetting(Long settingId) {
        this.removeById(settingId);
        this.initCachePointsSetting();
    }


    /**
     * 修改配置状态
     *
     * @param setting 积分配置
     */
    @Override
    public void setSettingStatus(BbsPointsSetting setting) {
        BbsPointsSetting dbSetting = this.getById(setting.getId());
        if (Objects.isNull(dbSetting)) {
            throw new ServiceException("修改失败，未查询到当前积分配置数据。");
        }

        if (!dbSetting.getEnableStatus().equals(setting.getEnableStatus())) {
            BbsPointsSetting updSetting = new BbsPointsSetting();
            updSetting.setId(dbSetting.getId());
            updSetting.setEnableStatus(setting.getEnableStatus());
            this.updateById(updSetting);
        }
    }


    /**
     * 处理用户操作积分
     *
     * @param detail 操作明细
     */
    @Override
    public void handleOperatePoints(OperateDetail detail) {
        log.info("=> 处理用户操作积分：{}", detail);
        BbsPointsSetting cacheSetting = POINTS_SETTING.get(detail.getOperateCode());
        if (Objects.isNull(cacheSetting)) {
            throw new ServiceException("处理失败，未查询到操作编码对应的积分配置。");
        }

        String userName = detail.getUserName();
        String operateCode = cacheSetting.getOperateCode();
        int pointsCount = this.baseMapper.selectPointsCount(userName, operateCode, 7);
        if (pointsCount >= cacheSetting.getLimitCount()) {
            return;
        }

        // 匹配积分队列
        String pointsQueue;
        PointsSettingType settingType = PointsSettingType.getSettingType(cacheSetting.getType());
        if (PointsSettingType.ADD == settingType) {
            pointsQueue = ActiveMQConstant.Points.INCR_USER_POINTS_QUEUE;
        } else if (PointsSettingType.DEC == settingType) {
            pointsQueue = ActiveMQConstant.Points.DECR_USER_POINTS_QUEUE;
        } else {
            throw new ServiceException("处理失败，当前积分规则的设置类型错误。");
        }

        // 积分消息明细
        String operateName = cacheSetting.getOperateName();
        Integer points = cacheSetting.getOperatePoints();
        PointsDetail pointsDetail = new PointsDetail();
        pointsDetail.setLinkTracId(detail.getLinkTracId());
        pointsDetail.setUserName(userName);
        pointsDetail.setDetailPoints(points);
        pointsDetail.setDetailName(operateName);
        pointsDetail.setDetailCode(operateCode);
        pointsDetail.setDescription(String.format("用户【%s】操作【%s】积分【%s】", userName, operateName, points));

        // 发送积分消息
        this.jmsTemplate.convertAndSend(pointsQueue, pointsDetail);
    }

}
