package com.ym.mec.biz.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.ym.mec.auth.api.client.SysUserFeignService;
import com.ym.mec.auth.api.entity.SysUser;
import com.ym.mec.biz.dal.dao.*;
import com.ym.mec.biz.dal.dto.BasicUserDto;
import com.ym.mec.biz.dal.dto.GoodsSellDto;
import com.ym.mec.biz.dal.dto.RepairGoodsDto;
import com.ym.mec.biz.dal.entity.*;
import com.ym.mec.biz.dal.enums.*;
import com.ym.mec.biz.dal.page.RepairStudentQueryInfo;
import com.ym.mec.biz.service.*;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.page.PageInfo;
import com.ym.mec.common.page.QueryInfo;
import com.ym.mec.common.service.IdGeneratorService;
import com.ym.mec.common.service.impl.BaseServiceImpl;
import com.ym.mec.thirdparty.message.MessageSenderPluginContext;
import com.ym.mec.util.collection.MapUtil;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

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

@Service
public class StudentRepairServiceImpl extends BaseServiceImpl<Integer, StudentRepair> implements StudentRepairService {
    private static final Logger log = LoggerFactory.getLogger(StudentRepairServiceImpl.class);
    @Autowired
    private StudentRepairDao studentRepairDao;
    @Autowired
    private SysUserFeignService sysUserFeignService;
    @Autowired
    private PayService payService;
    @Autowired
    private IdGeneratorService idGeneratorService;
    @Autowired
    private SysConfigDao sysConfigDao;
    @Autowired
    private StudentPaymentOrderService studentPaymentOrderService;
    @Autowired
    private SysPaymentConfigService sysPaymentConfigService;
    @Autowired
    private MusicGroupDao musicGroupDao;
    @Autowired
    private SysUserCashAccountService sysUserCashAccountService;
    @Autowired
    private SysUserCashAccountDetailService sysUserCashAccountDetailService;
    @Autowired
    private SysMessageService sysMessageService;
    @Autowired
    private StudentDao studentDao;
    @Autowired
    private StudentPaymentRouteOrderService studentPaymentRouteOrderService;
    @Autowired
    private SellOrderService sellOrderService;
    @Autowired
    private StudentGoodsSellDao studentGoodsSellDao;
    @Autowired
    private ContractService contractService;
    @Autowired
    private GoodsService goodsService;

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

    @Override
    public BaseDAO<Integer, StudentRepair> getDAO() {
        return studentRepairDao;
    }

    @Override
    public PageInfo<BasicUserDto> getStudents(RepairStudentQueryInfo queryInfo) {
        PageInfo<BasicUserDto> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<>();
        MapUtil.populateMap(params, queryInfo);
        List<BasicUserDto> dataList = new ArrayList<>();
        int count = studentRepairDao.getStudentsCount(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = studentRepairDao.getStudents(params);
            Set<Integer> userIds = dataList.stream().map(BasicUserDto::getUserId).collect(Collectors.toSet());
            List<MusicGroup> musicGroups = studentRepairDao.getUserMusicGroup(userIds);
            Map<Integer, List<MusicGroup>> userMusicGroup = musicGroups.stream().collect(Collectors.groupingBy(MusicGroup::getRepairUserId));
            for (BasicUserDto basicUserDto : dataList) {
                if (!userMusicGroup.containsKey(basicUserDto.getUserId())) {
                    continue;
                }
                MusicGroup musicGroup = userMusicGroup.get(basicUserDto.getUserId()).get(0);
                basicUserDto.setMusicGroupId(musicGroup.getId());
                basicUserDto.setMusicGroupName(musicGroup.getName());
            }
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public Map addGoodsSellOrder(StudentGoodsSell studentGoodsSell) throws Exception {
        //关闭老订单
        if (StringUtils.isNotEmpty(studentGoodsSell.getOrderNo())) {
            StudentPaymentOrder orderByOrderNo = studentPaymentOrderService.findOrderByOrderNo(studentGoodsSell.getOrderNo());
            if (orderByOrderNo.getBalancePaymentAmount() != null && orderByOrderNo.getBalancePaymentAmount().longValue() != 0l) {
                studentGoodsSell.setIsUseBalancePayment(true);
            } else {
                studentGoodsSell.setIsUseBalancePayment(false);
            }
            orderByOrderNo.setStatus(DealStatusEnum.CLOSE);
            studentPaymentOrderService.update(orderByOrderNo);
            if (orderByOrderNo.getBalancePaymentAmount() != null && orderByOrderNo.getBalancePaymentAmount().compareTo(BigDecimal.ZERO) > 0) {
                sysUserCashAccountService.updateBalance(orderByOrderNo.getUserId(), orderByOrderNo.getBalancePaymentAmount(), PlatformCashAccountDetailTypeEnum.REFUNDS, "关闭订单");
            }
            StudentGoodsSell byOrderNo = studentGoodsSellDao.findByOrderNo(studentGoodsSell.getOrderNo());
            if (byOrderNo != null) {
                studentGoodsSell = byOrderNo;
                studentGoodsSell.setGoodsSellDtos(JSON.parseArray(byOrderNo.getGoodsJson(), GoodsSellDto.class));
            }
        }
        Integer studentId = studentGoodsSell.getUserId();
        List<GoodsSellDto> goodsSellDtos = studentGoodsSell.getGoodsSellDtos();
        if (goodsSellDtos == null || goodsSellDtos.size() == 0) {
            throw new BizException("请选择需要购买的商品");
        }
        if (studentId == null) {
            throw new BizException("请指定学员");
        }

        studentDao.lockUser(studentId);
        SysUser student = sysUserFeignService.queryUserById(studentId);
        //如果教务老师为空，代表学员自己创建的订单
        if (studentGoodsSell.getTeacherId() == null) {
            //获取学生关联的所有教务老师列表
            List<Integer> stuEducation = studentRepairDao.countStuEducation(studentId);
            if (stuEducation != null && stuEducation.size() == 1) {
                //获取学员乐团关联的教务
                MusicGroup musicGroup = musicGroupDao.getStuMusic(studentId);
                studentGoodsSell.setTeacherId(stuEducation.get(0));
                if (musicGroup != null) {
                    studentGoodsSell.setCooperationOrganId(musicGroup.getCooperationOrganId());
                }
            }
        } else if (studentGoodsSell.getCooperationOrganId() == null) {
            //获取教务老师，学员关联的乐团
            MusicGroup musicGroup = musicGroupDao.getStuEduMusic(studentId, studentGoodsSell.getTeacherId());
            if (musicGroup != null) {
                studentGoodsSell.setCooperationOrganId(musicGroup.getCooperationOrganId());
            }
        }
        List<Integer> goodsIds = goodsSellDtos.stream().map(e -> e.getGoodsId()).collect(Collectors.toList());
        Map<Integer, String> integerStringMap = getMap("goods", "id_", "type_", goodsIds, Integer.class, String.class);
        Map<Integer, BigDecimal> map = getMap("goods", "id_", "discount_price_", goodsIds, Integer.class, BigDecimal.class);
        for (GoodsSellDto goodsSellDto : goodsSellDtos) {
            goodsSellDto.setGoodsType(integerStringMap.get(goodsSellDto.getGoodsId()));
            if (StringUtils.isNotEmpty(goodsSellDto.getComplementGoodsIdList())) {
                goodsSellDto.setGoodsSellDtos(goodsService.queryGoodsSellDtos(goodsSellDto.getComplementGoodsIdList()));
            }
            goodsSellDto.setGoodsPrice(map.get(goodsSellDto.getGoodsId()));
            goodsSellDto.setTotalGoodsPrice(map.get(goodsSellDto.getGoodsId()).multiply(new BigDecimal(goodsSellDto.getGoodsNum())));
        }
        Map<Integer, List<GoodsSellDto>> goodsMap = goodsSellDtos.stream().collect(Collectors.groupingBy(GoodsSellDto::getGoodsId));
        BigDecimal amount = BigDecimal.ZERO;
        for (Integer id : goodsIds) {
            GoodsSellDto goodsSellDto = goodsMap.get(id).get(0);
            amount = amount.add(goodsSellDto.getTotalGoodsPrice());
        }
        amount = amount.subtract(studentGoodsSell.getMarketAmount());
        if (amount.signum() < 0) {
            throw new BizException("操作失败：订单金额异常");
        }
        studentGoodsSell.setOrganId(student.getOrganId());
        studentGoodsSell.setTotalAmount(amount);
        studentGoodsSell.setGoodsJson(JSONObject.toJSONString(goodsSellDtos));
        String orderNo = idGeneratorService.generatorId("payment") + "";
        studentGoodsSell.setOrderNo(orderNo);
        studentGoodsSellDao.insert(studentGoodsSell);

        if (studentGoodsSell.getType() == 1) {
            Map<String, Object> repairInfoMap = new HashMap<>();
            MapUtil.populateMap(repairInfoMap, studentGoodsSell);
            return repairInfoMap;
        }

        StudentPaymentOrder studentPaymentOrder = new StudentPaymentOrder();
        studentPaymentOrder.setUserId(studentId);
        studentPaymentOrder.setGroupType(GroupType.GOODS_SELL);
        studentPaymentOrder.setOrderNo(orderNo);
        studentPaymentOrder.setType(OrderTypeEnum.GOODS_SELL);
        studentPaymentOrder.setExpectAmount(amount);
        studentPaymentOrder.setActualAmount(amount);
        studentPaymentOrder.setStatus(DealStatusEnum.ING);
        studentPaymentOrder.setOrganId(student.getOrganId());
        studentPaymentOrder.setRoutingOrganId(student.getOrganId());
        studentPaymentOrderService.insert(studentPaymentOrder);

        studentPaymentOrder.setVersion(0);
        BigDecimal balance = BigDecimal.ZERO;
        if (studentGoodsSell.getIsUseBalancePayment() && amount.compareTo(BigDecimal.ZERO) > 0) {
            SysUserCashAccount userCashAccount = sysUserCashAccountService.getLocked(studentId);
            if (userCashAccount == null) {
                throw new BizException("用户账户不存在");
            }
            if (userCashAccount.getBalance() != null && userCashAccount.getBalance().compareTo(BigDecimal.ZERO) > 0) {
                balance = amount.compareTo(userCashAccount.getBalance()) >= 0 ? userCashAccount.getBalance() : amount;
                amount = amount.subtract(balance);
                studentPaymentOrder.setActualAmount(amount);
                studentPaymentOrder.setBalancePaymentAmount(balance);
                sysUserCashAccountService.updateBalance(studentId, balance.negate(), PlatformCashAccountDetailTypeEnum.PAY_FEE, "商品销售");
            }
        }
        studentPaymentOrderService.update(studentPaymentOrder);
        studentPaymentOrder.setVersion(studentPaymentOrder.getVersion() + 1);

        if (amount.compareTo(BigDecimal.ZERO) == 0) {
            studentPaymentRouteOrderService.addRouteOrder(orderNo, student.getOrganId(), balance);
            Map<String, String> notifyMap = new HashMap<>();
            notifyMap.put("tradeState", "1");
            notifyMap.put("merOrderNo", studentPaymentOrder.getOrderNo());
            studentPaymentOrderService.updateOrder(notifyMap);
            notifyMap.put("orderNo", orderNo);
            return notifyMap;
        }

        String baseApiUrl = sysConfigDao.findConfigValue(SysConfigService.BASE_API_URL);

        Map payMap = payService.getPayMap(
                amount,
                balance,
                orderNo,
                baseApiUrl + "/api-student/studentOrder/notify",
                baseApiUrl + "/api-student/studentOrder/paymentResult?type=edu&orderNo=" + orderNo,
                "商品销售",
                "商品销售",
                student.getOrganId(),
                "goodsSell"
        );

        studentPaymentOrder.setMerNos((String) payMap.get("routingMerNos"));
        studentPaymentOrder.setPaymentChannel((String) payMap.get("type"));
        studentPaymentOrderService.update(studentPaymentOrder);
        return payMap;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Map studentPaymentGoodsOrder(Integer goodsSellId) throws Exception {
        StudentGoodsSell studentGoodsSell = studentGoodsSellDao.get(goodsSellId);
        Integer studentId = studentGoodsSell.getUserId();
        studentDao.lockUser(studentId);
        List<GoodsSellDto> goodsSellDtos = JSONObject.parseArray(studentGoodsSell.getGoodsJson(), GoodsSellDto.class);
        List<Integer> goodsIds = goodsSellDtos.stream().map(e -> e.getGoodsId()).collect(Collectors.toList());
        Map<Integer, String> integerStringMap = getMap("goods", "id_", "type_", goodsIds, Integer.class, String.class);
        Map<Integer, BigDecimal> map = getMap("goods", "id_", "discount_price_", goodsIds, Integer.class, BigDecimal.class);
        for (GoodsSellDto goodsSellDto : goodsSellDtos) {
            goodsSellDto.setGoodsType(integerStringMap.get(goodsSellDto.getGoodsId()));
            if (StringUtils.isNotEmpty(goodsSellDto.getComplementGoodsIdList())) {
                goodsSellDto.setGoodsSellDtos(goodsService.queryGoodsSellDtos(goodsSellDto.getComplementGoodsIdList()));
            }
            goodsSellDto.setGoodsPrice(map.get(goodsSellDto.getGoodsId()));
            goodsSellDto.setTotalGoodsPrice(map.get(goodsSellDto.getGoodsId()).multiply(new BigDecimal(goodsSellDto.getGoodsNum())));
        }
        Map<Integer, List<GoodsSellDto>> goodsMap = goodsSellDtos.stream().collect(Collectors.groupingBy(GoodsSellDto::getGoodsId));
        BigDecimal amount = BigDecimal.ZERO;
        for (Integer id : goodsIds) {
            GoodsSellDto goodsSellDto = goodsMap.get(id).get(0);
            amount = amount.add(goodsSellDto.getTotalGoodsPrice());
        }
        amount = amount.subtract(studentGoodsSell.getMarketAmount());
        if (amount.signum() < 0) {
            throw new BizException("操作失败：订单金额异常");
        }
        String orderNo1 = studentGoodsSell.getOrderNo();
        String orderNo = idGeneratorService.generatorId("payment") + "";

        studentGoodsSell.setOrderNo(orderNo);
        StudentPaymentOrder studentPaymentOrder = null;
        if (StringUtils.isNotEmpty(orderNo1)) {
            studentPaymentOrder = studentPaymentOrderService.findOrderByOrderNo(orderNo1);
            if (studentPaymentOrder != null) {
                if (studentPaymentOrder.getStatus() == DealStatusEnum.SUCCESS) {
                    throw new BizException("该订单已支付");
                }
                //关闭老订单
                if (studentPaymentOrder.getBalancePaymentAmount() != null && studentPaymentOrder.getBalancePaymentAmount().longValue() != 0l) {
                    studentGoodsSell.setIsUseBalancePayment(true);
                } else {
                    studentGoodsSell.setIsUseBalancePayment(false);
                }
                studentPaymentOrder.setStatus(DealStatusEnum.CLOSE);
                studentPaymentOrderService.update(studentPaymentOrder);
                if (studentPaymentOrder.getBalancePaymentAmount() != null && studentPaymentOrder.getBalancePaymentAmount().compareTo(BigDecimal.ZERO) > 0) {
                    sysUserCashAccountService.updateBalance(studentPaymentOrder.getUserId(), studentPaymentOrder.getBalancePaymentAmount(), PlatformCashAccountDetailTypeEnum.REFUNDS, "关闭订单");
                }
            }
        }
        studentGoodsSellDao.update(studentGoodsSell);
        studentPaymentOrder = new StudentPaymentOrder();
        studentPaymentOrder.setUserId(studentId);
        studentPaymentOrder.setGroupType(GroupType.GOODS_SELL);
        studentPaymentOrder.setOrderNo(orderNo);
        studentPaymentOrder.setType(OrderTypeEnum.GOODS_SELL);
        studentPaymentOrder.setExpectAmount(amount);
        studentPaymentOrder.setActualAmount(amount);
        studentPaymentOrder.setStatus(DealStatusEnum.ING);
        studentPaymentOrder.setOrganId(studentGoodsSell.getOrganId());
        studentPaymentOrder.setRoutingOrganId(studentGoodsSell.getOrganId());
        studentPaymentOrderService.insert(studentPaymentOrder);

        studentPaymentOrder.setVersion(0);
        BigDecimal balance = BigDecimal.ZERO;
        if (studentGoodsSell.getIsUseBalancePayment() && amount.compareTo(BigDecimal.ZERO) > 0) {
            SysUserCashAccount userCashAccount = sysUserCashAccountService.getLocked(studentId);
            if (userCashAccount == null) {
                throw new BizException("用户账户不存在");
            }
            if (userCashAccount.getBalance() != null && userCashAccount.getBalance().compareTo(BigDecimal.ZERO) > 0) {
                balance = amount.compareTo(userCashAccount.getBalance()) >= 0 ? userCashAccount.getBalance() : amount;
                amount = amount.subtract(balance);
                studentPaymentOrder.setActualAmount(amount);
                studentPaymentOrder.setBalancePaymentAmount(balance);
                sysUserCashAccountService.updateBalance(studentId, balance.negate(), PlatformCashAccountDetailTypeEnum.PAY_FEE, "商品销售");
            }
        }
        studentPaymentOrderService.update(studentPaymentOrder);
        studentPaymentOrder.setVersion(studentPaymentOrder.getVersion() + 1);

        if (amount.compareTo(BigDecimal.ZERO) == 0) {
            studentPaymentRouteOrderService.addRouteOrder(orderNo, studentGoodsSell.getOrganId(), balance);
            Map<String, String> notifyMap = new HashMap<>();
            notifyMap.put("tradeState", "1");
            notifyMap.put("merOrderNo", studentPaymentOrder.getOrderNo());
            studentPaymentOrderService.updateOrder(notifyMap);
            notifyMap.put("orderNo", orderNo);
            return notifyMap;
        }

        String baseApiUrl = sysConfigDao.findConfigValue(SysConfigService.BASE_API_URL);

        Map payMap = payService.getPayMap(
                amount,
                balance,
                orderNo,
                baseApiUrl + "/api-student/studentOrder/notify",
                baseApiUrl + "/api-student/studentOrder/paymentResult?type=edu&orderNo=" + orderNo,
                "商品销售",
                "商品销售",
                studentGoodsSell.getOrganId(),
                "goodsSell"
        );

        studentPaymentOrder.setMerNos((String) payMap.get("routingMerNos"));
        studentPaymentOrder.setPaymentChannel((String) payMap.get("type"));
        studentPaymentOrderService.update(studentPaymentOrder);
        return payMap;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map addRepair(StudentRepair repairInfo) throws Exception {
        studentDao.lockUser(repairInfo.getEmployeeId());
        if (repairInfo.getSendType() != null && repairInfo.getSendType().equals(1) &&
                (repairInfo.getContactName() == null || repairInfo.getContactName().isEmpty()) &&
                (repairInfo.getContactMobile() == null || repairInfo.getContactMobile().isEmpty()) &&
                (repairInfo.getAddress() == null || repairInfo.getAddress().isEmpty())
        ) {
            throw new BizException("邮寄信息必填");
        }
        SysUser student = sysUserFeignService.queryUserById(repairInfo.getStudentId());
        repairInfo.setOrganId(student.getOrganId());

        Date date = new Date();
        BigDecimal amount = repairInfo.getAmount();
        String orderNo = idGeneratorService.generatorId("payment") + "";
        repairInfo.setTransNo(orderNo);
        repairInfo.setRepairStatus(0);
        repairInfo.setPayStatus(0);
        repairInfo.setCreateTime(date);
        repairInfo.setUpdateTime(date);
        String goodsJson = repairInfo.getGoodsJson();
        if (StringUtils.isNotEmpty(goodsJson)) {
            List<RepairGoodsDto> repairGoodsDtos = JSONObject.parseArray(goodsJson, RepairGoodsDto.class);
            List<Integer> goodsIds = repairGoodsDtos.stream().map(e -> e.getId()).collect(Collectors.toList());
            Map<Integer, BigDecimal> map = getMap("goods", "id_", "discount_price_", goodsIds, Integer.class, BigDecimal.class);
            repairGoodsDtos.forEach(e -> {
                e.setGroupPurchasePrice(map.get(e.getId()));
            });
            repairInfo.setGoodsJson(JSONObject.toJSONString(repairGoodsDtos));
        }
        studentRepairDao.insert(repairInfo);
        if (repairInfo.getType() == 1) {
            Map<String, Object> repairInfoMap = new HashMap<>();
            MapUtil.populateMap(repairInfoMap, repairInfo);
            return repairInfoMap;
        }

        if (StringUtils.isNoneBlank(repairInfo.getGoodsJson())) {
            JSONArray goods = JSON.parseArray(repairInfo.getGoodsJson());
            for (Object good : goods) {
                JSONObject goodObject = (JSONObject) good;
                BigDecimal groupPurchasePrice = goodObject.getBigDecimal("groupPurchasePrice");
                if (Objects.nonNull(groupPurchasePrice)) {
                    amount = amount.add(groupPurchasePrice);
                }
            }
        }

        repairInfo.setPayStatus(1);
        String channelType = "";

        StudentPaymentOrder studentPaymentOrder = new StudentPaymentOrder();
        studentPaymentOrder.setUserId(repairInfo.getStudentId());
        studentPaymentOrder.setGroupType(GroupType.REPAIR);
        studentPaymentOrder.setOrderNo(orderNo);
        studentPaymentOrder.setType(OrderTypeEnum.REPAIR);
        studentPaymentOrder.setExpectAmount(amount);
        studentPaymentOrder.setActualAmount(amount);
        studentPaymentOrder.setStatus(DealStatusEnum.ING);
        studentPaymentOrder.setMusicGroupId(repairInfo.getId().toString());
        studentPaymentOrder.setPaymentChannel("BALANCE");
        studentPaymentOrder.setUpdateTime(date);
        studentPaymentOrder.setOrganId(repairInfo.getOrganId());
        studentPaymentOrder.setRoutingOrganId(repairInfo.getOrganId());

        studentPaymentOrderService.insert(studentPaymentOrder);
        studentPaymentOrder.setVersion(0);

        BigDecimal balance = BigDecimal.ZERO;
        if (repairInfo.getIsUseBalancePayment() && amount.compareTo(BigDecimal.ZERO) > 0) {
            SysUserCashAccount userCashAccount = sysUserCashAccountService.getLocked(repairInfo.getStudentId());
            if (userCashAccount == null) {
                throw new BizException("用户账户找不到");
            }
            if (userCashAccount.getBalance() != null && userCashAccount.getBalance().compareTo(BigDecimal.ZERO) > 0) {
                balance = amount.compareTo(userCashAccount.getBalance()) >= 0 ? userCashAccount.getBalance() : amount;
                amount = amount.subtract(balance);
                studentPaymentOrder.setActualAmount(amount);
                studentPaymentOrder.setBalancePaymentAmount(balance);
                sysUserCashAccountService.updateBalance(repairInfo.getStudentId(), balance.negate(), PlatformCashAccountDetailTypeEnum.PAY_FEE, "乐器维修");
            }
        }
        studentPaymentOrderService.update(studentPaymentOrder);
        studentPaymentOrder.setVersion(studentPaymentOrder.getVersion() + 1);

        if (amount.compareTo(BigDecimal.ZERO) == 0) {
            studentPaymentRouteOrderService.addRouteOrder(orderNo, repairInfo.getOrganId(), balance);
            Map<String, String> notifyMap = new HashMap<>();
            notifyMap.put("tradeState", "1");
            notifyMap.put("merOrderNo", studentPaymentOrder.getOrderNo());
            notifyMap.put("channelType", channelType);
            notifyMap.put("orderNo", "");
            studentPaymentOrderService.updateOrder(notifyMap);
            notifyMap.put("orderNo", orderNo);
            return notifyMap;
        }

        String baseApiUrl = sysConfigDao.findConfigValue(SysConfigService.BASE_API_URL);

        Map<String, BigDecimal> classFee = new HashMap<>();
        classFee.put("course", BigDecimal.ZERO);
        classFee.put("instrument", BigDecimal.ZERO);
        classFee.put("accessories", BigDecimal.ZERO);
        classFee.put("other", amount);

        Map payMap = payService.getPayMap(
                amount,
                balance,
                orderNo,
                baseApiUrl + "/api-student/studentOrder/notify",
                baseApiUrl + "/api-student/studentOrder/paymentResult?type=edu&orderNo=" + orderNo,
                "乐器维修",
                "乐器维修",
                repairInfo.getOrganId(),
                "repair"
        );

        studentPaymentOrder.setMerNos((String) payMap.get("routingMerNos"));
        studentPaymentOrder.setPaymentChannel((String) payMap.get("type"));
        studentPaymentOrder.setUpdateTime(date);
        studentPaymentOrderService.update(studentPaymentOrder);
        return payMap;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void repairSuccess(Integer id, String description, Integer repairStatus) {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("用户信息获取失败");
        }
        studentDao.lockUser(sysUser.getId());
        StudentRepair studentRepair = studentRepairDao.getRepairInfo(id);
        if (studentRepair == null) {
            throw new BizException("维修信息不存在");
        }
        if (repairStatus != null) {
            studentRepair.setRepairStatus(1);
            studentRepair.setFinishTime(new Date());
        }
        studentRepair.setUpdateTime(new Date());
        studentRepair.setDescription(description);
        studentRepairDao.update(studentRepair);

        if (repairStatus != null) {
            SysUser student = sysUserFeignService.queryUserById(studentRepair.getStudentId());
            Map<Integer, String> map = new HashMap();
            map.put(student.getId(), student.getId().toString());

            String imContent = student.getUsername() + "您的乐器已保养维修完毕，请安排时间来维修点取回\n" +
                    "联系人：" + studentRepair.getEmployeeName() + "（" + studentRepair.getEmployeePhone() + "）\n" +
                    "地址：" + studentRepair.getEmployeeAddress();

            if (studentRepair.getSendType().equals(0)) {
                sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.SMS_REPAIR_UNSEND_COMPLETED, map, null, 0, "1", "STUDENT",
                        student.getUsername(), studentRepair.getEmployeeName(), studentRepair.getEmployeePhone(), studentRepair.getEmployeeAddress());
            } else {
                sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.SMS_REPAIR_SEND_COMPLETED, map, null, 0, "1", "STUDENT",
                        student.getUsername());
                imContent = student.getUsername() + "学员您好,您的乐器已保养维修完毕，快递已寄出，请注意查收。";
            }

            sysMessageService.sendPrivateMessage(student.getId().toString(), imContent);
        }
        log.info("操作人 :" + sysUser.getId());
    }

    @Override
    public BasicUserDto getStudentInfo(Integer studentId) {
        return studentRepairDao.getStudentInfo(studentId);
    }

    @Override
    public StudentRepair getRepairInfo(Integer id) {
        return studentRepairDao.getRepairInfo(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map payRepair(StudentRepair repairInfo) throws Exception {
        if (repairInfo.getSendType().equals(1) &&
                (repairInfo.getContactName() == null || repairInfo.getContactName().isEmpty()) &&
                (repairInfo.getContactMobile() == null || repairInfo.getContactMobile().isEmpty()) &&
                (repairInfo.getAddress() == null || repairInfo.getAddress().isEmpty())
        ) {
            throw new BizException("邮寄信息必填");
        }
        Date date = new Date();
        StudentRepair studentRepair = studentRepairDao.get(repairInfo.getId());
        studentDao.lockUser(studentRepair.getStudentId());
        BigDecimal amount = studentRepair.getAmount();
        String goodsJson = studentRepair.getGoodsJson();
        if (StringUtils.isNotEmpty(goodsJson)) {
            List<RepairGoodsDto> repairGoodsDtos = JSONObject.parseArray(goodsJson, RepairGoodsDto.class);
            BigDecimal reduce = repairGoodsDtos.stream().map(e -> e.getGroupPurchasePrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
            amount = amount.add(reduce);
        }
        String orderNo = idGeneratorService.generatorId("payment") + "";
        studentRepair.setIsUseBalancePayment(repairInfo.getIsUseBalancePayment());
        studentRepair.setTransNo(orderNo);
        studentRepair.setRepairStatus(0);
        studentRepair.setPayStatus(1);
        studentRepair.setSendType(repairInfo.getSendType());
        studentRepair.setContactName(repairInfo.getContactName());
        studentRepair.setContactMobile(repairInfo.getContactMobile());
        studentRepair.setAddress(repairInfo.getAddress());
        studentRepair.setUpdateTime(date);
        studentRepairDao.update(studentRepair);

        String channelType = "";

        StudentPaymentOrder studentPaymentOrder = new StudentPaymentOrder();
        studentPaymentOrder.setUserId(studentRepair.getStudentId());
        studentPaymentOrder.setGroupType(GroupType.REPAIR);
        studentPaymentOrder.setOrderNo(orderNo);
        studentPaymentOrder.setType(OrderTypeEnum.REPAIR);
        studentPaymentOrder.setExpectAmount(amount);
        studentPaymentOrder.setActualAmount(amount);
        studentPaymentOrder.setStatus(DealStatusEnum.ING);
        studentPaymentOrder.setMusicGroupId(studentRepair.getId().toString());
        studentPaymentOrder.setPaymentChannel("BALANCE");
        studentPaymentOrder.setUpdateTime(date);
        studentPaymentOrder.setOrganId(studentRepair.getOrganId());
        studentPaymentOrder.setRoutingOrganId(studentRepair.getOrganId());

        studentPaymentOrderService.insert(studentPaymentOrder);
        studentPaymentOrder.setVersion(0);

        BigDecimal balance = BigDecimal.ZERO;
        if (studentRepair.getIsUseBalancePayment() && amount.compareTo(BigDecimal.ZERO) > 0) {
            SysUserCashAccount userCashAccount = sysUserCashAccountService.getLocked(studentRepair.getStudentId());
            if (userCashAccount == null) {
                throw new BizException("用户账户找不到");
            }
            if (userCashAccount.getBalance() != null && userCashAccount.getBalance().compareTo(BigDecimal.ZERO) > 0) {
                balance = amount.compareTo(userCashAccount.getBalance()) >= 0 ? userCashAccount.getBalance() : amount;
                amount = amount.subtract(balance);
                studentPaymentOrder.setActualAmount(amount);
                studentPaymentOrder.setBalancePaymentAmount(balance);
                sysUserCashAccountService.updateBalance(studentRepair.getStudentId(), balance.negate(), PlatformCashAccountDetailTypeEnum.PAY_FEE, "乐器维修");
            }
        }
        studentPaymentOrderService.update(studentPaymentOrder);
        studentPaymentOrder.setVersion(studentPaymentOrder.getVersion() + 1);

        if (amount.compareTo(BigDecimal.ZERO) == 0) {
            studentPaymentRouteOrderService.addRouteOrder(orderNo, studentRepair.getOrganId(), studentPaymentOrder.getExpectAmount());
            Map<String, String> notifyMap = new HashMap<>();
            notifyMap.put("tradeState", "1");
            notifyMap.put("merOrderNo", studentPaymentOrder.getOrderNo());
            notifyMap.put("channelType", channelType);
            notifyMap.put("orderNo", "");
            studentPaymentOrderService.updateOrder(notifyMap);
            notifyMap.put("orderNo", orderNo);
            return notifyMap;
        }

        String baseApiUrl = sysConfigDao.findConfigValue(SysConfigService.BASE_API_URL);

        Map<String, BigDecimal> classFee = new HashMap<>();
        classFee.put("course", BigDecimal.ZERO);
        classFee.put("instrument", BigDecimal.ZERO);
        classFee.put("accessories", BigDecimal.ZERO);
        classFee.put("other", amount);

        Map payMap = payService.getPayMap(
                amount,
                balance,
                orderNo,
                baseApiUrl + "/api-student/studentOrder/notify",
                baseApiUrl + "/api-student/studentOrder/paymentResult?orderNo=" + orderNo,
                "乐器维修",
                "乐器维修",
                studentRepair.getOrganId(),
                "repair"
        );

        studentPaymentOrder.setMerNos((String) payMap.get("routingMerNos"));
        studentPaymentOrder.setPaymentChannel((String) payMap.get("type"));
        studentPaymentOrder.setUpdateTime(date);
        studentPaymentOrderService.update(studentPaymentOrder);
        return payMap;
    }

    @Override
    public BasicUserDto getStudentRepairer(Integer studentId, Integer organId) {
        BasicUserDto repairer = studentRepairDao.getStudentMusicGroupRepairer(studentId);
        if (repairer == null) {
            repairer = studentRepairDao.getStudentOrganRepairer(organId);
        }
        return repairer;
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void goodsSellOrderCallback(StudentPaymentOrder studentPaymentOrder) {
        Date nowDate = new Date();
        //更新订单信息
        studentPaymentOrder.setUpdateTime(nowDate);
        int updateCount = studentPaymentOrderService.update(studentPaymentOrder);
        if (updateCount <= 0) {
            throw new BizException("订单更新失败");
        }

        Integer userId = studentPaymentOrder.getUserId();

        Map<Integer, String> map = new HashMap<>();
        map.put(userId, userId.toString());

        if (studentPaymentOrder.getStatus() == DealStatusEnum.SUCCESS) {
            try {
                contractService.transferProduceContract(userId, null);
            } catch (Exception e) {
                logger.error("产品协议生成失败", e);
            }
            //插入交易明细
            BigDecimal amount = studentPaymentOrder.getActualAmount();
            SysUserCashAccount cashAccount = sysUserCashAccountService.get(userId);
            //充值
            SysUserCashAccountDetail rechargeDetail = new SysUserCashAccountDetail();
            rechargeDetail.setAmount(amount);
            rechargeDetail.setBalance(cashAccount.getBalance().add(amount));
            rechargeDetail.setComment("缴费前充值");
            rechargeDetail.setStatus(DealStatusEnum.SUCCESS);
            rechargeDetail.setTransNo(studentPaymentOrder.getTransNo());
            rechargeDetail.setType(PlatformCashAccountDetailTypeEnum.RECHARGE);
            rechargeDetail.setUserId(userId);
            rechargeDetail.setChannel(studentPaymentOrder.getPaymentChannel());
            if (studentPaymentOrder.getComAmount() != null) {
                rechargeDetail.setComAmount(studentPaymentOrder.getComAmount().negate());
                rechargeDetail.setPerAmount(studentPaymentOrder.getPerAmount().negate());
            }
            sysUserCashAccountDetailService.insert(rechargeDetail);
            //缴费
            SysUserCashAccountDetail paymentDetail = new SysUserCashAccountDetail();
            paymentDetail.setAmount(amount.negate());
            paymentDetail.setBalance(cashAccount.getBalance());
            paymentDetail.setComment("商品销售");
            paymentDetail.setStatus(DealStatusEnum.SUCCESS);
            paymentDetail.setTransNo(studentPaymentOrder.getTransNo());
            paymentDetail.setType(PlatformCashAccountDetailTypeEnum.GOODS_SELL);
            paymentDetail.setUserId(userId);
            sysUserCashAccountDetailService.insert(paymentDetail);
            saveSellOrder(studentPaymentOrder.getOrderNo());
        } else if (studentPaymentOrder.getStatus() == DealStatusEnum.CLOSE || studentPaymentOrder.getStatus() == DealStatusEnum.FAILED) {
            if (studentPaymentOrder.getBalancePaymentAmount() != null && studentPaymentOrder.getBalancePaymentAmount().compareTo(BigDecimal.ZERO) > 0) {
                sysUserCashAccountService.updateBalance(studentPaymentOrder.getUserId(), studentPaymentOrder.getBalancePaymentAmount(), PlatformCashAccountDetailTypeEnum.REFUNDS, "乐器购买支付失败");
            }
        }
    }

    @Override
    public PageInfo<BasicUserDto> queryEduStudents(QueryInfo queryInfo) {
        SysUser sysUser = sysUserFeignService.queryUserInfo();
        if (sysUser == null) {
            throw new BizException("请登录");
        }
        PageInfo<BasicUserDto> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<>();
        MapUtil.populateMap(params, queryInfo);
        params.put("teacherId", sysUser.getId());

        List<BasicUserDto> dataList = null;
        int count = studentRepairDao.countEduStudents(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = studentRepairDao.queryEduStudents(params);
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public void saveSellOrder(String orderNo) {
        StudentPaymentOrder orderByOrderNo = studentPaymentOrderService.findOrderByOrderNo(orderNo);
        StudentGoodsSell studentGoodsSell = studentGoodsSellDao.findByOrderNo(orderNo);
        String goodsJson = studentGoodsSell.getGoodsJson();
        List<GoodsSellDto> goodsSellDtos = JSONObject.parseArray(goodsJson, GoodsSellDto.class);
        //用户选择的商品
        Map<Integer, List<GoodsSellDto>> collect = goodsSellDtos.stream().collect(Collectors.groupingBy(GoodsSellDto::getGoodsId));
        List<Integer> goodsIds = new ArrayList<>();
        goodsSellDtos.forEach(e -> {
            for (int i = 0; i < e.getGoodsNum(); i++) {
                goodsIds.add(e.getGoodsId());
            }
        });
        AccountType accountType = AccountType.INTERNAL;
        if (StringUtils.isNotEmpty(orderByOrderNo.getPaymentChannel())) {
            accountType = sysPaymentConfigService.checkAccountType(PaymentChannelEnum.valueOf(orderByOrderNo.getPaymentChannel()), orderByOrderNo.getMerNos());
        }
        //实际扣减的库存商品
        List<SellOrder> sellOrderList = goodsService.subtractStock(goodsIds, accountType);
        Map<String, BigDecimal> costMap = new HashMap<>(2);
        BigDecimal balancePaymentAmount = orderByOrderNo.getBalancePaymentAmount();
        //可用余额
        BigDecimal usableBalance = balancePaymentAmount;
        BigDecimal marketAmount = studentGoodsSell.getMarketAmount();
        //可用减免金额
        BigDecimal usableMarketAmount = marketAmount;
        //包含减免余额的总金额
        BigDecimal totalAmount = goodsSellDtos.stream().map(e -> e.getTotalGoodsPrice()).reduce(BigDecimal.ZERO, BigDecimal::add);
        //组合商品减免金额
        Map<Integer, BigDecimal> parentGoodsCutTotalPriceMap = new HashMap<>();
        //组合商品附加金额
        Map<Integer, BigDecimal> parentGoodsAddTotalPriceMap = new HashMap<>();
        //组合商品实际总价
        Map<Integer, BigDecimal> parentGoodsTotalPriceMap = new HashMap<>();
        //应付总额
        BigDecimal totalActual = totalAmount.subtract(marketAmount);
        //可用应付
        BigDecimal usableActual = totalActual;
        //获取实付总额
        BigDecimal realityAmount = totalActual.subtract(usableBalance);
        //可用实付总额
        BigDecimal usableAmount = realityAmount;
        //可用组合商品总减免金额
        BigDecimal usableParentGoodsCutTotalPrice;
        //可用组合商品总附加金额
        BigDecimal usableParentGoodsAddTotalPrice;

        //获取组合商品列表
        List<SellOrder> orderList = sellOrderList.stream().filter(sellOrder -> sellOrder.getParentGoodsId() != null).collect(Collectors.toList());
        Map<Integer, List<SellOrder>> orderListMap = orderList.stream().collect(Collectors.groupingBy(SellOrder::getParentGoodsId));

        //获取组合商品实际销售价，和单个商品总和价
        for (Integer integer : orderListMap.keySet()) {
            SellOrder sellOrder = orderListMap.get(integer).get(0);
            //获取组合商品销售总价
            GoodsSellDto goodsSellDto = collect.get(sellOrder.getParentGoodsId()).get(0);
            BigDecimal parentTotalGoodsPrice = goodsSellDto.getTotalGoodsPrice().divide(new BigDecimal(goodsSellDto.getGoodsNum()));
            BigDecimal totalGoodsPrice = BigDecimal.ZERO;
            //获取单个商品销售总价
            for (GoodsSellDto sellDto : goodsSellDto.getGoodsSellDtos()) {
                totalGoodsPrice = totalGoodsPrice.add(sellDto.getTotalGoodsPrice());
            }
            parentGoodsTotalPriceMap.put(sellOrder.getParentGoodsId(), totalGoodsPrice);
            //如果组合价大于预计总价
            if (parentTotalGoodsPrice.compareTo(totalGoodsPrice) == 1) {
                parentGoodsAddTotalPriceMap.put(sellOrder.getParentGoodsId(), parentTotalGoodsPrice.subtract(totalGoodsPrice));
            } else if (parentTotalGoodsPrice.compareTo(totalGoodsPrice) == -1) {//小于
                parentGoodsCutTotalPriceMap.put(sellOrder.getParentGoodsId(), totalGoodsPrice.subtract(parentTotalGoodsPrice));
            }
        }
        //分配组合商品的中单个商品的价格
        noFreeAmount:
        for (Integer parentGoodsId : orderListMap.keySet()) {

            BigDecimal addTotalPrice = parentGoodsAddTotalPriceMap.get(parentGoodsId);
            usableParentGoodsAddTotalPrice = addTotalPrice;
            BigDecimal cutTotalPrice = parentGoodsCutTotalPriceMap.get(parentGoodsId);
            usableParentGoodsCutTotalPrice = cutTotalPrice;

            //获取组合商品销售总价
            GoodsSellDto goodsSellDto = collect.get(parentGoodsId).get(0);
//            BigDecimal divide = goodsSellDto.getGoodsPrice();

            //获取子商品明细map
            List<GoodsSellDto> sellDtos = goodsSellDto.getGoodsSellDtos();
            Map<Integer, List<GoodsSellDto>> subGoodsMap = sellDtos.stream().collect(Collectors.groupingBy(GoodsSellDto::getGoodsId));
            List<Integer> integers = new ArrayList<>(subGoodsMap.keySet());
            BigDecimal divide = parentGoodsTotalPriceMap.get(parentGoodsId);
            for (int i = 0; i < integers.size(); i++) {
                GoodsSellDto sellDto = subGoodsMap.get(integers.get(i)).get(0);
                //获取比例
                BigDecimal ratioAmount = sellDto.getTotalGoodsPrice().divide(divide, 6, BigDecimal.ROUND_HALF_UP);

                if (addTotalPrice != null && addTotalPrice.doubleValue() > 0l) {
                    //如果是最后一件商品
                    if (i == integers.size() - 1) {
                        sellDto.setTotalGoodsPrice(sellDto.getTotalGoodsPrice().add(usableParentGoodsAddTotalPrice));
                    } else {
                        //获取分配的附加
                        BigDecimal multiply = ratioAmount.multiply(addTotalPrice).setScale(2, BigDecimal.ROUND_HALF_UP);
                        sellDto.setTotalGoodsPrice(sellDto.getTotalGoodsPrice().add(multiply));
                        usableParentGoodsAddTotalPrice = usableParentGoodsAddTotalPrice.subtract(multiply);
                    }
                    sellDto.setGoodsPrice(sellDto.getTotalGoodsPrice());
                } else if (cutTotalPrice != null && cutTotalPrice.doubleValue() > 0l) {
                    //如果是最后一件商品
                    if (i == integers.size() - 1) {
                        sellDto.setTotalGoodsPrice(sellDto.getTotalGoodsPrice().subtract(usableParentGoodsCutTotalPrice));
                    } else {
                        //获取分配的组合减免金额
                        BigDecimal multiply = ratioAmount.multiply(cutTotalPrice).setScale(2, BigDecimal.ROUND_HALF_UP);
                        sellDto.setTotalGoodsPrice(sellDto.getTotalGoodsPrice().subtract(multiply));
                        usableParentGoodsCutTotalPrice = usableParentGoodsCutTotalPrice.subtract(multiply);
                    }
                    sellDto.setGoodsPrice(sellDto.getTotalGoodsPrice());
                } else {
                    continue noFreeAmount;
                }
            }
        }
        for (int i = 0; i < sellOrderList.size(); i++) {
            SellOrder sellOrder = sellOrderList.get(i);
            Integer e = null;
            if (sellOrder.getParentGoodsId() != null) {
                e = sellOrder.getParentGoodsId();
            } else {
                e = sellOrder.getGoodsId();
            }
            GoodsSellDto goodsSellDto = collect.get(e).get(0);
            List<GoodsSellDto> sellDtos = goodsSellDto.getGoodsSellDtos();
            if (sellDtos != null && sellDtos.size() > 0) {
                Map<Integer, List<GoodsSellDto>> map = sellDtos.stream().collect(Collectors.groupingBy(GoodsSellDto::getGoodsId));
                goodsSellDto = map.get(sellOrder.getGoodsId()).get(0);
            }
            sellOrder.setOrganId(orderByOrderNo.getOrganId());
            sellOrder.setTransNo(orderByOrderNo.getTransNo());
            sellOrder.setOrderId(orderByOrderNo.getId());
            sellOrder.setOrderNo(orderByOrderNo.getOrderNo());
            Goods goods = goodsService.get(e);
            costMap.put("sellCost", goods.getDiscountPrice());
            if (goods.getAgreeCostPrice() != null) {
                costMap.put("SellCost2", goods.getAgreeCostPrice());
            }
            BigDecimal multiply2 = goodsSellDto.getGoodsPrice().multiply(new BigDecimal(sellOrder.getNum()));
            //获取比例
            BigDecimal ratioAmount = multiply2.divide(totalAmount, 6, BigDecimal.ROUND_HALF_UP);
            //如果有减免金额
            if (marketAmount.doubleValue() > 0l) {
                //如果是最后一件商品
                if (i == sellOrderList.size() - 1) {
                    goodsSellDto.setTotalGoodsPrice(multiply2.subtract(usableMarketAmount));
                } else {
                    //获取分配的减免金额
                    BigDecimal multiply = ratioAmount.multiply(marketAmount).setScale(2, BigDecimal.ROUND_HALF_UP);
                    goodsSellDto.setTotalGoodsPrice(multiply2.subtract(multiply));
                    usableMarketAmount = usableMarketAmount.subtract(multiply);
                }
            }

            //如果没有使用余额，那么实际金额和预计金额一致
            if (balancePaymentAmount.doubleValue() == 0l) {
                sellOrder.setActualAmount(goodsSellDto.getTotalGoodsPrice());
                sellOrder.setBalanceAmount(BigDecimal.ZERO);
            } else {
                //如果是最后一件商品
                if (i == sellOrderList.size() - 1) {
                    sellOrder.setActualAmount(usableAmount);
                    sellOrder.setBalanceAmount(usableBalance);
                } else {
                    //获取分配的余额
                    BigDecimal multiply = ratioAmount.multiply(balancePaymentAmount).setScale(2, BigDecimal.ROUND_HALF_UP);
                    //分配的实际支付
                    BigDecimal multiply1 = ratioAmount.multiply(realityAmount).setScale(2, BigDecimal.ROUND_HALF_UP);
                    sellOrder.setActualAmount(multiply1);
                    sellOrder.setBalanceAmount(multiply);
                    usableAmount = usableAmount.subtract(multiply1);
                    usableBalance = usableBalance.subtract(multiply);
                    usableActual = usableActual.subtract(multiply1).subtract(multiply);
                }
            }
            sellOrder.setExpectAmount(sellOrder.getActualAmount().add(sellOrder.getBalanceAmount()));
//            sellOrder.setSellCost2(JSONObject.toJSONString(costMap));
            if (SellTypeEnum.ACCESSORIES.getCode().equals(goodsSellDto.getGoodsType()) || SellTypeEnum.INSTRUMENT.getCode().equals(goodsSellDto.getGoodsType())) {
                sellOrder.setType(SellTypeEnum.valueOf(goodsSellDto.getGoodsType()));
            } else {
                sellOrder.setType(SellTypeEnum.OTHER);
            }
            sellOrder.setGoodsId(sellOrder.getGoodsId());
            sellOrder.setGoodsName(goodsSellDto.getGoodsName());
            sellOrder.setUserId(studentGoodsSell.getUserId());
            sellOrder.setPaymentChannel(orderByOrderNo.getPaymentChannel());
            sellOrder.setMerNo(orderByOrderNo.getMerNos());
            sellOrder.setSellTime(orderByOrderNo.getPayTime());
            sellOrder.setEduTeacherId(studentGoodsSell.getTeacherId());
            sellOrder.setCooperationOrganId(studentGoodsSell.getCooperationOrganId());
        }
        if (sellOrderList.size() > 0) {
            sellOrderService.batchInsert(sellOrderList);
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Boolean orderCallback(StudentPaymentOrder studentPaymentOrder) {
        Date nowDate = new Date();
        //更新订单信息
        studentPaymentOrder.setUpdateTime(nowDate);
        int updateCount = studentPaymentOrderService.update(studentPaymentOrder);
        if (updateCount <= 0) {
            throw new BizException("订单更新失败");
        }
        //更新维修单信息
        StudentRepair repairInfo = getRepairInfo(Integer.parseInt(studentPaymentOrder.getMusicGroupId()));
        if (repairInfo == null) {
            throw new BizException("维修单不存在");
        }
        if (repairInfo.getPayStatus().equals(2)) {
            return true;
        }

        Integer userId = studentPaymentOrder.getUserId();

        Map<Integer, String> map = new HashMap<>();
        map.put(userId, userId.toString());

        if (studentPaymentOrder.getStatus() == DealStatusEnum.SUCCESS) {
            try {
                contractService.transferProduceContract(userId, null);
            } catch (Exception e) {
                logger.error("产品协议生成失败", e);
            }

            repairInfo.setPayStatus(2);
            repairInfo.setUpdateTime(nowDate);
            if (this.update(repairInfo) <= 0) {
                throw new BizException("维修单更新失败");
            }

            //插入交易明细
            BigDecimal amount = studentPaymentOrder.getActualAmount();
            SysUserCashAccount cashAccount = sysUserCashAccountService.get(userId);
            //充值
            SysUserCashAccountDetail rechargeDetail = new SysUserCashAccountDetail();
            rechargeDetail.setAmount(amount);
            rechargeDetail.setBalance(cashAccount.getBalance().add(amount));
            rechargeDetail.setComment("缴费前充值");
            rechargeDetail.setCreateTime(nowDate);
            rechargeDetail.setStatus(DealStatusEnum.SUCCESS);
            rechargeDetail.setTransNo(studentPaymentOrder.getTransNo());
            rechargeDetail.setType(PlatformCashAccountDetailTypeEnum.RECHARGE);
            rechargeDetail.setUpdateTime(nowDate);
            rechargeDetail.setUserId(userId);
            rechargeDetail.setChannel(studentPaymentOrder.getPaymentChannel());
            rechargeDetail.setComAmount(studentPaymentOrder.getComAmount());
            rechargeDetail.setPerAmount(studentPaymentOrder.getPerAmount());
            sysUserCashAccountDetailService.insert(rechargeDetail);

            //缴费
            SysUserCashAccountDetail paymentDetail = new SysUserCashAccountDetail();
            paymentDetail.setAmount(amount.negate());
            paymentDetail.setBalance(cashAccount.getBalance());
            paymentDetail.setComment("乐器维修");
            paymentDetail.setCreateTime(nowDate);
            paymentDetail.setStatus(DealStatusEnum.SUCCESS);
            paymentDetail.setTransNo(studentPaymentOrder.getTransNo());
            paymentDetail.setType(PlatformCashAccountDetailTypeEnum.PAY_FEE);
            paymentDetail.setUpdateTime(nowDate);
            paymentDetail.setUserId(userId);
            rechargeDetail.setChannel(studentPaymentOrder.getPaymentChannel());
            if (studentPaymentOrder.getComAmount() != null) {
                rechargeDetail.setComAmount(studentPaymentOrder.getComAmount().negate());
                rechargeDetail.setPerAmount(studentPaymentOrder.getPerAmount().negate());
            }
            sysUserCashAccountDetailService.insert(paymentDetail);
            //生成销售订单
            if (StringUtils.isNotBlank(repairInfo.getGoodsJson())) {
                List<Goods> goods = JSONObject.parseArray(repairInfo.getGoodsJson(), Goods.class);
                List<Integer> goodsIds = goods.stream().map(Goods::getId).collect(Collectors.toList());
                if (goodsIds.size() > 0) {
                    sellOrderService.addSellOrder(studentPaymentOrder.getId(), null, goodsIds, studentPaymentOrder.getExpectAmount(), studentPaymentOrder.getBalancePaymentAmount());
                }
            }

            String imContent = repairInfo.getStudentName() + "学员您好，您的乐器维修已受理，我们会尽快完成保养维修";

            if (repairInfo.getType().equals(1)) { //线上
                imContent = repairInfo.getStudentName() + "学员您好，请尽快寄送乐器至维修点，我们会尽快完成保养维修\n" +
                        "联系人：" + repairInfo.getEmployeeName() + "（" + repairInfo.getEmployeePhone() + "）\n" +
                        "地址：" + repairInfo.getEmployeeAddress() + "";

                sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.SMS_REPAIR_ONLINE_PAYMENT_SUCCESS, map, null, 0, "1", "STUDENT",
                        repairInfo.getStudentName(), repairInfo.getEmployeeName(), repairInfo.getEmployeePhone(), repairInfo.getEmployeeAddress());
            } else {
                sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.SMS_REPAIR_OFFLINE_PAYMENT_SUCCESS, map, null, 0, "1", "STUDENT",
                        repairInfo.getStudentName());
            }
            sysMessageService.sendNoAuthPrivateMessage(repairInfo.getEmployeeId().toString(), userId.toString(), imContent);
            return true;
        }

        if (studentPaymentOrder.getStatus() == DealStatusEnum.CLOSE || studentPaymentOrder.getStatus() == DealStatusEnum.FAILED) {
            repairInfo.setPayStatus(0);
            repairInfo.setUpdateTime(nowDate);
            if (this.update(repairInfo) <= 0) {
                throw new BizException("维修单更新失败");
            }
            if (studentPaymentOrder.getBalancePaymentAmount() != null && studentPaymentOrder.getBalancePaymentAmount().compareTo(BigDecimal.ZERO) > 0) {
                sysUserCashAccountService.updateBalance(studentPaymentOrder.getUserId(), studentPaymentOrder.getBalancePaymentAmount(), PlatformCashAccountDetailTypeEnum.REFUNDS, "乐器维修支付失败");
            }

            sysMessageService.batchSendMessage(MessageSenderPluginContext.MessageSender.JIGUANG, MessageTypeEnum.SMS_SPORADIC_PAYMENT_FAILED, map, null, 0, "", "STUDENT",
                    studentPaymentOrder.getActualAmount(), "乐器维修");
            return false;
        }
        return false;
    }

}
