package com.yc.ship.module.trade.service.order.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.yc.ship.framework.common.lang.Asserts;
import com.yc.ship.framework.common.pojo.CommonResult;
import com.yc.ship.framework.common.util.collection.CollectionUtils;
import com.yc.ship.framework.common.util.object.ObjectUtils;
import com.yc.ship.framework.mybatis.core.query.LambdaQueryWrapperX;
import com.yc.ship.framework.security.core.LoginUser;
import com.yc.ship.framework.security.core.util.SecurityFrameworkUtils;
import com.yc.ship.module.ota.api.OtaDistributorApi;
import com.yc.ship.module.ota.api.dto.DistributorRespDTO;
import com.yc.ship.module.otc.api.agency.dto.AgencyUserLoginInfoRespDTO;
import com.yc.ship.module.product.api.dto.ProductSpuRespDTO;
import com.yc.ship.module.system.api.notify.NotifyMessageSendApi;
import com.yc.ship.module.system.api.notify.dto.NotifySendSingleToUserReqDTO;
import com.yc.ship.module.system.api.user.AdminUserApi;
import com.yc.ship.module.system.api.user.dto.AdminUserRespDTO;
import com.yc.ship.module.trade.api.contract.ContractApi;
import com.yc.ship.module.trade.api.contract.dto.ContractApplyReqDTO;
import com.yc.ship.module.trade.api.contract.dto.ContractTouristDTO;
import com.yc.ship.module.trade.api.dto.TradeRefundAuditReqDTO;
import com.yc.ship.module.trade.api.dto.TradeRefundCalculateRespDTO;
import com.yc.ship.module.trade.api.dto.TradeRefundCreateReqDTO;
import com.yc.ship.module.trade.api.dto.TradeRefundRespDTO;
import com.yc.ship.module.trade.api.invoice.dto.InvoicingReqDTO;
import com.yc.ship.module.trade.controller.admin.order.vo.refund.*;
import com.yc.ship.module.trade.convert.invoice.InvoiceConvert;
import com.yc.ship.module.trade.convert.order.TradeRefundConvert;
import com.yc.ship.module.trade.dal.dataobject.audituser.AuditUserDO;
import com.yc.ship.module.trade.dal.dataobject.order.TradeDetailDO;
import com.yc.ship.module.trade.dal.dataobject.order.TradeOrderBindDO;
import com.yc.ship.module.trade.dal.dataobject.order.TradeOrderDO;
import com.yc.ship.module.trade.dal.dataobject.order.TradeOrderUserDO;
import com.yc.ship.module.trade.dal.mysql.audituser.AuditUserMapper;
import com.yc.ship.module.trade.dal.mysql.order.TradeDetailMapper;
import com.yc.ship.module.trade.dal.mysql.order.TradeOrderBindMapper;
import com.yc.ship.module.trade.dal.mysql.order.TradeOrderMapper;
import com.yc.ship.module.trade.enums.RefundChannelEnum;
import com.yc.ship.module.trade.enums.TradeOrderOperateTypeEnum;
import com.yc.ship.module.trade.enums.TradeOrderStatusEnum;
import com.yc.ship.module.trade.framework.annotation.TradeOrderLog;
import com.yc.ship.module.trade.framework.common.TradeOrderLogUtils;
import com.yc.ship.module.trade.service.invoice.InvoiceService;
import com.yc.ship.module.trade.service.order.AdminTradeOrderService;
import com.yc.ship.module.trade.service.order.TradeOrderRepositoryService;
import com.yc.ship.module.trade.service.order.bo.TradeVisitorBO;
import com.yc.ship.module.trade.service.pay.TradeOrderPayService;
import com.yc.ship.module.trade.service.refund.TradeRefundService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import static com.yc.ship.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.yc.ship.framework.security.core.util.SecurityFrameworkUtils.getLoginUser;
import static com.yc.ship.framework.web.core.util.WebFrameworkUtils.getLoginUserId;
import static com.yc.ship.module.trade.enums.ApiConstants.*;
import static com.yc.ship.module.trade.enums.ErrorCodeConstants.*;
import static com.yc.ship.module.trade.utils.AgencyAuthUtils.AGENCY_LOGIN_INFO;


/**
 * &#064;Description ：后台交易（平台、旅行社）service实现
 * &#064;Author ：qsl
 * &#064;Date ：2025/6/4 16:18
 *
 * @author qsl
 */
@Service
@Slf4j
public class AdminTradeOrderServiceImpl implements AdminTradeOrderService {

    @Resource
    private TradeRefundService tradeRefundService;
    @Resource
    private TradeOrderPayService tradeOrderPayService;
    @Resource
    private TradeDetailMapper tradeDetailMapper;
    @Resource
    private AuditUserMapper auditUserMapper;
    @Resource
    private TradeOrderMapper tradeOrderMapper;
    @Resource
    private TradeOrderBindMapper tradeOrderBindMapper;
    @Resource
    private ContractApi contractApi;
    @Resource
    private TradeOrderRepositoryService tradeOrderRepositoryService;
    @Resource
    private OtaDistributorApi distributorApi;
    @Resource
    private InvoiceService invoiceService;

    @Resource
    private NotifyMessageSendApi notifyMessageSendApi;

    @Resource
    private AdminUserApi adminUserApi;

    @Override
    public CommonResult<TradeRefundCreateRespVO> refund(LoginUser loginUser, TradeRefundCreateReqVO refundCreateReqVO) {
        AgencyUserLoginInfoRespDTO agencyUserLoginInfo = loginUser.getContext(AGENCY_LOGIN_INFO, AgencyUserLoginInfoRespDTO.class);
        //根据退款类型分别处理
        TradeRefundCreateReqDTO tradeRefundCreateReqDTO = TradeRefundConvert.INSTANCE.convert(refundCreateReqVO);
        tradeRefundCreateReqDTO.setRefundUser(loginUser.getId());
        if (agencyUserLoginInfo != null) {
            tradeRefundCreateReqDTO.setMachineId(agencyUserLoginInfo.getMachineId());
            tradeRefundCreateReqDTO.setMachineName(agencyUserLoginInfo.getMachineName());
            tradeRefundCreateReqDTO.setStoreId(agencyUserLoginInfo.getStoreId());
            tradeRefundCreateReqDTO.setStoreName(agencyUserLoginInfo.getStoreName());
        }
        TradeRefundCreateRespVO respVO = new TradeRefundCreateRespVO();
        List<String> successList = new ArrayList<>();
        List<String> auditList = new ArrayList<>();
        List<String> supplierFailList = new ArrayList<>();
        List<String> failList = new ArrayList<>();
        List<String> messageList = new ArrayList<>();
        if (refundCreateReqVO.getRefundType() == REFUND_TYPE_ORDER) {
            Asserts.isTrue(CollUtil.isNotEmpty(refundCreateReqVO.getOrderInfoList()), "退款订单列表不能为空");
            boolean isMultiOrder = refundCreateReqVO.getOrderInfoList().size() > 1;
            refundCreateReqVO.getOrderInfoList().forEach(orderInfo -> {

                tradeRefundCreateReqDTO.setOrderId(orderInfo.getOrderId());
                if (isMultiOrder) {
                    tradeRefundCreateReqDTO.setRefundAmount(orderInfo.getRefundAmount());
                    tradeRefundCreateReqDTO.setOriginRefundAmount(orderInfo.getOriginRefundAmount());
                    tradeRefundCreateReqDTO.setFee(orderInfo.getFee());
                }
                CommonResult<TradeRefundRespDTO> resp = tradeRefundService.refund(tradeRefundCreateReqDTO);
                if (resp.isSuccess()) {
                    successList.add(orderInfo.getOrderNo());
                } else if (ObjectUtil.equal(resp.getCode(), REFUND_AUDITING.getCode())) {
                    auditList.add(orderInfo.getOrderNo());
                } else if (ObjectUtil.equal(resp.getCode(), SUPPLIER_SERVICE_REFUND_CONFIRM.getCode())) {
                    supplierFailList.add(orderInfo.getOrderNo());
                } else {
                    messageList.add(resp.getMsg());
                    failList.add(orderInfo.getOrderNo());
                }
            });
            respVO.setSuccessList(successList).setAuditList(auditList).setSupplierFailList(supplierFailList).setFailList(failList)
                    .setMessageList(messageList);
        } else if (refundCreateReqVO.getRefundType() == REFUND_TYPE_ITEM) {
            Asserts.isTrue(CollUtil.isNotEmpty(refundCreateReqVO.getRefundItemList()), "退款项列表不能为空");
            Map<Long, List<TradeRefundCreateReqDTO.RefundItem>> refundByOrderMap = refundCreateReqVO.getRefundItemList().stream().collect(Collectors.groupingBy(TradeRefundCreateReqDTO.RefundItem::getOrderId));
            boolean isMultiOrder = refundByOrderMap.size() > 1;
            refundByOrderMap.forEach((key, value) -> {
                //窗口、后台退款可以改价
                if (!ObjectUtils.equalsAny(refundCreateReqVO.getRefundChannel(), RefundChannelEnum.BACKEND.getType(), RefundChannelEnum.WINDOW.getType())) {
                    if (isMultiOrder) {
                        //后面系统会计算
                        tradeRefundCreateReqDTO.setRefundAmount(null);
                        tradeRefundCreateReqDTO.setOriginRefundAmount(null);
                        tradeRefundCreateReqDTO.setFee(null);
                    }
                }

                tradeRefundCreateReqDTO.setOrderId(key);
                tradeRefundCreateReqDTO.setItemlList(value);
                CommonResult<TradeRefundRespDTO> resp = tradeRefundService.refund(tradeRefundCreateReqDTO);
                List<String> voucherList = value.stream().map(TradeRefundCreateReqDTO.RefundItem::getVoucherCode).collect(Collectors.toList());
                if (resp.isSuccess()) {
                    successList.addAll(voucherList);
                } else if (ObjectUtil.equal(resp.getCode(), REFUND_AUDITING.getCode())) {
                    auditList.addAll(voucherList);
                } else if (ObjectUtil.equal(resp.getCode(), SUPPLIER_SERVICE_REFUND_CONFIRM.getCode())) {
                    supplierFailList.addAll(voucherList);
                } else {
                    messageList.add(resp.getMsg());
                    failList.addAll(voucherList);
                }
            });
            respVO.setSuccessList(successList).setAuditList(auditList).setSupplierFailList(supplierFailList).setFailList(failList)
                    .setMessageList(messageList);
        } else if (refundCreateReqVO.getRefundType() == REFUND_TYPE_ITEM_BASE) {
            Asserts.isTrue(CollUtil.isNotEmpty(refundCreateReqVO.getRefundItemList()), "退款项列表不能为空");
            Asserts.isTrue(refundCreateReqVO.getRefundItemList().size() == 1, "退款项数据格式不正确");
            Asserts.isTrue(CollUtil.isNotEmpty(refundCreateReqVO.getRefundItemList().get(0).getDetailList()), "退款项明细列表不能为空");
            tradeRefundCreateReqDTO.setItemlList(refundCreateReqVO.getRefundItemList());
            CommonResult<TradeRefundRespDTO> resp = tradeRefundService.refund(tradeRefundCreateReqDTO);
            if (resp.isSuccess()) {
                return CommonResult.success(null);
            } else {
                return CommonResult.error(resp.getCode(), resp.getMsg());
            }
        } else {
            throw exception(REFUND_TYPE_ERROR);
        }

        return CommonResult.success(respVO);
    }

    @Override
    public CommonResult<TradeRefundCreateRespVO> minirefund(LoginUser loginUser, TradeRefundCreateReqVO refundCreateReqVO) {
        AgencyUserLoginInfoRespDTO agencyUserLoginInfo = loginUser.getContext(AGENCY_LOGIN_INFO, AgencyUserLoginInfoRespDTO.class);
        //根据退款类型分别处理
        TradeRefundCreateReqDTO tradeRefundCreateReqDTO = TradeRefundConvert.INSTANCE.convert(refundCreateReqVO);
        tradeRefundCreateReqDTO.setRefundUser(loginUser.getId());
        if (agencyUserLoginInfo != null) {
            tradeRefundCreateReqDTO.setMachineId(agencyUserLoginInfo.getMachineId());
            tradeRefundCreateReqDTO.setMachineName(agencyUserLoginInfo.getMachineName());
            tradeRefundCreateReqDTO.setStoreId(agencyUserLoginInfo.getStoreId());
            tradeRefundCreateReqDTO.setStoreName(agencyUserLoginInfo.getStoreName());
        }
        TradeRefundCreateRespVO respVO = new TradeRefundCreateRespVO();
        List<String> successList = new ArrayList<>();
        List<String> auditList = new ArrayList<>();
        List<String> supplierFailList = new ArrayList<>();
        List<String> failList = new ArrayList<>();
        List<String> messageList = new ArrayList<>();
        Asserts.isTrue(CollUtil.isNotEmpty(refundCreateReqVO.getOrderInfoList()), "退款订单列表不能为空");
        boolean isMultiOrder = refundCreateReqVO.getOrderInfoList().size() > 1;
        refundCreateReqVO.getOrderInfoList().forEach(orderInfo -> {
            tradeRefundCreateReqDTO.setOrderId(orderInfo.getOrderId());
            if (isMultiOrder) {
                tradeRefundCreateReqDTO.setRefundAmount(orderInfo.getRefundAmount());
                tradeRefundCreateReqDTO.setOriginRefundAmount(orderInfo.getOriginRefundAmount());
                tradeRefundCreateReqDTO.setFee(orderInfo.getFee());
            }
            CommonResult<TradeRefundRespDTO> resp = tradeRefundService.minirefund(tradeRefundCreateReqDTO);
            if (resp.isSuccess()) {
                successList.add(orderInfo.getOrderNo());
            } else if (ObjectUtil.equal(resp.getCode(), REFUND_AUDITING.getCode())) {
                auditList.add(orderInfo.getOrderNo());
            } else if (ObjectUtil.equal(resp.getCode(), SUPPLIER_SERVICE_REFUND_CONFIRM.getCode())) {
                supplierFailList.add(orderInfo.getOrderNo());
            } else {
                messageList.add(resp.getMsg());
                failList.add(orderInfo.getOrderNo());
            }
        });
        respVO.setSuccessList(successList).setAuditList(auditList).setSupplierFailList(supplierFailList).setFailList(failList)
                .setMessageList(messageList);
        return CommonResult.success(respVO);
    }

    @Override
    public CommonResult<TradeRefundCalculateRespVO> calculateRefundAmount(LoginUser loginUser, TradeRefundCreateReqVO refundCreateReqVO) {
        //根据退款类型分别处理
        TradeRefundCreateReqDTO tradeRefundCreateReqDTO = TradeRefundConvert.INSTANCE.convert(refundCreateReqVO);
        if (loginUser != null) {
            tradeRefundCreateReqDTO.setRefundUser(loginUser.getId());
        }

        TradeRefundCalculateRespVO respVO = new TradeRefundCalculateRespVO();
        List<TradeRefundCalculateRespDTO> list = new ArrayList<>();
        Asserts.isTrue(CollUtil.isNotEmpty(refundCreateReqVO.getOrderInfoList()), "退款订单列表不能为空");
        boolean isMultiOrder = refundCreateReqVO.getOrderInfoList().size() > 1;
        refundCreateReqVO.getOrderInfoList().forEach(orderInfo -> {
            tradeRefundCreateReqDTO.setOrderId(orderInfo.getOrderId());
            if (isMultiOrder) {
                tradeRefundCreateReqDTO.setRefundAmount(orderInfo.getRefundAmount());
                tradeRefundCreateReqDTO.setOriginRefundAmount(orderInfo.getOriginRefundAmount());
                tradeRefundCreateReqDTO.setFee(orderInfo.getFee());
            }
            CommonResult<TradeRefundCalculateRespDTO> resp = tradeRefundService.calculateRefundAmount(tradeRefundCreateReqDTO);
            list.add(resp.getData());
        });
        respVO.setList(list);
        return CommonResult.success(respVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<?> refundAudit(LoginUser loginUser, TradeRefundAuditReqVO refundAuditReqVO) {
        TradeRefundAuditReqDTO refundAuditReqDTO = TradeRefundConvert.INSTANCE.convert(refundAuditReqVO);
        refundAuditReqDTO.setAuditUser(loginUser.getId());
        return tradeRefundService.refundAudit(refundAuditReqDTO);
    }

    @Override
    public CommonResult<?> manualRefund(LoginUser loginUser, Long refundId) {
        return tradeRefundService.refundByPaymentType(refundId);
    }

    @Override
    public CommonResult<?> refundByRecord(LoginUser loginUser, Long refundRecordId) {
        return tradeRefundService.refundByRecord(refundRecordId);
    }

    @Override
    public CommonResult<?> refundQuery(Long refundRecordId) {
        return tradeRefundService.refundQuery(refundRecordId);
    }


    @Override
    public void applyContract(TradeOrderDO tradeOrderDO) {
        //目前合同配置是在组合产品上
        List<Map<String, Object>> contractProductList = tradeOrderRepositoryService.getContractProductFromOrder(tradeOrderDO.getId());
        if (CollUtil.isEmpty(contractProductList)) {
            CommonResult.error(ORDER_CONTRACT_PRODUCT_NO_CONFIG);
            return;
        }
        //一个订单只处理一个合同
        Map<String, Object> contractProduct = contractProductList.get(0);
        List<TradeVisitorBO> visitorDOList = tradeOrderRepositoryService.getContractVisitor(tradeOrderDO.getId(), MapUtil.getLong(contractProduct, "product_id"));
        if (CollUtil.isEmpty(visitorDOList)) {
            log.info("当前产品合同无出行人信息{}", MapUtil.getLong(contractProduct, "product_id"));
            CommonResult.error(ORDER_CONTRACT_NO_PEOPLE);
            return;
        }
        List<TradeDetailDO> tradeDetailDOList = tradeOrderRepositoryService.queryDetailByOrderId(tradeOrderDO.getId());
        ProductSpuRespDTO productSpu = tradeDetailMapper.getProductSpu(tradeDetailDOList.get(0).getProductId());
        TradeVisitorBO holder = visitorDOList.get(0);
        TradeOrderUserDO tradeOrderUserDO = tradeOrderRepositoryService.getOrderUser(tradeOrderDO.getId());
        ContractApplyReqDTO reqDTO = new ContractApplyReqDTO();
        reqDTO.setOrderId(tradeOrderDO.getId());
        reqDTO.setOrderNo(tradeOrderDO.getOrderNo());
        reqDTO.setTravelDate(holder.getUseDate());
        reqDTO.setPayType(3);
        reqDTO.setRouteName(tradeDetailDOList.get(0).getProductName());
        reqDTO.setOperatorMobile(tradeOrderUserDO.getMobile());
        reqDTO.setOrderAmount(tradeOrderDO.getPayAmount());
        reqDTO.setTemplateId(MapUtil.getStr(contractProduct, "contract_id"));
        reqDTO.setTravelerName(tradeOrderUserDO.getContactName());
        reqDTO.setOperatorName(tradeOrderUserDO.getContactName());
        if (StringUtils.isNotBlank(tradeOrderUserDO.getCredentialNo())) {
            reqDTO.setTravelerIdCardNo(tradeOrderUserDO.getCredentialNo());
        } else {
            List<TradeVisitorBO> collect = visitorDOList.stream().filter(item -> ObjectUtil.equal(item.getName(), tradeOrderUserDO.getContactName())).collect(Collectors.toList());
            if (!collect.isEmpty()) {
                reqDTO.setTravelerIdCardNo(collect.get(0).getCredentialNo());
            } else {
                reqDTO.setTravelerIdCardNo(visitorDOList.get(0).getCredentialNo());
            }
        }
        reqDTO.setTravelerIdCardType(String.valueOf(tradeOrderUserDO.getCredentialType()));
        reqDTO.setContractTouristList(CollectionUtils.convertList(visitorDOList, this::convert));
        reqDTO.setTouristQuantity(visitorDOList.size());
        reqDTO.setTravelerMobile(tradeOrderUserDO.getMobile());
        if (StringUtils.isNotBlank(productSpu.getBookingInstructions())) {
            reqDTO.setTripDescription(productSpu.getProductIntroduction().replaceAll("<p>", "").replaceAll("</p>", ""));
        } else {
            reqDTO.setTripDescription(productSpu.getProductIntroduction());
        }
        CommonResult<?> result = contractApi.applyContract(reqDTO);
        tradeOrderRepositoryService.updateOrderContractStatus(tradeOrderDO.getId(), 0);
    }

    private ContractTouristDTO convert(TradeVisitorBO tradeVisitorBO) {
        ContractTouristDTO contractTouristDTO = new ContractTouristDTO();
        if (tradeVisitorBO.getGender() != null) {
            contractTouristDTO.setGender(tradeVisitorBO.getGender() == 0 ? "女" : "男");
        }
        contractTouristDTO.setName(tradeVisitorBO.getName());
        contractTouristDTO.setMobile(tradeVisitorBO.getMobile());
        contractTouristDTO.setIdCardNo(tradeVisitorBO.getCredentialNo());
        contractTouristDTO.setIdCardType(String.valueOf(tradeVisitorBO.getCredentialType()));
        return contractTouristDTO;
    }

    @Override
    @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.MANUL_CANCEL)
    public CommonResult<?> cancelOrder(Long orderId) {
        TradeOrderDO tradeOrderDO = tradeOrderRepositoryService.getById(orderId);
        Asserts.isTrue(tradeOrderDO != null, "订单不存在");
        TradeOrderBindDO tradeOrderBindDO = new TradeOrderBindDO();
        tradeOrderBindDO.setId(IdWorker.getId());
        tradeOrderBindDO.setType(1);
        tradeOrderBindDO.setBindId(orderId);
        tradeOrderBindDO.setOrderId(orderId);
        tradeOrderBindDO.setCustom("订单取消");
        tradeOrderBindDO.setRemark("订单取消");
        tradeOrderBindDO.setCreateTime(LocalDateTime.now());
        tradeOrderBindDO.setCreator(getLoginUserId() + "");
        tradeOrderBindMapper.insert(tradeOrderBindDO);

        List<TradeDetailDO> tradeDetailList = tradeOrderRepositoryService.queryYcDetailByOrderId(orderId);
        long between = DateUtil.between(new Date(), tradeOrderDO.getTravelDate(), DateUnit.DAY, false);
        BigDecimal damaged;
        if (between > 21) {
            damaged = new BigDecimal(500).multiply(new BigDecimal(tradeDetailList.size()));
        } else if (between > 15) {
            damaged = tradeOrderDO.getPayAmount().multiply(new BigDecimal("0.2"));
        } else {
            damaged = tradeOrderDO.getPayAmount();
        }

        AuditUserDO auditUserDO = auditUserMapper.selectOne(new LambdaQueryWrapperX<AuditUserDO>().eq(AuditUserDO::getType, 4).eq(AuditUserDO::getAuditStatus, 1).eq(AuditUserDO::getDeleted, 0).orderByDesc(AuditUserDO::getCreateTime).last("limit 1"));
        tradeOrderMapper.update(new UpdateWrapper<TradeOrderDO>().set("audit_type", 4).set("audit_user", auditUserDO == null ? "" : auditUserDO.getAuditUser()).set("order_status", TradeOrderStatusEnum.CANCEL_AUDIT.getStatus()).set("audit_status", 1).set("damaged", damaged).set("damaged_status", 1).set("damaged_time", LocalDateTime.now()).eq("id", tradeOrderDO.getId()));

        try {
            Map map = new HashMap();
            Long userId = SecurityFrameworkUtils.getLoginUserId();
            map.put("orderNo", tradeOrderDO.getOrderNo());
            map.put("oldOrderStatus", TradeOrderStatusEnum.valueOf(tradeOrderDO.getOrderStatus()).getName());
            map.put("newOrderStatus", TradeOrderStatusEnum.CANCEL_AUDIT.getName());
            AdminUserRespDTO user = adminUserApi.getUser(userId);
            map.put("modifyUser", user.getNickname());
            NotifySendSingleToUserReqDTO reqDTO = new NotifySendSingleToUserReqDTO();
            reqDTO.setTemplateParams(map);
            //订单（{orderNo}）已修改, 状态由{oldOrderStatus} 改为{newOrderStatus},  修改人为： {modifyUser} ，请注意核对！
            //订单详情页面展示具体变更内容
            reqDTO.setTemplateCode("sendmsg_cd_12");

            List<Long> userIds = adminUserApi.getUserListByRoleCode("jdtx");
            if (userIds != null) {
                userIds.forEach(senduser -> {
                    reqDTO.setUserId(senduser);
                    notifyMessageSendApi.sendSingleMessageToAdmin(reqDTO);
                });
            } else {
                log.error("获取角色jdtx用户为空");
            }
        } catch (Exception e) {
            log.error("发送站内信异常", e);
        }

        TradeOrderLogUtils.setOrderInfo(orderId, tradeOrderDO.getOrderStatus(), TradeOrderStatusEnum.CANCEL_AUDIT.getStatus());
        return CommonResult.success("订单取消审核中");
    }

    @Override
    public CommonResult<?> refundAmount(TradeRefundAmountReqVO refundAmountReqVO) {
        LoginUser loginUser = getLoginUser();
        Asserts.isTrue(loginUser != null, "调用此方法需要登录");
        tradeRefundService.refundByService(refundAmountReqVO, loginUser);
        return CommonResult.success(null);
    }


    @Override
    public CommonResult<?> cancelRefund(Long refundId) {
        return tradeRefundService.cancelRefund(refundId);
    }

    @Override
    public CommonResult<?> orderApplyInvoice(String jsonStr) {
        JSONObject reqObj = JSONUtil.parseObj(jsonStr);
        List<String> orderNoList = Arrays.asList(reqObj.getStr("orderNos").split(","));
        String otaId = reqObj.getStr("otaId");
        String remark = reqObj.getStr("remark");
        if (StringUtils.isNotBlank(otaId)) {
            //平台开旅行社发票
            DistributorRespDTO distributorRespDTO = distributorApi.getDistributorById(Long.parseLong(otaId));
            if (distributorRespDTO == null) {
                throw exception(INVOICING_FAIL);
            }
            InvoicingReqDTO reqDTO = InvoiceConvert.INSTANCE.convertOtc(distributorRespDTO);
            reqDTO.setOrderIdList(orderNoList);
            reqDTO.setTitleType(1);
            reqDTO.setRemark(remark);
            reqDTO.setPrice(reqObj.getBigDecimal("amount"));
            reqDTO.setTotalPrice(reqObj.getBigDecimal("totalAmount"));
            return invoiceService.applyInvoicing(reqDTO);
        }
        TradeOrderDO tradeOrderDO = tradeOrderMapper.selectByOrderNo(orderNoList.get(0));
        DistributorRespDTO distributorRespDTO = distributorApi.getDistributorById(Long.parseLong(tradeOrderDO.getSourceId()));
        if (distributorRespDTO==null) {
            throw exception(INVOICING_NOTFIND);
        }
        InvoicingReqDTO reqDTO = InvoiceConvert.INSTANCE.convertOtc(distributorRespDTO);
        reqDTO.setOrderIdList(orderNoList);
        reqDTO.setTitleType(1);
        reqDTO.setRemark(remark);
        reqDTO.setPrice(reqObj.getBigDecimal("amount"));
        reqDTO.setTotalPrice(reqObj.getBigDecimal("totalAmount"));
        return invoiceService.applyInvoicing(reqDTO);
    }

    @Override
    public CommonResult<?> platApplyInvoice(String jsonStr) {
        JSONObject reqObj = JSONUtil.parseObj(jsonStr);
        List<String> orderNoList = Arrays.asList(reqObj.getStr("orderNos").split(","));
        String otaId = reqObj.getStr("otaId");
        String remark = reqObj.getStr("remark");
        if (StringUtils.isBlank(otaId)) {
            throw exception(INVOICING_FAIL_OTA);
        }
        //平台开旅行社发票
        DistributorRespDTO distributorRespDTO = distributorApi.getDistributorById(Long.parseLong(otaId));
        if (distributorRespDTO == null) {
            throw exception(INVOICING_FAIL);
        }
        InvoicingReqDTO reqDTO = InvoiceConvert.INSTANCE.convertOtc(distributorRespDTO);
        reqDTO.setOrderIdList(orderNoList);
        reqDTO.setTitleType(1);
        reqDTO.setIsPlat(1);
        reqDTO.setRemark(remark);
        reqDTO.setPrice(reqObj.getBigDecimal("amount"));
        reqDTO.setTotalPrice(reqObj.getBigDecimal("totalAmount"));
        return invoiceService.applyInvoicing(reqDTO);
    }

}
