package com.fs.patient.service.impl;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.fs.common.core.domain.R;
import com.fs.common.core.redis.RedisCache;
import com.fs.common.exception.CustomException;
import com.fs.common.utils.DateUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fs.company.domain.CompanyUser;
import com.fs.company.mapper.CompanyUserMapper;
import com.fs.core.config.WxMaConfiguration;
import com.fs.course.domain.FsCourseTrafficLog;
import com.fs.course.domain.FsVideoResource;
import com.fs.course.mapper.FsCourseTrafficLogMapper;
import com.fs.course.mapper.FsVideoResourceMapper;
import com.fs.his.domain.*;
import com.fs.his.mapper.FsProjectCateMapper;
import com.fs.his.mapper.FsProjectRedDetailMapper;
import com.fs.his.mapper.FsUserMapper;
import com.fs.his.param.FsPatientBaseInfoListDParam;
import com.fs.his.param.ProjectRedParam;
import com.fs.his.param.WxSendRedPacketParam;
import com.fs.his.service.IFsDoctorService;
import com.fs.his.service.IFsProjectService;
import com.fs.his.service.IFsStorePaymentService;
import com.fs.his.service.IFsUserWxService;
import com.fs.his.vo.FsPatientBaseInfoListDVO;
import com.fs.patient.domain.FsProjectRedPacketRecord;
import com.fs.patient.mapper.FsProjectRedPacketRecordMapper;
import com.fs.patient.param.BindPatientParam;
import com.fs.patient.param.FsProjectSendRewardUParam;
import com.fs.patient.param.FsProjectVideoFinishUParam;
import com.fs.patient.vo.PatientBaseInfoVO;
import com.fs.qw.mapper.QwExternalContactMapper;
import com.fs.system.oss.CloudStorageService;
import com.fs.system.oss.OSSFactory;
import com.fs.system.service.ISysConfigService;
import com.github.binarywang.wxpay.bean.transfer.TransferBillsResult;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.fs.patient.mapper.FsPatientBaseInfoMapper;
import com.fs.patient.domain.FsPatientBaseInfo;
import com.fs.patient.service.IFsPatientBaseInfoService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

/**
 * 患者基本信息Service业务层处理
 * 
 * @author fs
 * @date 2026-04-19
 */
@Slf4j
@Service
public class FsPatientBaseInfoServiceImpl extends ServiceImpl<FsPatientBaseInfoMapper, FsPatientBaseInfo> implements IFsPatientBaseInfoService {

    protected final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private FsProjectRedDetailMapper projectRedDetailMapper;
    @Autowired
    private CompanyUserMapper companyUserMapper;

    @Autowired
    private IFsDoctorService doctorService;


    @Autowired
    private FsPatientBaseInfoMapper fsPatientBaseInfoMapper;

    @Autowired
    private IFsProjectService projectService;

    @Autowired
    private FsProjectRedPacketRecordMapper projectRedPacketRecordMapper;

    @Autowired
    private FsUserMapper userMapper;

    @Autowired
    private ISysConfigService configService;

    @Autowired
    private IFsUserWxService fsUserWxService;

    @Autowired
    private IFsStorePaymentService fsStorePaymentService;

    @Autowired
    private QwExternalContactMapper qwExternalContactMapper;

    @Autowired
    private FsVideoResourceMapper fsVideoResourceMapper;

    @Autowired
    private FsCourseTrafficLogMapper fsCourseTrafficLogMapper;

    @Autowired
    private FsProjectCateMapper fsProjectCateMapper;
    /**
     * 查询患者基本信息
     * 
     * @param id 患者基本信息主键
     * @return 患者基本信息
     */
    @Override
    public FsPatientBaseInfo selectFsPatientBaseInfoById(Long id)
    {
        return baseMapper.selectFsPatientBaseInfoById(id);
    }

    /**
     * 查询患者基本信息列表
     * 
     * @param fsPatientBaseInfo 患者基本信息
     * @return 患者基本信息
     */
    @Override
    public List<FsPatientBaseInfo> selectFsPatientBaseInfoList(FsPatientBaseInfo fsPatientBaseInfo)
    {
        return baseMapper.selectFsPatientBaseInfoList(fsPatientBaseInfo);
    }

    /**
     * 新增患者基本信息
     * 
     * @param fsPatientBaseInfo 患者基本信息
     * @return 结果
     */
    @Override
    public int insertFsPatientBaseInfo(FsPatientBaseInfo fsPatientBaseInfo)
    {
        fsPatientBaseInfo.setCreateTime(DateUtils.getNowDate());
        fsPatientBaseInfo.setDoctorStatus(0);
        fsPatientBaseInfo.setStatus(0);
        CompanyUser companyUser = companyUserMapper.selectCompanyUserById(fsPatientBaseInfo.getCompanyUserId());
        if (companyUser != null) {
            if (companyUser.getDoctorId() != null) {
                fsPatientBaseInfo.setDoctorId(companyUser.getDoctorId());
            } else {
                Long doctorId = doctorService.selectFsDoctorDoctorByPackage();
                fsPatientBaseInfo.setDoctorId(doctorId);
            }
        } else {
            throw new CustomException("销售信息错误！");
        }
        return baseMapper.insertFsPatientBaseInfo(fsPatientBaseInfo);
    }

    /**
     * 修改患者基本信息
     * 
     * @param fsPatientBaseInfo 患者基本信息
     * @return 结果
     */
    @Override
    public int updateFsPatientBaseInfo(FsPatientBaseInfo fsPatientBaseInfo)
    {
        fsPatientBaseInfo.setUpdateTime(DateUtils.getNowDate());
        return baseMapper.updateFsPatientBaseInfo(fsPatientBaseInfo);
    }

    /**
     * 批量删除患者基本信息
     * 
     * @param ids 需要删除的患者基本信息主键
     * @return 结果
     */
    @Override
    public int deleteFsPatientBaseInfoByIds(Long[] ids)
    {
        return baseMapper.deleteFsPatientBaseInfoByIds(ids);
    }

    /**
     * 删除患者基本信息信息
     * 
     * @param id 患者基本信息主键
     * @return 结果
     */
    @Override
    public int deleteFsPatientBaseInfoById(Long id)
    {
        return baseMapper.deleteFsPatientBaseInfoById(id);
    }

//    @Override
//    public R getWxaCodePatientBaseInfoUnLimit(Long patientId,String appId) {
//        log.info("生成用患者信息二维码，请求参数：{}，{}",patientId,appId);
//
//        final WxMaService wxMaService = WxMaConfiguration.getMaService(appId);
//        String scene="patientId="+ patientId ;
//        byte[] file;
//        try {
//            file = wxMaService.getQrcodeService().createWxaCodeUnlimitBytes(
//                    scene,
//                    "pages_user/healthRegimen",
//                    true,
//                    "release",//release trial
//                    430,
//                    true,
//                    null,
//                    false);
//
//            // 上传图片到存储桶
//            String suffix = ".png";
//            CloudStorageService storage = OSSFactory.build();
//            String url;
//            try {
//                url = storage.uploadSuffix(file, suffix);
//            }  catch (Exception e) {
//                // 记录错误日志
//                log.error("生成图片失败:{}",e.getMessage(),e);
//                return R.error("生成图片失败");
//            }
//            // 返回成功信息
//            return R.ok().put("url",url);
//
//        } catch (WxErrorException e) {
//            log.error(e.getMessage(), e);
//            return R.error("微信接口调用失败: " + e.getMessage());
//        }
//    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R getWxaCodePatientBaseInfoUnLimit(Long patientId,String appId) {
        log.info("生成用患者信息二维码，请求参数：{}，{}",patientId,appId);
        String baseInfoKey = null;
        FsPatientBaseInfo baseInfo = fsPatientBaseInfoMapper.selectFsPatientBaseInfoById(patientId);
        if (baseInfo == null) {
            return R.error("未找到患者基础信息");
        }

        if (baseInfo.getUserId() == null) {
            baseInfoKey = IdUtil.getSnowflake(0,0).nextIdStr();
            FsProjectRedDetail detail = new FsProjectRedDetail();
            detail.setProjectId(baseInfo.getProjectId());
            detail.setCompanyUserId(baseInfo.getCompanyUserId());
            detail.setCreateTime(new Date());
            detail.setSendTime(new Date());
            detail.setSource("小程序");
            detail.setStatus(0);
            //存入缓存
            redisCache.setCacheObject(baseInfoKey,detail,24, TimeUnit.HOURS);
        } else {
            ProjectRedParam param = new ProjectRedParam();
            param.setProjectId(baseInfo.getProjectId());
            param.setCompanyUserId(baseInfo.getCompanyUserId());
            param.setUserId(baseInfo.getUserId());
            FsProjectRedDetail detail = projectRedDetailMapper.selectFsProjectRedDetailDataByCompanyUserIdAndProjectId(param);
            if (detail == null) {
                detail = new FsProjectRedDetail();
                detail.setProjectId(baseInfo.getProjectId());
                detail.setCompanyUserId(baseInfo.getCompanyUserId());
                detail.setUserId(baseInfo.getUserId());
                detail.setSendTime(new Date());
                detail.setCreateTime(new Date());
                detail.setSource("小程序");
                detail.setStatus(0);
                projectRedDetailMapper.insertFsProjectRedDetail(detail);
            }
        }

        final WxMaService wxMaService = WxMaConfiguration.getMaService(appId);
        String scene=patientId + "&" +baseInfoKey;
        byte[] file;
        try {
            file = wxMaService.getQrcodeService().createWxaCodeUnlimitBytes(
                    scene,
                    "pages_user/healthRegimen",
                    true,
                    "release",//release trial
                    430,
                    true,
                    null,
                    false);

            // 上传图片到存储桶
            String suffix = ".png";
            CloudStorageService storage = OSSFactory.build();
            String url;
            try {
                url = storage.uploadSuffix(file, suffix);
            }  catch (Exception e) {
                // 记录错误日志
                log.error("生成图片失败:{}",e.getMessage(),e);
                return R.error("生成图片失败");
            }
            // 返回成功信息
            return R.ok().put("url",url);

        } catch (WxErrorException e) {
            log.error(e.getMessage(), e);
            return R.error("微信接口调用失败: " + e.getMessage());
        }
    }

    @Override
    public R getPatientBaseInfoDetail(Long patientId,Long userId) {
        //扫码的患者信息
        FsPatientBaseInfo info = fsPatientBaseInfoMapper.selectFsPatientBaseInfoById(patientId);
        if (info == null) {
            return R.error("患者信息错误");
        }
        FsDoctor doctor = null;
        Long projectId = info.getProjectId();

        PatientBaseInfoVO patientBaseInfoVO = new PatientBaseInfoVO();


        //自己的患者信息
        FsPatientBaseInfo selectedByUserId = fsPatientBaseInfoMapper.selectByUserId(userId);

        if (selectedByUserId != null) {
            BeanUtils.copyProperties(selectedByUserId, patientBaseInfoVO);
            //医生信息
            doctor = doctorService.selectFsDoctorByDoctorId(selectedByUserId.getDoctorId());
        } else {
            BeanUtils.copyProperties(info, patientBaseInfoVO);
            //医生信息
            doctor = doctorService.selectFsDoctorByDoctorId(info.getDoctorId());
        }
        if (doctor != null) {
            patientBaseInfoVO.setDoctorName(doctor.getDoctorName());
            patientBaseInfoVO.setDoctorNo(doctor.getCertificateCode());
        }
        //理疗项目信息 始终取分享的理疗数据
        FsProject fsProject = projectService.selectFsProjectById(projectId);
        if (fsProject != null) {
            patientBaseInfoVO.setProject(fsProject);
            FsVideoResource resource = fsVideoResourceMapper.selectVideoByVideoUrl(fsProject.getVideoUrl());
            if (resource != null) {
                patientBaseInfoVO.setDuration(resource.getDuration());
            }
            FsProjectCate fsProjectCate = fsProjectCateMapper.selectFsProjectCateById(fsProject.getCateId());
            patientBaseInfoVO.setCate(fsProjectCate);
        }

        //红包配置信息
        BigDecimal amount = new BigDecimal("0.1");
        boolean openFlag = false;
        Long redSecond = 0L;
        Integer type = 1;
        String json = getProjectRedPacketConfig();
        if(StringUtils.isNotEmpty(json)) {
            try {
                JSONObject jsonObject = JSON.parseObject(json);
                String open = jsonObject.getString("open");
                if ("1".equals(open)) {
                    openFlag = true;
                }
                amount = jsonObject.getBigDecimal("amount");
                redSecond = jsonObject.getLong("redSecond");
                type = jsonObject.getInteger("type");
            } catch (Exception e) {
                log.error("解析理疗红包配置失败, json={}", json, e);
                amount = new BigDecimal("0.1");
                redSecond = 0L;
                type = 1;
            }
        }
        patientBaseInfoVO.setAmount(amount);
        patientBaseInfoVO.setOpenFlag(openFlag);
        patientBaseInfoVO.setRedSecond(redSecond);
        patientBaseInfoVO.setType(type);
        return R.ok().put("data", patientBaseInfoVO);
    }

    @Override
    public R patientBindUser(BindPatientParam param) {

        if (param.getCompanyUserId() != null) {
            return R.error("销售不能绑定");
        }
        FsPatientBaseInfo selectByUserId = fsPatientBaseInfoMapper.selectByUserId(param.getUserId());
        if (selectByUserId != null) {
            return R.error("已绑定过患者信息，无需绑定");
        }
        FsPatientBaseInfo info = fsPatientBaseInfoMapper.selectFsPatientBaseInfoById(param.getPatientId());
        if (info == null) {
            return R.error("患者信息错误，绑定失败");
        }
        if (info.getStatus() == 1) {
            return R.error("患者信息已绑定，绑定失败");
        }
        FsPatientBaseInfo map    = new FsPatientBaseInfo();
        map.setId(info.getId());
        map.setUserId(param.getUserId());
        map.setStatus(1);
        int i = fsPatientBaseInfoMapper.updateFsPatientBaseInfo(map);
        if (i > 0) {
            return R.ok();
        }
        return R.error();
    }

    @Override
    public List<FsPatientBaseInfoListDVO> selectFsPatientBaseInfoListDVO(FsPatientBaseInfoListDParam param) {
        return fsPatientBaseInfoMapper.selectFsPatientBaseInfoListDVO(param);
    }

    @Override
    public R diagnose(FsPatientBaseInfo param) {
        FsPatientBaseInfo info = fsPatientBaseInfoMapper.selectFsPatientBaseInfoById(param.getId());
        if (info == null) {
            return R.error("患者信息错误，诊断失败");
        }
        FsPatientBaseInfo map = new FsPatientBaseInfo();
        map.setId(info.getId());
        map.setDoctorStatus(1);
        map.setName(param.getName());
        map.setAge(param.getAge());
        map.setSex(param.getSex());
        map.setDiagnosisTime(new Date());
        map.setDiagnosisResult(param.getDiagnosisResult());
        map.setTreatmentTarget(param.getTreatmentTarget());
        map.setCheckStatus(0);
        int i = fsPatientBaseInfoMapper.updateFsPatientBaseInfo(map);
        if (i > 0) {
            return R.ok();
        }
        return R.error("诊断失败");
    }

    @Override
    public R sendProjectReward(FsProjectSendRewardUParam param) {
        FsPatientBaseInfo fsPatientBaseInfo = fsPatientBaseInfoMapper.selectFsPatientBaseInfoById(param.getPatientId());
        if (fsPatientBaseInfo == null) {
            return R.error("患者信息错误，领取失败");
        }
        CompanyUser companyUser = companyUserMapper.selectCompanyUserByCompanyUserId(fsPatientBaseInfo.getCompanyUserId());
        if (companyUser == null) {
            return R.error("销售信息错误，领取失败");
        }
        FsProject fsProject = projectService.selectFsProjectById(param.getProjectId());
        if (fsProject == null) {
            return R.error("理疗信息错误，领取失败");
        }

        // 获取用户信息
        FsUser user = userMapper.selectFsUserByUserId(param.getUserId());
        if (user == null) {
            return R.error("用户信息缺失，无法领取");
        }
        if (user.getStatus() == 0){
            return R.error("会员被停用，无权限，请联系客服！");
        }
        //当前用户是否添加企微
        Long qwCount = qwExternalContactMapper.selectCountByUnionId(user.getUnionId());
        if (qwCount < 1) {
            return R.error("请添加企微后领取");
        }
        //获取今日理疗红包记录
        FsProjectRedPacketRecord redPacketRecord = projectRedPacketRecordMapper.selectTodayFsProjectRedPacketRecordByUserId(param.getUserId());
        if (!ObjectUtils.isEmpty(redPacketRecord)) {
            if (redPacketRecord.getCollectType() == 1) {
                return R.error("今日已领取过红包！");
            }
            if (redPacketRecord.getCollectType() == 0) {
                if (!Objects.equals(param.getProjectId(), redPacketRecord.getProjectId())) {
                    return R.error("当日只能领取一次理疗红包！");
                }
            }
        }

        FsProjectRedPacketRecord record = projectRedPacketRecordMapper.selectFsProjectRedPacketByUserIdAndProjectId(param.getUserId(), param.getProjectId());
        if (record != null && record.getCollectType() == 1) {
            return R.error("已领取过该理疗红包，不可重复领取");
        }
        if (record != null && record.getCollectType() == 0 && StringUtils.isNotEmpty(record.getResult())) {
            try {
                //返回已有生成的红包数据
                return JSON.parseObject(record.getResult(), R.class);
            } catch (Exception e) {
                log.error("理疗红包=====》转换已有红包数据失败：{}",e.getMessage());
                return R.error("操作频繁，请稍后再试！");
            }
        }
        //发送红包
        return sendProjectRedPacket(param,user,companyUser);
    }

    @Override
    public int reject(FsPatientBaseInfo param) {
        FsPatientBaseInfo map = new FsPatientBaseInfo();
        map.setId(param.getId());
        map.setDoctorStatus(0);
        return fsPatientBaseInfoMapper.updateFsPatientBaseInfo(map);
    }

    @Override
    public int check(FsPatientBaseInfo param) {
        if (param.getId() == null || param.getId() <= 0) {
            throw new CustomException("参数错误");
        }
        FsPatientBaseInfo fsPatientBaseInfo = fsPatientBaseInfoMapper.selectFsPatientBaseInfoById(param.getId());
        if (fsPatientBaseInfo == null) {
            throw new CustomException("未找到患者基础信息");
        }
        FsPatientBaseInfo map = new FsPatientBaseInfo();
        map.setId(param.getId());
        map.setCheckStatus(param.getCheckStatus());
        map.setCheckTime(new Date());
        map.setReason(param.getReason());
        return fsPatientBaseInfoMapper.updateFsPatientBaseInfo(map);
    }

    @Override
    public R getInternetTraffic(FsProjectVideoFinishUParam param) {
        try {
            if (param.getBufferRate()==null){
                logger.error("【缓冲值空】参数: {}",param);
                return R.error("缓冲值空");
            }
            FsCourseTrafficLog trafficLog = new FsCourseTrafficLog();
            trafficLog.setCreateTime(new Date());
            BeanUtils.copyProperties(param, trafficLog);
            FsVideoResource resource = fsVideoResourceMapper.selectVideoByVideoUrl(param.getVideoUrl());
            if (resource == null) {
                return R.error("视频源不存在");
            }
            // 计算流量
            BigDecimal result = param.getBufferRate().divide(new BigDecimal("100"), 4, RoundingMode.HALF_UP);
            BigDecimal longAsBigDecimal = BigDecimal.valueOf(resource.getFileSize());
            long roundedResult = result.multiply(longAsBigDecimal).setScale(0, RoundingMode.HALF_UP).longValue();
            trafficLog.setInternetTraffic( Math.round(roundedResult * 1.4));

            // 处理 UUID 为空的情况
            if (StringUtils.isNotEmpty(trafficLog.getUuId())) {
                // 插入或更新
                fsCourseTrafficLogMapper.insertOrUpdateTrafficLog(trafficLog);
            }
        } catch (Exception e) {
            e.printStackTrace();
            // 打印参数param和异常信息
            logger.error("【插入或更新流量失败】参数: {}, 错误信息：{}", param, e.getMessage(), e);
            return R.error();
        }
        return R.ok();
    }


    private R sendProjectRedPacket(FsProjectSendRewardUParam param,FsUser user,CompanyUser companyUser){
        //默认0.1红包数据
        BigDecimal amount;
        String json = getProjectRedPacketConfig();
        if(StringUtils.isNotEmpty(json)) {
            try {
                JSONObject jsonObject = JSON.parseObject(json);
                String open = jsonObject.getString("open");
                if (!"1".equals(open)) {
                    return R.error("未开启领取功能，领取失败");
                }
                amount = jsonObject.getBigDecimal("amount");
            } catch (Exception e) {
                log.error("解析理疗红包配置失败, json={}", json, e);
                amount = new BigDecimal("0.1");
            }
        } else {
            return R.error("获取理疗红包配置错误");
        }
        // 准备发送红包参数
        WxSendRedPacketParam packetParam = new WxSendRedPacketParam();
        //处理多小程序问题
        FsUserWx fsUserWx = fsUserWxService.selectByAppIdAndUserId(param.getAppId(),user.getUserId(),1);
        if (fsUserWx ==null){
            try {
                handleFsUserWx(user,param.getAppId());
            }catch (Exception e){
                log.error("【更新或插入用户与小程序的绑定关系失败】：{}", user.getUserId());
            }
        }else {
            packetParam.setOpenId(fsUserWx.getOpenId());
        }
        packetParam.setRedPacketMode(1);
        packetParam.setAppId(param.getAppId());
        packetParam.setMpAppId(param.getAppId());
        packetParam.setUser(user);
        packetParam.setProjectFlag(true);
        packetParam.setAmount(amount);
        //小程序
        packetParam.setSource(2);
        packetParam.setCompanyId(companyUser.getCompanyId());

        // 发送红包
        R sendRedPacket = fsStorePaymentService.sendRedPacket(packetParam);
        if (sendRedPacket.get("code").equals(200)) {
            FsProjectRedPacketRecord redPacketRecord = new FsProjectRedPacketRecord();
            TransferBillsResult transferBillsResult;
            if (sendRedPacket.get("isNew").equals(1)){
                transferBillsResult = (TransferBillsResult)sendRedPacket.get("data");
                redPacketRecord.setResult(JSON.toJSONString(sendRedPacket));
                redPacketRecord.setOutBatchNo(transferBillsResult.getOutBillNo());
            }else {
                redPacketRecord.setOutBatchNo(sendRedPacket.get("orderCode").toString());
                redPacketRecord.setBatchId(sendRedPacket.get("batchId").toString());
            }
            // 添加红包记录
            redPacketRecord.setCompanyId(companyUser.getCompanyId());
            redPacketRecord.setCompanyUserId(companyUser.getUserId());
            redPacketRecord.setCompanyName(companyUser.getCompanyName());
            redPacketRecord.setUserId(param.getUserId());
            redPacketRecord.setUserName(user.getNickName());
            redPacketRecord.setProjectId(param.getProjectId());
            redPacketRecord.setCollectType(0);
            redPacketRecord.setSendTime(new Date());
            redPacketRecord.setCreateTime(new Date());
            redPacketRecord.setAmount(amount);
            redPacketRecord.setType(param.getType());
            redPacketRecord.setSignUrl(param.getSignUrl());
            projectRedPacketRecordMapper.insertFsProjectRedPacketRecord(redPacketRecord);
            return sendRedPacket;
        } else {
            return R.error("奖励发送失败，请联系客服");
        }
    }

    private void handleFsUserWx(FsUser user, String appId) {
        FsUserWx fsUserWx = new FsUserWx();
        fsUserWx.setType(1);
        fsUserWx.setFsUserId(user.getUserId());
        fsUserWx.setAppId(appId);
        fsUserWx.setOpenId(user.getCourseMaOpenId());
        fsUserWx.setUnionId(user.getUnionId());
        fsUserWx.setCreateTime(new Date());
        fsUserWx.setUpdateTime(new Date());
        fsUserWxService.saveOrUpdateByUniqueKey(fsUserWx);

        log.info("【更新或插入用户与小程序{}的绑定关系】：{}", appId, user.getUserId());
    }

    private String getProjectRedPacketConfig(){
        return configService.selectConfigByKey("projectRedPacket.config");
    }
}
