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

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
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.*;
import com.ym.mec.biz.dal.entity.*;
import com.ym.mec.biz.dal.enums.*;
import com.ym.mec.biz.dal.page.SporadicOrderQueryInfo;
import com.ym.mec.biz.dal.page.StudentPaymentOrderQueryInfo;
import com.ym.mec.biz.dal.vo.StudentPaymentOrderVo;
import com.ym.mec.biz.service.*;
import com.ym.mec.common.controller.BaseController;
import com.ym.mec.common.dal.BaseDAO;
import com.ym.mec.common.entity.HttpResponseResult;
import com.ym.mec.common.entity.MallCreateOrderModel;
import com.ym.mec.common.entity.OrderCancelModel;
import com.ym.mec.common.exception.BizException;
import com.ym.mec.common.page.PageInfo;
import com.ym.mec.common.page.PageUtil;
import com.ym.mec.common.page.WrapperUtil;
import com.ym.mec.common.service.IdGeneratorService;
import com.ym.mec.common.service.impl.BaseServiceImpl;
import com.ym.mec.common.tenant.TenantContextHolder;
import com.ym.mec.thirdparty.adapay.ConfigInit;
import com.ym.mec.thirdparty.adapay.Payment;
import com.ym.mec.thirdparty.adapay.entity.HfMerchantConfig;
import com.ym.mec.thirdparty.yqpay.*;
import com.ym.mec.util.collection.MapUtil;
import com.ym.mec.util.date.DateUtil;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

import static com.ym.mec.biz.dal.enums.DealStatusEnum.CLOSE;

@Service
public class StudentPaymentOrderServiceImpl extends BaseServiceImpl<Long, StudentPaymentOrder> implements StudentPaymentOrderService {

    @Autowired
    private StudentPaymentOrderDao studentPaymentOrderDao;
    @Autowired
    private YqPayFeignService yqPayFeignService;
    @Autowired
    private StudentRegistrationService studentRegistrationService;
    @Autowired
    @Lazy
    private VipGroupService vipGroupService;
    @Autowired
    private MusicGroupService musicGroupService;
    @Autowired
    private SporadicChargeInfoService sporadicChargeInfoService;
    @Autowired
    private PracticeGroupService practiceGroupService;
    @Autowired
    private SysUserCashAccountDao sysUserCashAccountDao;
    @Autowired
    private StudentRepairService studentRepairService;
    @Autowired
    private SysUserCashAccountService sysUserCashAccountService;
    @Autowired
    private SubjectChangeService subjectChangeService;
    @Autowired
    private DegreeRegistrationService degreeRegistrationService;
    @Autowired
    private StudentPaymentRouteOrderDao studentPaymentRouteOrderDao;
    @Autowired
    private StudentPaymentOrderDetailService studentPaymentOrderDetailService;
    @Autowired
    private IdGeneratorService idGeneratorService;
    @Autowired
    private SysConfigDao sysConfigDao;
    @Autowired
    private GoodsDao goodsDao;
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private StudentInstrumentService studentInstrumentService;
    @Autowired
    private ReplacementInstrumentActivityService replacementInstrumentActivityService;
    @Autowired
    private ChildrenDayReserveService childrenDayReserveService;
    @Autowired
    private MemberRankSettingService memberRankSettingService;
    @Autowired
    private PayService payService;
    @Autowired
    private StudentPaymentRouteOrderService studentPaymentRouteOrderService;
    @Autowired
    private CloudTeacherOrderService cloudTeacherOrderService;
    @Autowired
    private SysCouponCodeService sysCouponCodeService;
    @Autowired
    private VipGroupActivityDao vipGroupActivityDao;
    @Autowired
    private ActivityUserMapperService activityUserMapperService;
    @Autowired
    private MusicGroupSubjectPlanService musicGroupSubjectPlanService;
    @Autowired
    private SysUserFeignService sysUserFeignService;
    @Autowired
    private TenantConfigService tenantConfigService;
    @Autowired
    private GoodsProcurementDao goodsProcurementDao;
    @Autowired
    private ContractService contractService;
    @Autowired
    private HfMerchantConfigService hfMerchantConfigService;
    @Autowired
    private StudentDao studentDao;
    @Autowired
    private StudentPaymentOrderService studentPaymentOrderService;


    @Autowired
    private SysUserCashAccountDetailService sysUserCashAccountDetailService;
    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    @Override
    public BaseDAO<Long, StudentPaymentOrder> getDAO() {
        return studentPaymentOrderDao;
    }

    private final static Logger LOGGER = LoggerFactory.getLogger(StudentPaymentOrderServiceImpl.class);

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Map createOrder(StudentPaymentOrder studentPaymentOrder, List<StudentPaymentOrderDetail> details, String payReceiver) throws Exception {

        BigDecimal cashAmount = studentPaymentOrder.getActualAmount();
        BigDecimal expectAmount = studentPaymentOrder.getExpectAmount();
        BigDecimal balance = studentPaymentOrder.getBalancePaymentAmount();

        if (cashAmount.add(balance).compareTo(expectAmount) != 0) {
            throw new BizException("支付金额不正确，请重试");
        }

        Date date = new Date();
        studentPaymentOrder.setUpdateTime(date);

        StudentPaymentOrder orignStudentPaymentOrder = get(studentPaymentOrder.getId());
        if (orignStudentPaymentOrder == null) {

            String orderNo = idGeneratorService.generatorId("payment") + "";
            studentPaymentOrder.setOrderNo(orderNo);
            studentPaymentOrder.setCreateTime(date);
            studentPaymentOrder.setUpdateTime(date);
            studentPaymentOrder.setVersion(0);
            insert(studentPaymentOrder);
        }

        if (CollectionUtils.isNotEmpty(details)) {
            for (StudentPaymentOrderDetail spod : details) {
                spod.setPaymentOrderId(studentPaymentOrder.getId());
                spod.setCreateTime(date);
                spod.setUpdateTime(date);
            }

            studentPaymentOrderDetailService.allocateAndAdd(details, studentPaymentOrder.getCouponRemitFee());
        }

        String baseApiUrl = sysConfigDao.findConfigValue("base_api_url");

        if (cashAmount.compareTo(BigDecimal.ZERO) == 0) {

            studentPaymentRouteOrderService.addRouteOrder(studentPaymentOrder.getOrderNo(), studentPaymentOrder.getOrganId(), balance);

            Map<String, String> notifyMap = new HashMap<>(4);
            notifyMap.put("tradeState", "1");
            notifyMap.put("merOrderNo", studentPaymentOrder.getOrderNo());
            notifyMap.put("channelType", "");
            notifyMap.put("orderNo", "");
            updateOrder(notifyMap);
            return notifyMap;
        }

        Map<String, Object> payMap = payService.getPayMap(cashAmount, balance, studentPaymentOrder.getOrderNo(), baseApiUrl + "/api-student/studentOrder/callback", baseApiUrl
                + "/api-student/studentOrder/paymentResult?orderNo=" + studentPaymentOrder.getOrderNo(), studentPaymentOrder.getMemo(), studentPaymentOrder.getMemo(), studentPaymentOrder.getOrganId(), payReceiver);

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

    @Override
    public List<StudentPaymentOrder> queryByCondition(GroupType groupType, String musicGroupId, Integer userId, DealStatusEnum status, OrderTypeEnum type) {
        return studentPaymentOrderDao.queryByCondition(groupType, musicGroupId, userId, status, type);
    }

    @Override
    public List<StudentPaymentOrder> findMusicGroupApplyOrderByStatus(Integer userId, String musicGroupId, DealStatusEnum status) {
        return studentPaymentOrderDao.findMusicGroupApplyOrderByStatus(userId, musicGroupId, status);
    }

    @Override
    public StudentPaymentOrder findOrderByOrderNo(String orderNo) {
        return studentPaymentOrderDao.findOrderByOrderNo(orderNo);
    }

    @Override
    public List<StudentPaymentOrder> queryByBatchNo(Integer userId, String batchNo, DealStatusEnum status) {
        return studentPaymentOrderDao.queryByBatchNo(userId, batchNo, status);
    }

    @Override
    public List<StudentPaymentOrder> findOrdersByStatus(DealStatusEnum status, String paymentChannel) {
        return studentPaymentOrderDao.findOrdersByStatus(status, paymentChannel);
    }

    @Override
    public List<StudentPaymentOrder> findOrdersOverTime(List<String> orderNoList, DealStatusEnum status, Date beforeTime) {
        return studentPaymentOrderDao.findOrdersOverTime(orderNoList, status, beforeTime);
    }

    @Override
    public void queryOrderStatus() throws Exception {
        yqPayQuery(null);
        adaPayQuery(null);
        reConfirmOrder(null, null);
    }

    private void yqPayQuery(List<StudentPaymentOrder> payingOrders) throws Exception {
        if (payingOrders == null) {
            payingOrders = findOrdersByStatus(DealStatusEnum.ING, "YQPAY");
        }
        if (payingOrders.size() == 0) {
            return;
        }
        List<String> orderNoList = payingOrders.stream().map(StudentPaymentOrder::getOrderNo).collect(Collectors.toList());
        String merOrderNos = payingOrders.stream().map(StudentPaymentOrder::getOrderNo).collect(Collectors.joining(","));

        String notifyUrl = ""; //回调地址
        Map<String, Object> resultMap = new LinkedHashMap<>();
        resultMap.put("merOrderNoList", merOrderNos);
        Map<String, Object> requestMap = YqPayUtil.getRequestMap(notifyUrl, resultMap);

        RsqMsg rsqMsg = new RsqMsg(requestMap);

        Msg queryRs = yqPayFeignService.orderQuery(rsqMsg);

        if (queryRs.getCode().equals("88")) {
            //更新订单状态
            String[] statusArr = {"0", "1", "7"};
            String responseParameters = queryRs.getResponseParameters();
            List<Map<String, String>> responseList = JSON.parseObject(responseParameters, List.class);
            for (Map<String, String> response : responseList) {
                Map<String, String> rpMap = response;
                String channelType = rpMap.get("channelType").equals("1") ? "WXPay" : (rpMap.get("channelType").equals("2") ? "Alipay" : "quickPay");
                rpMap.put("channelType", channelType);

                if (orderNoList.contains(rpMap.get("merOrderNo"))) {
                    orderNoList.remove(rpMap.get("merOrderNo"));
                }

                if (Arrays.asList(statusArr).contains(rpMap.get("tradeState"))) {
                    try {
                        updateOrder(rpMap); //更新订单
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    continue;
                }
            }
            closeOrders(orderNoList); //关闭订单
        }
    }

    private void adaPayQuery(List<StudentPaymentOrder> payingOrders) throws Exception {
        if (payingOrders == null) {
            payingOrders = findOrdersByStatus(DealStatusEnum.ING, "ADAPAY");
        }

        Date date = new Date();

        if (payingOrders.size() == 0) {
            return;
        }
        
        Map<Integer,HfMerchantConfig> payConfigMap = new HashMap<Integer, HfMerchantConfig>();
        HfMerchantConfig hfMerchantConfig = null;
        
        List<String> orderNoList = new ArrayList<String>();

        for (StudentPaymentOrder payingOrder : payingOrders) {
            //if (payingOrder.getTransNo() == null && "205".equals(payingOrder.getPaymentAccountNo()) && DateUtil.isSameDay(payingOrder.getCreateTime(), new Date())) {
            if (payingOrder.getTransNo() == null && "205".equals(payingOrder.getPaymentAccountNo())) {
                continue;
            }
            if (payingOrder.getTransNo() == null) {
                orderNoList.add(payingOrder.getOrderNo());
                continue;
            }
            //查询支付超过10分钟的
            if (DateUtil.minutesBetween(payingOrder.getCreateTime(), date) < 10) {
                continue;
            }

            updateOrderStatus(date, payConfigMap, payingOrder,true);
        }
        closeOrders(orderNoList);
    }

    @Override
    @Transactional
    public OrderCancelModel updateOrderStatus(Date date, Map<Integer, HfMerchantConfig> payConfigMap, StudentPaymentOrder payingOrder, Boolean checkTime) throws Exception {
        if (payConfigMap == null) {
            throw new BizException("payConfigMap 不能为空");
        }
        HfMerchantConfig hfMerchantConfig;
        hfMerchantConfig = payConfigMap.get(payingOrder.getTenantId());
        if(hfMerchantConfig == null){
            hfMerchantConfig = hfMerchantConfigService.queryByTenantId(payingOrder.getTenantId());
            if(hfMerchantConfig == null){
                throw new BizException("机构[{}]汇付商户信息找不到", payingOrder.getTenantId());
            }
            payConfigMap.put(payingOrder.getTenantId(), hfMerchantConfig);
        }
        OrderCancelModel  model = new OrderCancelModel();

        Map<String, Object> payment = Payment.queryPayment(payingOrder.getTransNo(), hfMerchantConfig.getMerKey());
        LOGGER.info("订单[{}]交易主动查询接口返回：{}", payingOrder.getTransNo(), payment);

        Map<String, String> rpMap = new HashMap<>();
        rpMap.put("merOrderNo", payingOrder.getOrderNo());
        rpMap.put("orderNo", payingOrder.getTransNo());
        rpMap.put("channelType", (String) payment.get("pay_channel"));
        model.setPayChannel((String) payment.get("pay_channel"));
        String status = (String) payment.get("status");
        if (payment.containsKey("error_msg")) {
            rpMap.put("remarks", (String) payment.get("error_msg"));
        }
        if (status.equals("succeeded")) {
            rpMap.put("tradeState", "1");
            model.setStatus(true);
        } else if (status.equals("failed") || !checkTime
                || (DateUtil.minutesBetween(DateUtil.addHours(payingOrder.getUpdateTime(), 2),date) > 0)) {
            rpMap.put("tradeState", "0");
            model.setStatus(false);
        }

        if (status.equals("succeeded") ||
                (status.equals("failed") || !checkTime || payingOrder.getCreateTime().before(DateUtil.addMinutes(new Date(), -35)))) {
            try {
                updateOrder(rpMap); //更新订单
                model.setSuccess(true);
            } catch (Exception e) {
                e.printStackTrace();
                model.setSuccess(false);
                return model;
            }
        }
        return model;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void quitCouponAndBalance(StudentPaymentOrder order) {
        //增加用户余额
        if (order.getBalancePaymentAmount().compareTo(BigDecimal.ZERO) > 0) {
            sysUserCashAccountService.updateBalance(order.getUserId(), order.getBalancePaymentAmount(),
                    PlatformCashAccountDetailTypeEnum.REFUNDS, order.getMemo() + ",订单号:" + order.getOrderNo());
        }
        //退还优惠券
        sysCouponCodeService.quit(order.getCouponCodeId());
    }

    @Transactional(rollbackFor = Exception.class)
    public void updateOrder(Map<String, String> rpMap) throws Exception {
        DealStatusEnum status = rpMap.get("tradeState").equals("1") ? DealStatusEnum.SUCCESS : DealStatusEnum.FAILED;
        StudentPaymentOrder order = findOrderByOrderNo(rpMap.get("merOrderNo"));
        order = studentPaymentOrderDao.lockOrder(order.getId());
        //关闭或失败的订单查询订单成功,订单改成成功，钱退到余额
        if (order != null && (order.getStatus().equals(DealStatusEnum.CLOSE) || order.getStatus().equals(DealStatusEnum.FAILED)) && status.equals(DealStatusEnum.SUCCESS)) {
            String memo = order.getStatus().equals(DealStatusEnum.CLOSE) ? "关闭订单" : "失败订单";
            memo = memo + ",实际支付成功,退到用户余额";
            //更新订单状态
            order.setStatus(status);
            order.setTransNo(rpMap.get("orderNo"));
            order.setPaymentBusinessChannel(rpMap.get("channelType"));
            order.setPayTime(new Date());
            order.setMemo(memo);
            int updateCount = this.update(order);
            if (updateCount <= 0) {
                throw new BizException("订单更新失败");
            }
            sysUserCashAccountService.updateBalance(order.getUserId(), order.getActualAmount(),
                    PlatformCashAccountDetailTypeEnum.REFUNDS, order.getMemo() + ",订单号:" + order.getOrderNo());

            if (StringUtils.isNotBlank(order.getPaymentChannel())
                    && order.getPaymentChannel().equals("ADAPAY")
                    && !rpMap.containsKey("simulation")) {
                confirmOrder(order);
            }
            return;
        }

        if (order == null || !order.getStatus().equals(DealStatusEnum.ING)) {
            return;
        }

        if (status.equals(DealStatusEnum.SUCCESS)) {
            order.setPayTime(new Date());
        } else {
            order.setMemo(rpMap.get("remarks"));
        }
        order.setStatus(status);
        if (StringUtils.isBlank(order.getTransNo())) {
            order.setTransNo(rpMap.get("orderNo"));
        }

        order.setPaymentBusinessChannel(rpMap.get("channelType"));
        order.setTenantId(this.get(order.getId()).getTenantId());
        TenantContextHolder.setTenantId(order.getTenantId());
        callOrderCallBack(order);

        if (status.equals(DealStatusEnum.SUCCESS)
                && StringUtils.isNotBlank(order.getPaymentChannel())
                && order.getPaymentChannel().equals("ADAPAY")
                && !rpMap.containsKey("simulation")) {
            confirmOrder(order);
        }
        TenantContextHolder.clearTenantId();
    }

    private Boolean confirmOrder(StudentPaymentOrder order) {
        // 只有大雅延迟分账，其他实时分账
        if (order.getTenantId() != 1) {
            return true;
        }
        Date date = new Date();
        
        HfMerchantConfig hfMerchantConfig = null;
        
        List<StudentPaymentRouteOrder> routeOrders = studentPaymentRouteOrderDao.getRouteOrders(order.getOrderNo());
        for (StudentPaymentRouteOrder routeOrder : routeOrders) {
        	if(hfMerchantConfig == null){
        		hfMerchantConfig = hfMerchantConfigService.queryByTenantId(routeOrder.getTenantId());
        	}
            if(hfMerchantConfig == null){
            	throw new BizException("机构[{}]汇付商户信息找不到", routeOrder.getTenantId());
            }
            
            Map<String, Object> divMember = new HashMap<>();
            divMember.put("member_id", routeOrder.getMerNo());//分佣账户
            divMember.put("amount", routeOrder.getRouteAmount().setScale(2, BigDecimal.ROUND_HALF_UP));//分佣金额
            divMember.put("fee_flag", "Y");
            if (routeOrder.getMerNo().equals(ConfigInit.merNo)) {
                divMember.put("member_id", 0);
            }
            List<Map<String, Object>> divMembers = new ArrayList<>();
            divMembers.add(divMember);

            Map<String, Object> confirm = new HashMap<>();
            confirm.put("payment_id", order.getTransNo());
            confirm.put("order_no", idGeneratorService.generatorId("payment"));
            confirm.put("confirm_amt", routeOrder.getRouteAmount());
            confirm.put("div_members", divMembers);
            try {
                Map<String, Object> map = Payment.createConfirm(confirm, hfMerchantConfig.getMerKey());
                LOGGER.info("分账信息返回：{}", map);
                routeOrder.setServiceFee(new BigDecimal(map.get("fee_amt").toString()));
                routeOrder.setUpdateTime(date);
                studentPaymentRouteOrderDao.update(routeOrder);
            } catch (Exception e) {
                continue;
            }
        }
        return true;
    }

    //Date date = new Date();
    //        BigDecimal balance = BigDecimal.ZERO;
    //        MusicGroup musicGroup = musicGroupDao.get(studentRegistration.getMusicGroupId());
    //        if (registerPayDto.getIsUseBalancePayment() && amount.compareTo(BigDecimal.ZERO) > 0) {
    //            SysUserCashAccount userCashAccount = sysUserCashAccountService.getLocked(userId);
    //            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.setPaymentChannel("BALANCE");
    //                studentPaymentOrder.setActualAmount(amount);
    //                studentPaymentOrder.setBalancePaymentAmount(balance);
    //                sysUserCashAccountService.updateBalance(userId, balance.negate(), PlatformCashAccountDetailTypeEnum.PAY_FEE, "乐团报名");
    //            }
    //        }
    //        studentPaymentOrder.setPaymentChannel("BALANCE");
    //        studentPaymentOrder.setRemitFee(remitFee);
    //        studentPaymentOrder.setCourseRemitFee(courseRemitFee);
    //        studentPaymentOrder.setOrganId(musicGroup.getOrganId());
    //        studentPaymentOrder.setRoutingOrganId(musicGroup.getOrganId());
    //        studentPaymentOrder.setUpdateTime(date);
    //        studentPaymentOrderService.update(studentPaymentOrder);
    //        studentPaymentOrder.setVersion(studentPaymentOrder.getVersion() + 1);
    //
    //        if (amount.compareTo(BigDecimal.ZERO) == 0) {
    //            //如果赠送网管课
    //            studentPaymentRouteOrderService.addRouteOrder(orderNo, musicGroup.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);
    //            return notifyMap;
    //        }

    //调用相应业务回调接口
    public void callOrderCallBack(StudentPaymentOrder order) throws Exception {
        if (order.getType().equals(OrderTypeEnum.APPLY)) { //报名订单
            studentRegistrationService.updateApplyOrder(order);
        } else if (order.getType().equals(OrderTypeEnum.SMALL_CLASS_TO_BUY)) {
            vipGroupService.orderCallback(order);
        } else if (order.getType().equals(OrderTypeEnum.RENEW) || order.getType().equals(OrderTypeEnum.ADD_STUDENT)) {
            musicGroupService.renewForCallback(order);
        } else if (order.getType().equals(OrderTypeEnum.SPORADIC) || order.getType().equals(OrderTypeEnum.LUCK) || order.getType().equals(OrderTypeEnum.DOUBLE_ELEVEN2020)) {
            sporadicChargeInfoService.renewForCallback(order);
        } else if (order.getType().equals(OrderTypeEnum.PRACTICE_GROUP_BUY) || order.getType().equals(OrderTypeEnum.PRACTICE_GROUP_RENEW)) {
            practiceGroupService.orderCallback(order);
        } else if (order.getType().equals(OrderTypeEnum.REPAIR)) {
            studentRepairService.orderCallback(order);
        } else if (order.getType().equals(OrderTypeEnum.GOODS_SELL)) {
            studentRepairService.goodsSellOrderCallback(order);
        } else if (order.getType().equals(OrderTypeEnum.SUBJECT_CHANGE)) {
            subjectChangeService.orderCallback(order);
        } else if (order.getType().equals(OrderTypeEnum.DEGREE_REGISTRATION)) {
            degreeRegistrationService.updateStatus(order);
        } else if (order.getType().equals(OrderTypeEnum.MAINTENANCE)) {
            studentInstrumentService.orderCallback(order);
        } else if (order.getType().equals(OrderTypeEnum.REPLACEMENT)) {
            replacementInstrumentActivityService.orderCallback(order);
        } else if (order.getType().equals(OrderTypeEnum.DEGREE)) {
            childrenDayReserveService.orderCallback(order);
        } else if (order.getType().equals(OrderTypeEnum.MEMBER)) {
            //购买团练宝
            memberRankSettingService.orderCallback(order);
        } else if (order.getType().equals(OrderTypeEnum.ACTIVITY)) {
            //购买活动
            practiceGroupService.activityOrderCallback(order);
        } else if (order.getType().equals(OrderTypeEnum.LIVE_BUY)) {
            //直播课购买回调
            memberRankSettingService.liveBuyOrderCallback(order);
        } else if (order.getType().equals(OrderTypeEnum.MALL_BUY)) {
            // 商城购买订单回调
            studentPaymentOrderService.mallBuyOrderCallback(order);
        }
    }

    private void closeOrders(List<String> orderNoList) throws Exception {
        if (orderNoList.size() == 0) {
            return;
        }

        Calendar beforeTime = Calendar.getInstance();
        beforeTime.add(Calendar.MINUTE, -35);// 30分钟之前的时间
        Date beforeDate = beforeTime.getTime();

        List<StudentPaymentOrder> ordersOverTime = findOrdersOverTime(orderNoList, DealStatusEnum.ING, beforeDate);
        for (StudentPaymentOrder order : ordersOverTime) {
            try {
                TenantContextHolder.setTenantId(order.getTenantId());
                order.setStatus(DealStatusEnum.FAILED);
                order.setMemo("超时未支付关闭");
                callOrderCallBack(order);
                TenantContextHolder.clearTenantId();
            } catch (Exception e) {
                e.printStackTrace();
                continue;
            }
        }

    }

    @Override
    public List<StudentPaymentOrderExportDto> ExportQueryPage(Map<String, Object> params) {
        return studentPaymentOrderDao.ExportQueryPage(params);
    }

    @Override
    public PageInfo<SporadicChargeInfoDto> sporadicQueryPage(SporadicOrderQueryInfo queryInfo) {
        PageInfo<SporadicChargeInfoDto> pageInfo = new PageInfo<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<>();
        MapUtil.populateMap(params, queryInfo);

        List<SporadicChargeInfoDto> dataList = null;
        int count = studentPaymentOrderDao.countSporadicPage(params);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = studentPaymentOrderDao.sporadicQueryPage(params);
        }
        if (count == 0) {
            dataList = new ArrayList<>();
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    public PageInfoOrder<StudentPaymentOrderDto> OrderQueryPage(StudentPaymentOrderQueryInfo queryInfo) {
        PageInfoOrder<StudentPaymentOrderDto> pageInfo = new PageInfoOrder<>(queryInfo.getPage(), queryInfo.getRows());
        Map<String, Object> params = new HashMap<String, Object>();
        MapUtil.populateMap(params, queryInfo);

        List<StudentPaymentOrderDto> dataList = new ArrayList<>();
        int count = this.findCount(params);

        BigDecimal totalUserBalance = sysUserCashAccountDao.getTotalUserBalance(params);
        pageInfo.setTotalUserBalance(totalUserBalance);
        if (count > 0) {
            pageInfo.setTotal(count);
            params.put("offset", pageInfo.getOffset());
            dataList = studentPaymentOrderDao.queryPageOrder(params);

            StudentPaymentOrder orderMoneyAmount = studentPaymentOrderDao.getOrderMoneyAmount(params);
            BigDecimal totalExpectAmount = orderMoneyAmount.getExpectAmount() != null ? orderMoneyAmount.getExpectAmount() : BigDecimal.ZERO;
            BigDecimal totalActualAmount = orderMoneyAmount.getActualAmount() != null ? orderMoneyAmount.getActualAmount() : BigDecimal.ZERO;
            BigDecimal totalBalancePaymentAmount = orderMoneyAmount.getBalancePaymentAmount() != null ? orderMoneyAmount.getBalancePaymentAmount() : BigDecimal.ZERO;

            params.put("chargeType", SporadicChargeTypeEnum.RECHARGE);
            BigDecimal totalChargeAmount = studentPaymentOrderDao.getChargeAmount(params);
            totalChargeAmount = totalChargeAmount != null ? totalChargeAmount : BigDecimal.ZERO;
            BigDecimal totalAdvanceAmount = totalChargeAmount.subtract(totalBalancePaymentAmount);

            pageInfo.setTotalAdvanceAmount(totalAdvanceAmount);
            pageInfo.setTotalExpectAmount(totalExpectAmount);
            pageInfo.setTotalActualAmount(totalActualAmount);
            pageInfo.setTotalRevenueAmount(totalActualAmount.subtract(totalAdvanceAmount));
        }
        pageInfo.setRows(dataList);
        return pageInfo;
    }

    @Override
    public Boolean getOrderStatus(Long id) throws Exception {
        StudentPaymentOrder studentPaymentOrder = studentPaymentOrderDao.get(id);
        List<StudentPaymentOrder> orderList = new ArrayList<>();
        orderList.add(studentPaymentOrder);
        if (studentPaymentOrder.getPaymentChannel().equals("ADAPAY")) {
            adaPayQuery(orderList);
        } else if (studentPaymentOrder.getPaymentChannel().equals("YQPAY")) {
            yqPayQuery(orderList);
        }
        return true;
    }

    @Override
    public Integer findOrganPayOrderNum(Integer organId) {
        return studentPaymentOrderDao.findOrganPayOrderNum(organId);
    }

    @Override
    public List<StudentPaymentOrder> getUserOrderByType(Integer userId, OrderTypeEnum type, DealStatusEnum status) {
        return studentPaymentOrderDao.getUserOrderByType(userId, type, status);
    }

    @Override
    public List<StudentPaymentOrder> reConfirmOrder(Date startTime, Date endTime) {
        if (startTime == null) {
            endTime = new Date();
            startTime = DateUtil.addMinutes(endTime, -20);
        }

        List<StudentPaymentOrder> orders = studentPaymentOrderDao.getAdaPayOrdersByTime(startTime, endTime);
        String tips = "";
        for (StudentPaymentOrder order : orders) {
            try {
                this.confirmOrder(order);
            } catch (Exception e) {
                tips += order.getOrderNo() + ":" + e.getMessage() + ",";
                continue;
            }
        }
        if (StringUtils.isNotBlank(tips)) {
            throw new BizException(tips);
        }
        return orders;
    }

    @Override
    public List<StudentPaymentOrderExportDto> getUserApplyOrders(Integer studentId, String musicGroupId) {
        List<StudentPaymentOrderExportDto> orders = studentPaymentOrderDao.getUserApplyOrders(studentId, musicGroupId);
        StudentRegistration studentRegister = studentRegistrationService.getStudentRegister(musicGroupId, studentId);
        for (StudentPaymentOrderExportDto order : orders) {
            if ((DealStatusEnum.ING.equals(order.getStatus()) || DealStatusEnum.SUCCESS.equals(order.getStatus())) &&
                    studentRegister.getPayingStatus().equals(2)) {
                order.setPayingStatus(2);
            }
            if (order.getOrderDetailList() == null) continue;
            for (StudentPaymentOrderDetail studentPaymentOrderDetail : order.getOrderDetailList()) {
                if (studentPaymentOrderDetail.getGoodsList() == null) continue;

                String childGoodIds = "";
                for (Goods goods : studentPaymentOrderDetail.getGoodsList()) {
                    if (StringUtils.isNotBlank(goods.getComplementGoodsIdList())) {
                        childGoodIds += StringUtils.isNotBlank(childGoodIds) ? "," : "" + goods.getComplementGoodsIdList();
                    }
                }
                if (StringUtils.isNotBlank(childGoodIds)) {
                    studentPaymentOrderDetail.setChildGoodsList(goodsDao.findGoodsByIds(childGoodIds));
                }
                if (studentPaymentOrderDetail.getType() == OrderDetailTypeEnum.CLOUD_TEACHER || studentPaymentOrderDetail.getType() == OrderDetailTypeEnum.CLOUD_TEACHER_PLUS) {
                    studentPaymentOrderDetail.setCloudTeacherOrderDto(cloudTeacherOrderService.queryOrderInfoByOrderId(studentPaymentOrderDetail.getPaymentOrderId()));
                }
            }
        }
        return orders;
    }

    @Override
    public StudentPaymentOrder getUserReplacementIngOrder(Integer userId, Integer replacementId) {
        return studentPaymentOrderDao.getUserReplacementIngOrder(userId, replacementId);
    }

    @Override
    public int batchUpdate(List<StudentPaymentOrder> studentPaymentOrderList) {
        return studentPaymentOrderDao.batchUpdate(studentPaymentOrderList);
    }

    @Override
    public PayStatus queryPayStatus(StudentPaymentOrder studentPaymentOrder) throws Exception {
    	
    	String paymentChannel = studentPaymentOrder.getPaymentChannel();
    	String orderNo = studentPaymentOrder.getOrderNo();
    	String transNo = studentPaymentOrder.getTransNo();
    	
        if (StringUtils.isBlank(transNo)) {
            return PayStatus.FAILED;
        }
        if (StringUtils.equals(paymentChannel, "ADAPAY")) {
        	HfMerchantConfig hfMerchantConfig = hfMerchantConfigService.queryByTenantId(studentPaymentOrder.getTenantId());
            if(hfMerchantConfig == null){
            	throw new BizException("机构[{}]汇付商户信息找不到", studentPaymentOrder.getTenantId());
            }
            Map<String, Object> payment = Payment.queryPayment(transNo, hfMerchantConfig.getMerKey());
            String status = (String) payment.get("status");
            if (status.equals("succeeded")) {
                return PayStatus.SUCCESSED;
            } else if (status.equals("failed")) {
                return PayStatus.FAILED;
            } else {
                return PayStatus.PAYING;
            }
        } else if (StringUtils.equals(paymentChannel, "YQPAY")) {
            String notifyUrl = ""; // 回调地址
            Map<String, Object> resultMap = new LinkedHashMap<>();
            resultMap.put("merOrderNoList", orderNo);
            Map<String, Object> requestMap = YqPayUtil.getRequestMap(notifyUrl, resultMap);

            RsqMsg rsqMsg = new RsqMsg(requestMap);

            Msg queryRs = yqPayFeignService.orderQuery(rsqMsg);

            if (queryRs.getCode().equals("88")) {
                // 更新订单状态
                String responseParameters = queryRs.getResponseParameters();
                List<Map<String, String>> responseList = JSON.parseObject(responseParameters, List.class);
                for (Map<String, String> response : responseList) {

                    if (StringUtils.equals(response.get("tradeState"), "1")) {
                        return PayStatus.SUCCESSED;
                    } else if (StringUtils.equals(response.get("tradeState"), "0") || StringUtils.equals(response.get("tradeState"), "7")) {
                        return PayStatus.FAILED;
                    } else {
                        return PayStatus.PAYING;
                    }
                }
            }
        }
        throw new BizException("支付渠道错误");
    }

    @Override
    public Integer getOrderIdByMusical(String musicGroupId, Integer studentId) {
        return studentPaymentOrderDao.getOrderIdByMusical(musicGroupId, studentId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer activityGive(Integer vipGroupActivityId, StudentPaymentOrder studentPaymentOrder, String vipGroupId, String practiceGroupId, Integer teacherId) {
        Integer activityUserMapperId = null;
        if (vipGroupActivityId != null) {
            VipGroupActivity activity = vipGroupActivityDao.get(vipGroupActivityId);
            ActivityUserMapper activityUserMapper = new ActivityUserMapper();
            activityUserMapper.setVipGroupId(vipGroupId);
            activityUserMapper.setPracticeGroupId(practiceGroupId);
            activityUserMapper.setPaymentOrderId(studentPaymentOrder.getId());
            activityUserMapper.setUserId(studentPaymentOrder.getUserId());
            activityUserMapper.setActivityId(vipGroupActivityId);
            activityUserMapper.setTeacherId(teacherId);
            activityUserMapper.setActualPrice(studentPaymentOrder.getExpectAmount());
            if (vipGroupId != null) {
                activityUserMapper.setVipFlag(2);
            } else {
                activityUserMapper.setPracticeFlag(2);
            }
            activityUserMapperService.copyProperty(activityUserMapper,activity,false,true);
            activityUserMapper.setSubCourseNum(0);
            //是否达到满赠标准
            if (activity.getFullMinusCourseTimes() == -1 || studentPaymentOrder.getActivityBuyNum() < activity.getFullMinusCourseTimes()) {
                activityUserMapperService.insert(activityUserMapper);
                return activityUserMapper.getId();
            }
            //是否赠送课程
            if (activity.getGiveCourseNum() > 0) {
                if (activity.getGiveCourseType().equals("VIP")) {
                    activityUserMapper.setGiveVipFlag(1);
                } else {
                    activityUserMapper.setGivePracticeFlag(1);
                }
                activityUserMapperService.copyProperty(activityUserMapper,activity,true,false);
            }
            //是否赠送优惠券
            if (activity.getGiveCouponNum() != null && activity.getGiveCouponNum() > 0) {
                activityUserMapper.setGiveCouponId(activity.getGiveCouponId());
            }
            //是否赠送会员(会员立即生效)
            if (activity.getGiveMemberTime() > 0) {
                Date now = new Date();
                // 查询会员订单信息
                CloudTeacherOrder cloudTeacherOrder = new CloudTeacherOrder();
                cloudTeacherOrder.setStatus(1);
                cloudTeacherOrder.setUpdateTime(now);
                cloudTeacherOrder.setAmount(BigDecimal.ZERO);
                cloudTeacherOrder.setOrderId(studentPaymentOrder.getId());
                cloudTeacherOrder.setRemark("购买vip活动赠送会员");
                cloudTeacherOrder.setLevel(activity.getGiveMemberRankId());
                cloudTeacherOrder.setStudentId(studentPaymentOrder.getUserId());
                cloudTeacherOrder.setType(activity.getGivePeriodEnum());
                cloudTeacherOrder.setOrganId(studentPaymentOrder.getOrganId());
                cloudTeacherOrder.setTime(activity.getGiveMemberTime());
                cloudTeacherOrderService.save(cloudTeacherOrder,tenantConfigService.autoActivationFlag(cloudTeacherOrder.getTenantId()));
                // 添加会员有效时长
                activityUserMapper.setGiveMemberFlag(2);
                activityUserMapper.setGiveMemberOrderId(cloudTeacherOrder.getId());
            }
            activityUserMapperService.insert(activityUserMapper);
            activityUserMapperId = activityUserMapper.getId();
        }
        return activityUserMapperId;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public HttpResponseResult checkRepeatPay(StudentPaymentOrder order, Boolean repeatPay) throws Exception {
        // 查询订单状态
        PayStatus payStatus = this.queryPayStatus(order);
        if (payStatus == PayStatus.SUCCESSED) {
            throw new BizException("订单已支付成功，请勿重复支付");
        }
        if (!repeatPay) {
            return BaseController.failed(HttpStatus.CONTINUE, "您有待支付的订单,是否继续支付");
        }
        //处理关闭订单
        order.setStatus(DealStatusEnum.CLOSE);
        order.setMemo("关闭订单");

        
        Date nowDate = new Date();
        //增加商品库存
        List<StudentPaymentOrderDetail> studentPaymentOrderDetailList = studentPaymentOrderDetailService.queryOrderDetail(order.getId());
        String goodsIds = studentPaymentOrderDetailList.stream().filter(t -> StringUtils.isNotBlank(t.getMinuendStockGoodsIdList())).map(t -> t.getMinuendStockGoodsIdList()).collect(Collectors.joining(","));
        if(StringUtils.isNotBlank(goodsIds)){
        	GoodsProcurement goodsProcurement = null;
        	List<Goods> goodsList = goodsService.getGoodsWithLocked(goodsIds);
        	Map<Integer,Goods> goodsMap = goodsList.stream().collect(Collectors.toMap(Goods :: getId, t -> t));
        	Goods goods = null;
			Map<Integer, Goods> batchUpdateGoodsMap = new HashMap<Integer, Goods>();
			Map<Long, GoodsProcurement> goodsProcurementMap = new HashMap<Long, GoodsProcurement>();
        	
        	for(String goodsIdStr : goodsIds.split(",")){
        		if(StringUtils.isBlank(goodsIdStr)){
					continue;
				}
				goods = goodsMap.get(Integer.parseInt(goodsIdStr));
				if(batchUpdateGoodsMap.get(goods.getId()) != null){
					goods = batchUpdateGoodsMap.get(goods.getId());
				}
				goods.setStockCount(new AtomicInteger(goods.getStockCount()).incrementAndGet());
				goods.setSellCount(new AtomicInteger(goods.getSellCount()).decrementAndGet());
				goods.setUpdateTime(nowDate);
				
				batchUpdateGoodsMap.put(goods.getId(), goods);
				
				// 进货清单
				goodsProcurement = goodsProcurementDao.getWithStockSurplusProcurement(goods.getId());
				if(goodsProcurement != null){
					if(goodsProcurementMap.get(goodsProcurement.getId()) != null){
						goodsProcurement = goodsProcurementMap.get(goodsProcurement.getId());
					}
					goodsProcurement.setStockSoldNum(new AtomicInteger(goodsProcurement.getStockSoldNum()).decrementAndGet());
					goodsProcurement.setUpdateTime(nowDate);
					goodsProcurementMap.put(goodsProcurement.getId(), goodsProcurement);
				}
				
        	}
        	
        	if(goodsProcurementMap.size() > 0){
        		goodsProcurementDao.batchUpdate(new ArrayList<GoodsProcurement>(goodsProcurementMap.values()));
        	}
            
            if(batchUpdateGoodsMap.size() > 0){
            	goodsService.batchUpdate(new ArrayList<Goods>(batchUpdateGoodsMap.values()));
            }
        }
        
        //如果是报名订单，订单关闭时需要更改已缴费学员数
        cutSubjectPlan(order);
        if (order.getBalancePaymentAmount() != null && order.getBalancePaymentAmount().compareTo(BigDecimal.ZERO) > 0) {
            sysUserCashAccountService.updateBalance(order.getUserId(), order.getBalancePaymentAmount(),
                    PlatformCashAccountDetailTypeEnum.REFUNDS, "订单主动关闭退费");
        }
        studentPaymentOrderDao.update(order);
        sysCouponCodeService.quit(order.getCouponCodeId());
        return BaseController.succeed();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void cutSubjectPlan(StudentPaymentOrder order) {
        if (order.getType() == OrderTypeEnum.APPLY) {
            //如果是报名订单，订单关闭时需要更改已缴费学员数
            String musicGroupId = order.getMusicGroupId();
            Integer userId = order.getUserId();
            StudentRegistration studentRegistration = studentRegistrationService.getStudentRegister(musicGroupId, userId);
            //获取学员在乐团的状态，如果是在读，那么不处理人数
            if (studentRegistration.getMusicGroupStatus() == StudentMusicGroupStatusEnum.APPLY) {
                List<StudentPaymentOrder> oldStudentPaymentOrderList = this.queryByCondition(GroupType.MUSIC, musicGroupId, userId, DealStatusEnum.SUCCESS, OrderTypeEnum.APPLY);
                //判断是否有成功的订单，如果有，表示已经处理过人数
                if (oldStudentPaymentOrderList == null || oldStudentPaymentOrderList.size() == 0) {
                    List<StudentPaymentOrderDetail> orderDetail = studentPaymentOrderDetailService.getOrderDetail(order.getId());
                    if (orderDetail != null && orderDetail.size() > 0) {
                        long count = orderDetail.stream().filter(e -> e.getType() == OrderDetailTypeEnum.MUSICAL || e.getType() == OrderDetailTypeEnum.CLOUD_TEACHER).count();
                        MusicGroup musicGroup = musicGroupService.get(musicGroupId);
                        //如果购买了乐器或者云教练，或者不是会员团，那么关闭订单时人数减一
                        if (count > 0 || musicGroup.getCourseViewType() != CourseViewTypeEnum.MEMBER_FEE) {
                            MusicGroupSubjectPlan musicOneSubjectClassPlan = musicGroupSubjectPlanService.getMusicOneSubjectClassPlan(musicGroupId, studentRegistration.getActualSubjectId());
                            musicOneSubjectClassPlan.setPaidStudentNum(musicOneSubjectClassPlan.getPaidStudentNum() == null ? 0 : musicOneSubjectClassPlan.getPaidStudentNum() - 1);
                            musicGroupSubjectPlanService.update(musicOneSubjectClassPlan);
                        }
                    }
                }
            }
        }
    }

    /**
     * 只查询成功的订单
     *
     * @param param
     */
    public PageInfo<StudentPaymentOrderVo> queryOrder(Map<String, Object> param) throws Exception {
        SysUser user = sysUserFeignService.queryUserInfo();
        if (Objects.isNull(user)) {
            throw new BizException("未查询到学员信息！");
        }
        param.put("userId", user.getId());
        String queryDateStr = WrapperUtil.toStr(param, "queryDate", "请选择查询日期！");
        Date startDate = DateUtils.parseDate(queryDateStr + " 00:00:00", "yyyy-MM-dd HH:mm:ss");
        Date endDate = DateUtils.addMonths(startDate, 1);
        param.put("startDate", startDate);
        param.put("endDate", endDate);
        Page<StudentPaymentOrderVo> pageInfo = PageUtil.getPageInfo(param);
        pageInfo.setDesc("a.create_time_");
        return PageUtil.pageInfo(studentPaymentOrderDao.queryStudentOrderPage(pageInfo, param));
    }

    /**
     * 查询订单明细
     *
     * @param orderNo 订单编号
     */
    public StudentPaymentOrderVo queryOrderDetail(String orderNo) {
        Optional.ofNullable(orderNo)
                .map(this::findOrderByOrderNo)
                .orElseThrow(() -> new BizException("未查询到该订单数据!"));
        StudentPaymentOrderVo voList = studentPaymentOrderDao.queryOrderDetail(orderNo);
        if (Objects.nonNull(voList) && CollectionUtils.isNotEmpty(voList.getList())) {
            List<StudentPaymentOrderVo.StudentPaymentDetailVo> collect = voList.getList().stream()
                    .filter(d -> Objects.nonNull(d.getGoodsName()))
                    .collect(Collectors.toList());
            if (CollectionUtils.isEmpty(collect)) {
                voList.setList(null);
            } else {
                voList.setList(collect);
            }
        }
        return voList;
    }

    @Override
    public List<StudentPaymentOrder> queryByDealStatus(String musicGroupId, OrderTypeEnum orderType, DealStatusEnum status) {
        return studentPaymentOrderDao.queryByDealStatus(musicGroupId, orderType, status);
    }

    @Override
    public StudentPaymentOrder lockOrder(Long paymentOrderId) {
        return studentPaymentOrderDao.lockOrder(paymentOrderId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void returnBalanceAndCoupon(StudentPaymentOrder studentPaymentOrder, String memo) {
        if (studentPaymentOrder.getBalancePaymentAmount() != null && studentPaymentOrder.getBalancePaymentAmount().compareTo(BigDecimal.ZERO) > 0) {
            sysUserCashAccountService.updateBalance(studentPaymentOrder.getUserId(), studentPaymentOrder.getBalancePaymentAmount(),
                    PlatformCashAccountDetailTypeEnum.REFUNDS, memo);
        }
        sysCouponCodeService.quit(studentPaymentOrder.getCouponCodeId());
    }

    @Override
    public StudentPaymentOrder getMemberIngOrder(OrderTypeEnum member, DealStatusEnum status) {
        return studentPaymentOrderDao.getMemberIngOrder(member, status);
    }

    @Autowired
    private StudentRepairDao studentRepairDao;
    @Autowired
    private MusicGroupDao musicGroupDao;

    @Autowired
    private StudentGoodsSellDao studentGoodsSellDao;

    @Override
    public Map createOrder(MallCreateOrderModel model) throws Exception {

        if(model == null ||model.getUserId() == null) {
            throw new BizException("参数错误");
        }
        StudentGoodsSell studentGoodsSell;
        if (StringUtils.isNotEmpty(model.getOldOrderNo())) {
            studentGoodsSell = studentGoodsSellDao.findByOrderNo(model.getOldOrderNo());
        }  else {
            studentGoodsSell = new StudentGoodsSell();
        }
        studentDao.lockUser(model.getUserId());
        SysUser student = studentDao.getUser(model.getUserId());
        Map payMap = new HashMap();
        if (student == null) {
            payMap.put("mallStatus",0);
            return payMap;
        }
        studentGoodsSell.setUserId(model.getUserId());
        studentGoodsSell.setTeacherId(model.getTeacherId() >0 ? model.getTeacherId():studentGoodsSell.getTeacherId());
        studentGoodsSell.setAuthorUser(model.getTeacherId() >0 ? model.getTeacherId():studentGoodsSell.getAuthorUser());
        //如果教务老师为空，代表学员自己创建的订单
        if (model.getTeacherId() == null && studentGoodsSell.getTeacherId() == null) {
            //获取学生关联的所有教务老师列表
            List<Integer> stuEducation = studentRepairDao.countStuEducation(model.getUserId());
            if (stuEducation != null && stuEducation.size() == 1) {
                //获取学员乐团关联的教务
                MusicGroup musicGroup = musicGroupDao.getStuMusic(model.getUserId());
                studentGoodsSell.setTeacherId(stuEducation.get(0));
                if (musicGroup != null) {
                    studentGoodsSell.setCooperationOrganId(musicGroup.getCooperationOrganId());
                }
            }
        } else if (studentGoodsSell.getCooperationOrganId() == null) {
            //获取教务老师，学员关联的乐团
            MusicGroup musicGroup = musicGroupDao.getStuEduMusic(model.getUserId(), studentGoodsSell.getTeacherId());
            if (musicGroup != null) {
                studentGoodsSell.setCooperationOrganId(musicGroup.getCooperationOrganId());
            }
        }

        if (StringUtils.isNotEmpty(model.getOldOrderNo())) {
            StudentPaymentOrder orderByOrderNo = studentPaymentOrderService.findOrderByOrderNo(model.getOldOrderNo());
            if (orderByOrderNo == null) {
                throw new BizException("未找到原订单");
            }
            // 已有订单，先关单
            orderByOrderNo.setStatus(CLOSE);
            studentPaymentOrderService.update(orderByOrderNo);
            if (orderByOrderNo.getBalancePaymentAmount() != null && orderByOrderNo.getBalancePaymentAmount().compareTo(BigDecimal.ZERO) > 0) {
                sysUserCashAccountService.updateBalance(orderByOrderNo.getUserId(), orderByOrderNo.getBalancePaymentAmount(), PlatformCashAccountDetailTypeEnum.REFUNDS, "关闭订单");
            }
            //退优惠券
            sysCouponCodeService.quit(orderByOrderNo.getCouponCodeId());
        }


        Date date = new Date();
        StudentPaymentOrder studentPaymentOrder = sysCouponCodeService.use(model.getCouponIdList(), model.getAmount(),false);

        studentPaymentOrder.setStatus(DealStatusEnum.ING);
        if (studentPaymentOrder.getActualAmount().compareTo(BigDecimal.ZERO) == 0) {
            studentPaymentOrder.setStatus(DealStatusEnum.SUCCESS);
        }
        studentPaymentOrder.setGroupType(GroupType.MALL_SELL);
        studentPaymentOrder.setUserId(model.getUserId());
        studentPaymentOrder.setType(OrderTypeEnum.MALL_BUY);
        studentPaymentOrder.setOrderNo(model.getOrderNo());
        studentPaymentOrder.setCreateTime(date);
        studentPaymentOrder.setUpdateTime(date);
        studentPaymentOrder.setPaymentChannel("ADAPAY");
        studentPaymentOrder.setOrganId(student.getOrganId());
        studentPaymentOrder.setRoutingOrganId(student.getOrganId());
        studentPaymentOrder.setTenantId(student.getTenantId());
        studentPaymentOrderService.insert(studentPaymentOrder);

        studentGoodsSell.setCouponMarketAmount(studentPaymentOrder.getCouponRemitFee());
        studentGoodsSell.setOrganId(student.getOrganId());
        studentGoodsSell.setTotalAmount(studentPaymentOrder.getActualAmount());
        studentGoodsSell.setGoodsType("MALL");
        // studentGoodsSell.setGoodsJson(JSONObject.toJSONString(goodsSellDtos));
        studentGoodsSell.setOrderNo(model.getOrderNo());
        List<Integer> couponIdList = model.getCouponIdList();
        if (couponIdList != null && couponIdList.size() > 0) {
            studentGoodsSell.setCouponIds(StringUtils.join(couponIdList, ","));
        }
        studentGoodsSell.setTenantId(student.getTenantId());
        studentGoodsSellDao.insert(studentGoodsSell);

        String baseApiUrl = sysConfigDao.findConfigValue("base_api_url");

        //  receiver类型
        payMap = payService.getPayMap(
                studentPaymentOrder.getExpectAmount(),
                studentPaymentOrder.getActualAmount(),
                model.getOrderNo(),
                baseApiUrl + "/api-mall-portal/payment/callback",
                baseApiUrl + "/api-student/studentOrder/paymentResult?type=edu&orderNo=" + model.getOrderNo(),
                "商品销售",
                "商品销售",
                student.getOrganId(),
                "mall_buy"
        );
        studentPaymentOrder.setMerNos((String) payMap.get("routingMerNos"));
        studentPaymentOrder.setPaymentChannel((String) payMap.get("type"));
        studentPaymentOrderService.update(studentPaymentOrder);
        payMap.put("mallCouponAmount",studentPaymentOrder.getCouponRemitFee() == null?BigDecimal.ZERO:studentPaymentOrder.getCouponRemitFee());
        payMap.put("mallStatus",1);
        return payMap;
    }

    @Override
    public void mallBuyOrderCallback(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, 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);
        } 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, "商城购买支付失败");
            }
            sysCouponCodeService.quit(studentPaymentOrder.getCouponCodeId());
        }
    }

    @Override
    public void mallSaveOrderInfo(MallCreateOrderModel model) {

        StudentGoodsSell studentGoodsSell = studentGoodsSellDao.findByOrderNo(model.getOrderNo());
        if (studentGoodsSell == null) {
            throw new BizException("未找到订单信息");
        }
        studentGoodsSell.setGoodsJson(model.getOrderInfo());
        studentGoodsSell.setGoodsType("MALL");
        studentGoodsSellDao.update(studentGoodsSell);
    }

    @Override
    public OrderCancelModel cancelOrder(StudentPaymentOrder order) {
        OrderCancelModel model = new OrderCancelModel();
        try {
            TenantContextHolder.setTenantId(order.getTenantId());
            order.setStatus(CLOSE);
            order.setMemo("超时未支付关闭");
            callOrderCallBack(order);
            TenantContextHolder.clearTenantId();
            model.setSuccess(true);
            model.setStatus(false);
        } catch (Exception e) {
            model.setSuccess(false);
            e.printStackTrace();
        }
        return model;
    }
}
