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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yc.ship.framework.common.lang.Asserts;
import com.yc.ship.framework.common.pojo.CommonResult;
import com.yc.ship.framework.common.util.date.DateUtils;
import com.yc.ship.framework.common.util.json.JsonUtils;
import com.yc.ship.framework.common.util.object.ObjectUtils;
import com.yc.ship.framework.security.core.LoginUser;
import com.yc.ship.framework.tenant.core.util.TenantUtils;
import com.yc.ship.module.infra.api.config.ConfigApi;
import com.yc.ship.module.ota.enums.DistributorTradeTypeEnum;
import com.yc.ship.module.product.api.ProductApi;
import com.yc.ship.module.product.api.dto.ProductGroupRespDTO;
import com.yc.ship.module.product.api.dto.ProductSkuRespDTO;
import com.yc.ship.module.product.api.dto.ProductSpuRespDTO;
import com.yc.ship.module.product.enums.SpecTypeEnum;
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.dto.GuideRefundConfirmRespDTO;
import com.yc.ship.module.trade.api.dto.GuideRefundReqDTO;
import com.yc.ship.module.trade.api.dto.GuideRefundRespDTO;
import com.yc.ship.module.trade.api.dto.TradeRefundCreateReqDTO;
import com.yc.ship.module.trade.api.dto.sms.SmsBatchSendRespDTO;
import com.yc.ship.module.trade.api.sms.dto.SmsSendLogDTO;
import com.yc.ship.module.trade.controller.admin.order.vo.order.PayOrderReqVO;
import com.yc.ship.module.trade.controller.admin.order.vo.order.PayOrderRespVO;
import com.yc.ship.module.trade.controller.admin.order.vo.refund.TradeRefundCreateReqVO;
import com.yc.ship.module.trade.controller.admin.order.vo.refund.TradeRefundCreateRespVO;
import com.yc.ship.module.trade.controller.admin.smsSendconfig.vo.SmsSendconfigQueryRespVO;
import com.yc.ship.module.trade.dal.dataobject.order.TradeDetailBaseDO;
import com.yc.ship.module.trade.dal.dataobject.order.TradeDetailDO;
import com.yc.ship.module.trade.dal.dataobject.order.TradeOrderDO;
import com.yc.ship.module.trade.dal.mysql.order.TradeDetailMapper;
import com.yc.ship.module.trade.enums.*;
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.order.AdminTradeOrderService;
import com.yc.ship.module.trade.service.order.TradeOrderBizService;
import com.yc.ship.module.trade.service.order.TradeOrderRepositoryService;
import com.yc.ship.module.trade.service.order.bo.TradeDetailBO;
import com.yc.ship.module.trade.service.order.handler.SmsUtil;
import com.yc.ship.module.trade.service.pay.TradeOrderPayService;
import com.yc.ship.module.trade.service.refund.TradeRefundRepositoryService;
import com.yc.ship.module.trade.service.refund.TradeRefundService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import java.io.*;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

import static com.yc.ship.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.yc.ship.module.product.enums.YesOrNoEnum.NO;
import static com.yc.ship.module.product.enums.YesOrNoEnum.YES;
import static com.yc.ship.module.trade.enums.ApiConstants.*;
import static com.yc.ship.module.trade.enums.ErrorCodeConstants.CONFIRM_ORDER_REFUND_FAIL;
import static com.yc.ship.module.trade.enums.ErrorCodeConstants.GUIDE_REFUND_PRODUCT_BASE_NOT_EXISTS;


/**
 * &#064;Description ：订单交易业务处理service接口
 * &#064;Author ：qsl
 * &#064;Date ：2025/2/27 15:29
 */

@Service
@Slf4j
public class TradeOrderBizServiceImpl implements TradeOrderBizService {

    @Resource
    private TradeOrderRepositoryService tradeOrderRepositoryService;
    @Resource
    private TradeRefundRepositoryService tradeRefundRepositoryService;
    @Resource
    private AdminTradeOrderService adminTradeOrderService;
    @Resource
    private RedissonClient redissonClient;
    @Resource
    private TradeDetailMapper tradeDetailMapper;
    @Resource
    private TradeOrderPayService tradeOrderPayService;

    @Resource
    @Lazy
    private AdminUserApi adminUserApi;
    @Resource
    @Lazy
    private ConfigApi configApi;
    @Resource
    @Lazy
    private ProductApi productApi;
    @Resource
    private TradeRefundService tradeRefundService;


    @Override
    public void updatePlatAmountAfterProcessSuccess(TradeOrderDO tradeOrderDO) {

    }

    @Override
    public void updatePlatAmountAfterMergeSuccess(TradeOrderDO tradeOrderDO) {
        //只有内部旅行社下的平台单才处理
        if (!ObjectUtil.equal(tradeOrderDO.getSellMethod(), SellMethodEnum.OTC.getType())) {
            return;
        }
    }

    @Override
    public void updatePlatAmountAfterRefund(TradeOrderDO tradeOrderDO) {
        //平台退款才处理
        if (!ObjectUtils.equalsAny(tradeOrderDO.getSellMethod(), SellMethodEnum.OTC.getType())) {
            return;
        }
    }

    @Override
    @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.CONFIRM_ORDER)
    public CommonResult<?> confirmOrder(LoginUser loginUser, Long orderId, Integer type, Integer sendSms) {
        return confirmOrder(loginUser, orderId, type, false, sendSms);
    }

    public CommonResult<?> confirmOrder(LoginUser loginUser, Long orderId, Integer type, boolean isNotice, Integer sendSms) {
        Asserts.isTrue(type != null && ObjectUtils.equalsAny(type, TradeOrderConfirmTypeEnum.CONFIRMED.getType()
                , TradeOrderConfirmTypeEnum.CANCEL.getType()), "确认类型不正确");
        Asserts.isTrue(orderId != null, "订单ID不能为空");
        String lockKey = String.format(UPDATE_CONFIRM_ORDER_LOCK, orderId);
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock();
        try {
            TradeOrderDO tradeOrderDO = tradeOrderRepositoryService.getById(orderId);
            Asserts.isTrue(tradeOrderDO != null, "订单不存在");
            if (ObjectUtil.equal(type, TradeOrderConfirmTypeEnum.CANCEL.getType())) {
                Asserts.isTrue(ObjectUtil.equal(tradeOrderDO.getConfirmType(), TradeOrderConfirmTypeEnum.NEED.getType()), "当前订单确认状态已变更，不能取消");
                CommonResult<TradeRefundCreateRespVO> refundResult = doCancelConfirmOrder(loginUser, tradeOrderDO, isNotice);
                if (refundResult.isError() || refundResult.getData().getSuccessList().size() != 1) {
                    if (isNotice) {
                        TradeOrderLogUtils.setOrderInfo(orderId, tradeOrderDO.getOrderStatus(), tradeOrderDO.getOrderStatus(), MapUtil.<String, Object>builder().put("confirmPerson", isNotice ? "平台同步" : "人工操作")
                                .put("confirmType", TradeOrderConfirmTypeEnum.valueOf(type).getName()).build());
                    }
                    return CommonResult.error(CONFIRM_ORDER_REFUND_FAIL);
                }
                TradeOrderLogUtils.setOrderInfo(orderId, tradeOrderDO.getOrderStatus(), tradeOrderDO.getOrderStatus(), MapUtil.<String, Object>builder().put("confirmPerson", isNotice ? "平台同步" : "人工操作")
                        .put("confirmType", TradeOrderConfirmTypeEnum.valueOf(type).getName()).build());
            } else {
                if (tradeOrderDO != null) {
                    Asserts.isTrue(ObjectUtil.equal(tradeOrderDO.getConfirmType(), TradeOrderConfirmTypeEnum.NEED.getType()), "当前订单确认状态已变更，不能确认");
                    TradeOrderLogUtils.setOrderInfo(orderId, tradeOrderDO.getOrderStatus(), tradeOrderDO.getOrderStatus(), MapUtil.<String, Object>builder().put("confirmPerson", isNotice ? "平台同步" : "人工操作")
                            .put("confirmType", TradeOrderConfirmTypeEnum.valueOf(type).getName()).build());
                }
            }
            tradeOrderRepositoryService.updateOrderConfirmType(orderId, type);
            //如果是平台订单，同步下旅行社订单
            if (tradeOrderDO != null && ObjectUtil.equal(tradeOrderDO.getSellMethod(), SellMethodEnum.OTC.getType())) {
                confirmAgencyOrder(loginUser, tradeOrderDO.getExternalOriginOrderNo(), sendSms);
            }
            if (ObjectUtil.equal(type, TradeOrderConfirmTypeEnum.CANCEL.getType())) {
                if (sendSms != null && sendSms == 2) {
                    List<SmsSendconfigQueryRespVO> list = tradeOrderRepositoryService.getOrderSmsInfo(tradeOrderDO.getId(), 5);
                    for (SmsSendconfigQueryRespVO smsSendconfigQueryRespVO : list) {
                        if (smsSendconfigQueryRespVO.getMobile() != null && StringUtils.isNotBlank(smsSendconfigQueryRespVO.getChannelCode())) {
                            if (StringUtils.equals("UNICOM", smsSendconfigQueryRespVO.getChannelCode())) {
                                sendMsg2(smsSendconfigQueryRespVO);
                            } else if (StringUtils.equals("UNEW", smsSendconfigQueryRespVO.getChannelCode())) {
                                sendMsg3(smsSendconfigQueryRespVO);
                            } else if (StringUtils.equals("CMCC", smsSendconfigQueryRespVO.getChannelCode())) {
                                sendMsg(smsSendconfigQueryRespVO);
                            }
                        }
                    }
                }
            } else {
                if (sendSms != null && sendSms == 2) {
                    List<SmsSendconfigQueryRespVO> list = tradeOrderRepositoryService.getOrderSmsInfo(tradeOrderDO.getId(), 4);
                    for (SmsSendconfigQueryRespVO smsSendconfigQueryRespVO : list) {
                        if (smsSendconfigQueryRespVO.getMobile() != null && StringUtils.isNotBlank(smsSendconfigQueryRespVO.getChannelCode())) {
                            if (StringUtils.equals("UNICOM", smsSendconfigQueryRespVO.getChannelCode())) {
                                //中国联通
                                sendMsg2(smsSendconfigQueryRespVO);
                            } else if (StringUtils.equals("CMCC", smsSendconfigQueryRespVO.getChannelCode())) {
                                //中国移动
                                sendMsg(smsSendconfigQueryRespVO);
                            } else if (StringUtils.equals("UNEW", smsSendconfigQueryRespVO.getChannelCode())) {
                                //联通新渠道
                                sendMsg3(smsSendconfigQueryRespVO);
                            }

                        }
                    }
                }
            }
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
        return CommonResult.success(null);
    }

    @Async
    public void sendMsg3(SmsSendconfigQueryRespVO smsSendconfigQueryRespVO) {
        try {
            String telphone = "0717-6910001";
            if (StringUtils.isNotEmpty(smsSendconfigQueryRespVO.getSellerId())) {
                try {
                    AdminUserRespDTO user = adminUserApi.getUserIgnoreTenant(Long.parseLong(smsSendconfigQueryRespVO.getSellerId()));
                    if (StringUtils.isNotEmpty(user.getMobile())) {
                        //如果有售票员的电话则发送售票员的电话作为咨询电话
                        telphone = user.getMobile();
                    } else {
                        //读取配置文件默认参数
                        String mtelphone = configApi.getPlatformConfigValueByKey("telphone");
                        if (mtelphone != null) {
                            telphone = mtelphone;
                        }
                    }
                } catch (Exception e) {
                    log.error("用户信息获取异常" + smsSendconfigQueryRespVO.getSellerId(), e);
                }
            }

            //sxly
            String appId = smsSendconfigQueryRespVO.getApiKey();
            //Sx@202305
            String secretKey = smsSendconfigQueryRespVO.getApiSecret();
            //https://112.35.10.201:58888/sms/tmpsubmit
            String url = smsSendconfigQueryRespVO.getApiUrl();
            //jFKNw6Cis
            String signName = smsSendconfigQueryRespVO.getSignature();
            String content = smsSendconfigQueryRespVO.getSmsParms();
            //【1】产品名称； 【2】订单号； 【3】游玩日期； 【4】联系人；【5】购买数量； 【6】团名称； 【7】旅行社联系人； 【8】联系电话；【9】时间方案名称；【10】产品简称； 【11】咨询电话；
            content = content.replaceAll("【1】", smsSendconfigQueryRespVO.getProductName().substring(0, 10).replace("【", "").replace("】", "").replace("-", ""));
            content = content.replaceAll("【2】", smsSendconfigQueryRespVO.getOrderNo());
            content = content.replaceAll("【3】", smsSendconfigQueryRespVO.getUseDate().substring(0, 10));
            content = content.replaceAll("【4】", smsSendconfigQueryRespVO.getContactName());
            content = content.replaceAll("【5】", smsSendconfigQueryRespVO.getNum() + "");
            content = content.replaceAll("【6】", smsSendconfigQueryRespVO.getSourceName());
            content = content.replaceAll("【7】", smsSendconfigQueryRespVO.getContactName());
            content = content.replaceAll("【8】", smsSendconfigQueryRespVO.getMobile());
            content = content.replaceAll("【9】", smsSendconfigQueryRespVO.getRouteName());
            content = content.replaceAll("【10】", smsSendconfigQueryRespVO.getShortName());
            content = content.replaceAll("【11】", telphone);
            JSONArray parts = JSONUtil.parseArray(content);
            JSONArray templates = JSONUtil.parseArray(smsSendconfigQueryRespVO.getTemplateParams());
            Map<Object, Object> map = new HashMap<>();
            for (int i = 0; i < templates.size(); i++) {
                String key = templates.getStr(i);
                String value = parts.getStr(i);
                map.put(key, value);
            }
            String content1 = "【三峡旅游】" + StrUtil.format(smsSendconfigQueryRespVO.getSmsContent(), map);
            String mobile = smsSendconfigQueryRespVO.getMobile();
            log.error("[下单成功短信发送参数]：" + content1 + ";手机号：" + mobile);
            String params = SmsUtil.generateParams2(
                    String.join(",", mobile), content1, null, null, null
            );
            // 生成时间戳和token
            String timeStamp = String.valueOf(System.currentTimeMillis());
            String original = appId + timeStamp + secretKey;
            String token = md5(original).toLowerCase();
            // 构造请求头参数
            Map<String, String> headers = new HashMap<>();
            headers.put("userId", appId);
            headers.put("timeStamp", timeStamp);
            headers.put("token", token);
            log.error("[下单成功短信发送参数]：" + url + ";" + params);
            String result = sendPost(url, params, headers);
            log.error("[下单成功短信返回参数]：" + result);

            // 检查返回结果是否为有效的JSON格式
            SmsBatchSendRespDTO response = null;
            if (result != null && result.trim().startsWith("{")) {
                try {
                    response = JSONUtil.toBean(result, SmsBatchSendRespDTO.class);
                } catch (Exception e) {
                    log.error("短信接口返回JSON解析失败，原始响应内容: {}", result, e);
                }
            } else {
                log.error("短信接口返回非JSON格式响应，原始响应内容: {}", result);
            }

            if (response != null && response.getCode() != null && response.getCode() == 0) {
                log.error("[下单成功短信发送成功]：" + mobile);
                SmsSendLogDTO reqDTO = new SmsSendLogDTO();
                reqDTO.setId(IdWorker.getId());
                reqDTO.setTenantId(smsSendconfigQueryRespVO.getTenantId());
                reqDTO.setMobile(mobile);
                reqDTO.setSmsConfigId(mobile);
                reqDTO.setOrderNo(smsSendconfigQueryRespVO.getOrderNo());
                reqDTO.setSmsConfigId(smsSendconfigQueryRespVO.getId() + "");
                reqDTO.setResult(result);
                if (result.contains("success")) {
                    reqDTO.setStatus(1);
                } else {
                    reqDTO.setStatus(0);
                }
                reqDTO.setSmsContent(content);
                tradeOrderRepositoryService.insertSmsLog(reqDTO);
            } else {
                log.error("[短信发送失败]：" + result);

            }
        } catch (Exception e) {
            log.error("[下单成功短信发送失败]：" + e.getMessage());
            e.getMessage();
        }
    }

    @Async
    public void sendMsg2(SmsSendconfigQueryRespVO smsSendconfigQueryRespVO) {
        try {
            String telphone = "0717-6910001";
            if (StringUtils.isNotEmpty(smsSendconfigQueryRespVO.getSellerId())) {
                try {
                    AdminUserRespDTO user = adminUserApi.getUserIgnoreTenant(Long.parseLong(smsSendconfigQueryRespVO.getSellerId()));
                    if (StringUtils.isNotEmpty(user.getMobile())) {
                        //如果有售票员的电话则发送售票员的电话作为咨询电话
                        telphone = user.getMobile();
                    } else {
                        //读取配置文件默认参数
                        String mtelphone = configApi.getPlatformConfigValueByKey("telphone");
                        if (mtelphone != null) {
                            telphone = mtelphone;
                        }
                    }
                } catch (Exception e) {
                    log.error("用户信息获取异常" + smsSendconfigQueryRespVO.getSellerId(), e);
                }
            }

            //sxly
            String appId = smsSendconfigQueryRespVO.getApiKey();
            //Sx@202305
            String secretKey = smsSendconfigQueryRespVO.getApiSecret();
            //https://112.35.10.201:58888/sms/tmpsubmit
            String url = smsSendconfigQueryRespVO.getApiUrl();
            //jFKNw6Cis
            String signName = smsSendconfigQueryRespVO.getSignature();
            String input = getString(smsSendconfigQueryRespVO, telphone);
            JSONArray parts = JSONUtil.parseArray(input);
            JSONArray templates = JSONUtil.parseArray(smsSendconfigQueryRespVO.getTemplateParams());
            Map<Object, Object> map = new HashMap<>();
            for (int i = 0; i < templates.size(); i++) {
                String key = templates.getStr(i);
                String value = parts.getStr(i);
                map.put(key, value);
            }
            String content = StrUtil.format(smsSendconfigQueryRespVO.getSmsContent(), map);

            String mobile = smsSendconfigQueryRespVO.getMobile();
            log.error("[下单成功短信发送参数]：" + content + ";手机号：" + mobile);
            HttpClient httpclient = new HttpClient();
            PostMethod post = new PostMethod(url);
            post.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "gbk");
            post.addParameter("SpCode", signName);
            post.addParameter("LoginName", appId);
            post.addParameter("Password", secretKey);
            post.addParameter("MessageContent", content);
            post.addParameter("UserNumber", mobile);
            Random random = new Random();
            int ranNum = random.nextInt(9);
            String serialNumber = SmsUtil.createOrderNo(ranNum + "");
            if (serialNumber.length() > 20) {
                serialNumber = serialNumber.substring(0, 19);
            }
            post.addParameter("SerialNumber", serialNumber);
            post.addParameter("ScheduleTime", "");
            post.addParameter("templateId", smsSendconfigQueryRespVO.getApiTemplateId());
            post.addParameter("f", "1");
            httpclient.executeMethod(post);
            String result = new String(post.getResponseBody(), "gbk");
            log.error("[下单成功短信返回参数]：" + result);
            if (result.contains("result=0")) {
                log.error("[下单成功短信发送成功]：" + mobile);
                SmsSendLogDTO reqDTO = new SmsSendLogDTO();
                reqDTO.setId(IdWorker.getId());
                reqDTO.setTenantId(smsSendconfigQueryRespVO.getTenantId());
                reqDTO.setMobile(mobile);
                reqDTO.setSmsConfigId(mobile);
                reqDTO.setOrderNo(smsSendconfigQueryRespVO.getOrderNo());
                reqDTO.setSmsConfigId(smsSendconfigQueryRespVO.getId() + "");
                reqDTO.setResult(result);
                reqDTO.setStatus(1);
                reqDTO.setSmsContent(content);
                tradeOrderRepositoryService.insertSmsLog(reqDTO);
            } else {
                SmsSendLogDTO reqDTO = new SmsSendLogDTO();
                reqDTO.setId(IdWorker.getId());
                reqDTO.setTenantId(smsSendconfigQueryRespVO.getTenantId());
                reqDTO.setMobile(mobile);
                reqDTO.setSmsConfigId(mobile);
                reqDTO.setOrderNo(smsSendconfigQueryRespVO.getOrderNo());
                reqDTO.setSmsConfigId(smsSendconfigQueryRespVO.getId() + "");
                reqDTO.setResult(result);
                reqDTO.setStatus(0);
                reqDTO.setSmsContent(content);
                tradeOrderRepositoryService.insertSmsLog(reqDTO);
            }
        } catch (Exception e) {
            log.error("[下单成功短信发送失败]：" + e.getMessage());
            e.getMessage();
        }
    }

    @NotNull
    private static String getString(SmsSendconfigQueryRespVO smsSendconfigQueryRespVO, String telphone) {
        String smsParms = smsSendconfigQueryRespVO.getSmsParms();
        //【1】产品名称； 【2】订单号； 【3】游玩日期； 【4】联系人；【5】购买数量； 【6】团名称； 【7】旅行社联系人； 【8】联系电话；【9】时间方案名称；【10】产品简称； 【11】咨询电话；
        smsParms = smsParms.replaceAll("【1】", smsSendconfigQueryRespVO.getProductName().substring(0, 10).replace("【", "").replace("】", "").replace("-", ""));
        smsParms = smsParms.replaceAll("【2】", smsSendconfigQueryRespVO.getOrderNo());
        smsParms = smsParms.replaceAll("【3】", smsSendconfigQueryRespVO.getUseDate().substring(0, 10));
        smsParms = smsParms.replaceAll("【4】", smsSendconfigQueryRespVO.getContactName());
        smsParms = smsParms.replaceAll("【5】", smsSendconfigQueryRespVO.getNum() + "");
        smsParms = smsParms.replaceAll("【6】", smsSendconfigQueryRespVO.getSourceName());
        smsParms = smsParms.replaceAll("【7】", smsSendconfigQueryRespVO.getContactName());
        smsParms = smsParms.replaceAll("【8】", smsSendconfigQueryRespVO.getMobile());
        smsParms = smsParms.replaceAll("【9】", smsSendconfigQueryRespVO.getRouteName());
        smsParms = smsParms.replaceAll("【10】", smsSendconfigQueryRespVO.getShortName());
        smsParms = smsParms.replaceAll("【11】", telphone);
        return smsParms;
    }

    @Async
    public void sendMsg(SmsSendconfigQueryRespVO smsSendconfigQueryRespVO) {
        try {
            String telphone = "0717-6910001";
            if (StringUtils.isNotEmpty(smsSendconfigQueryRespVO.getSellerId())) {
                try {
                    AdminUserRespDTO user = adminUserApi.getUserIgnoreTenant(Long.parseLong(smsSendconfigQueryRespVO.getSellerId()));
                    if (StringUtils.isNotEmpty(user.getMobile())) {
                        //如果有售票员的电话则发送售票员的电话作为咨询电话
                        telphone = user.getMobile();
                    } else {
                        //读取配置文件默认参数
                        String mtelphone = configApi.getPlatformConfigValueByKey("telphone");
                        if (mtelphone != null) {
                            telphone = mtelphone;
                        }
                    }
                } catch (Exception e) {
                    log.error("用户信息获取异常" + smsSendconfigQueryRespVO.getSellerId(), e);
                }
            }

            //sxly
            String appId = smsSendconfigQueryRespVO.getApiKey();
            //Sx@202305
            String secretKey = smsSendconfigQueryRespVO.getApiSecret();
            //https://112.35.10.201:58888/sms/tmpsubmit
            String url = smsSendconfigQueryRespVO.getApiUrl();
            //jFKNw6Cis
            String signName = smsSendconfigQueryRespVO.getSignature();
            String content = smsSendconfigQueryRespVO.getSmsParms();
            //【1】产品名称； 【2】订单号； 【3】游玩日期； 【4】联系人；【5】购买数量； 【6】团名称； 【7】旅行社联系人； 【8】联系电话；【9】时间方案名称；【10】产品简称； 【11】咨询电话；
            content = content.replaceAll("【1】", smsSendconfigQueryRespVO.getProductName().substring(0, 10).replace("【", "").replace("】", "").replace("-", ""));
            content = content.replaceAll("【2】", smsSendconfigQueryRespVO.getOrderNo());
            content = content.replaceAll("【3】", smsSendconfigQueryRespVO.getUseDate().substring(0, 10));
            content = content.replaceAll("【4】", smsSendconfigQueryRespVO.getContactName());
            content = content.replaceAll("【5】", smsSendconfigQueryRespVO.getNum() + "");
            content = content.replaceAll("【6】", smsSendconfigQueryRespVO.getSourceName());
            content = content.replaceAll("【7】", smsSendconfigQueryRespVO.getContactName());
            content = content.replaceAll("【8】", smsSendconfigQueryRespVO.getMobile());
            content = content.replaceAll("【9】", smsSendconfigQueryRespVO.getRouteName());
            content = content.replaceAll("【10】", smsSendconfigQueryRespVO.getShortName());
            content = content.replaceAll("【11】", telphone);

            String mobile = smsSendconfigQueryRespVO.getMobile();
            log.error("[下单成功二次确认短信发送参数]：" + content + ";手机号：" + mobile);

            String params = SmsUtil.generateParams(String.join(",", mobile), content, smsSendconfigQueryRespVO.getApiTemplateId() + "", appId, signName, secretKey);
            log.error("[下单成功二次确认短信发送参数]：" + url + ";" + params);
            String result = sendPost(url, params, null);
            log.error("[下单成功二次确认短信返回参数]：" + result);
            JSONObject resultObject = JSONUtil.parseObj(result);

            if ("true".equals(resultObject.getStr("success"))) {
                log.error("[下单成功二次确认短信发送成功]：" + mobile);
                SmsSendLogDTO reqDTO = new SmsSendLogDTO();
                reqDTO.setId(IdWorker.getId());
                reqDTO.setTenantId(smsSendconfigQueryRespVO.getTenantId());
                reqDTO.setMobile(mobile);
                reqDTO.setSmsConfigId(mobile);
                reqDTO.setOrderNo(smsSendconfigQueryRespVO.getOrderNo());
                reqDTO.setSmsConfigId(smsSendconfigQueryRespVO.getId() + "");
                reqDTO.setResult(result);
                if (result != null && result.indexOf("成功") != -1) {
                    reqDTO.setStatus(1);
                } else {
                    reqDTO.setStatus(0);
                }
                reqDTO.setSmsContent(content);
                tradeOrderRepositoryService.insertSmsLog(reqDTO);
            } else {
                resultObject.getStr("rspcod");
            }
        } catch (Exception e) {
            log.error("[下单成功二次确认短信发送失败]：" + e.getMessage());
            e.getMessage();
        }
    }

    private static class MyHostnameVerifier implements HostnameVerifier {
        @Override
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    }

    public static String sendPost(String url, String param, Map<String, String> headParam) {
        PrintWriter out = null;
        BufferedReader in = null;
        String result = "";
        try {
            URL realUrl = new URL(url);
            // 打开和URL之间的连接
            HttpURLConnection conn;
            if ("https".equalsIgnoreCase(realUrl.getProtocol())) {
                HttpsURLConnection httpsConn = (HttpsURLConnection) realUrl.openConnection();
                httpsConn.setHostnameVerifier(new MyHostnameVerifier());
                conn = httpsConn;
            } else {
                conn = (HttpURLConnection) realUrl.openConnection();
            }
            // 设置通用的请求属性
            conn.setRequestProperty("accept", "*/*");
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Accept-Charset", "UTF-8");
            conn.setRequestProperty("Content-Type", "application/json");
            conn.setRequestProperty("charset", "UTF-8");
            if (headParam != null) {
                for (Map.Entry<String, String> entry : headParam.entrySet()) {
                    conn.setRequestProperty(entry.getKey(), entry.getValue());
                }
            }
            // 发送POST请求必须设置如下两行
            conn.setUseCaches(false);
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setConnectTimeout(1000000);
            conn.setReadTimeout(1000000);

//            System.setProperty("sun.net.client.defaultConnectTimeout", "1000000");
//            System.setProperty("sun.net.client.defaultReadTimeout", "1000000");
            // 获取URLConnection对象对应的输出流
            if (StringUtils.isNotBlank(param)) {
                out = new PrintWriter(new OutputStreamWriter(conn.getOutputStream(), "utf-8"));
                out.write(param);
                // flush输出流的缓冲
                out.flush();
            }

            // 定义BufferedReader输入流来读取URL的响应
            in = new BufferedReader(
                    new InputStreamReader(conn.getInputStream(), "utf-8"));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            System.out.println("发送 POST 请求出现异常！" + e);
            e.printStackTrace();
        }
        //使用finally块来关闭输出流、输入流
        finally {
            try {
                if (out != null) {
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            //LogUtil.appLog.info("sendPost>>"+url+">>"+param+">>>"+headParam+">>>>>执行时间："+(System.currentTimeMillis()-s0));
        }
        return result;
    }

    private String md5(String input) {
        try {
            java.security.MessageDigest md = java.security.MessageDigest.getInstance("MD5");
            byte[] array = md.digest(input.getBytes());
            StringBuilder sb = new StringBuilder();
            for (byte b : array) {
                sb.append(String.format("%02x", b));
            }
            return sb.toString();
        } catch (java.security.NoSuchAlgorithmException e) {
            throw new RuntimeException("MD5加密失败", e);
        }
    }

    private CommonResult<TradeRefundCreateRespVO> doCancelConfirmOrder(LoginUser loginUser, TradeOrderDO tradeOrderDO, boolean isNotice) {

        TradeRefundCreateReqVO refundCreateReqVO = new TradeRefundCreateReqVO();
        refundCreateReqVO.setRefundAmount(tradeOrderDO.getPayAmount());
        refundCreateReqVO.setRefundBackType(REFUND_BACK_TYPE_ORIGINAL);
        refundCreateReqVO.setRefundType(REFUND_TYPE_ORDER);
        refundCreateReqVO.setRefundMethod(REFUND_METHOD_CONFIRM_ORDER);
        refundCreateReqVO.setRefundChannel(RefundChannelEnum.BACKEND.getType());
        refundCreateReqVO.setRefundReason("二次确认订单取消");
        refundCreateReqVO.setIgnorePlatRefund(isNotice);

        List<TradeRefundCreateReqVO.RefundOrderInfo> orderInfoList = new ArrayList<>();
        TradeRefundCreateReqVO.RefundOrderInfo refundOrderInfo = new TradeRefundCreateReqVO.RefundOrderInfo();
        refundOrderInfo.setOrderNo(tradeOrderDO.getOrderNo());
        refundOrderInfo.setOrderId(tradeOrderDO.getId());
        orderInfoList.add(refundOrderInfo);
        refundCreateReqVO.setOrderInfoList(orderInfoList);
        return adminTradeOrderService.refund(loginUser, refundCreateReqVO);
    }

    @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.CONFIRM_ORDER)
    public void confirmAgencyOrder(LoginUser loginUser, String originOrderNo, Integer sendSms) {
        List<TradeOrderDO> orderList = tradeOrderRepositoryService.getByExternalOriginOrderNo(originOrderNo);
        boolean confirm = orderList.stream().allMatch(item -> ObjectUtil.equal(item.getConfirmType(), TradeOrderConfirmTypeEnum.CONFIRMED.getType()));
        boolean cancel = orderList.stream().allMatch(item -> ObjectUtil.equal(item.getConfirmType(), TradeOrderConfirmTypeEnum.CANCEL.getType()));
        if (confirm || cancel) {

            Integer type = confirm ? TradeOrderConfirmTypeEnum.CONFIRMED.getType() : TradeOrderConfirmTypeEnum.CANCEL.getType();
            TradeOrderDO tradeOrderDO = tradeOrderRepositoryService.getOrderByOrderNoWithoutTenant(originOrderNo);
            TenantUtils.execute(tradeOrderDO.getTenantId(), () -> {

                confirmOrder(loginUser, tradeOrderDO.getId(), type, sendSms);
            });
        }
    }

    @Override
    @TradeOrderLog(operateType = TradeOrderOperateTypeEnum.CONFIRM_ORDER)
    public void handleConfirmOrderMessage(Long orderId) {
        String lockKey = String.format(UPDATE_CONFIRM_ORDER_LOCK, orderId);
        RLock lock = redissonClient.getLock(lockKey);
        lock.lock();
        try {
            TradeOrderDO tradeOrderDO = tradeOrderRepositoryService.getById(orderId);
            if (ObjectUtils.equalsAny(tradeOrderDO.getConfirmType(), TradeOrderConfirmTypeEnum.CONFIRMED.getType()
                    , TradeOrderConfirmTypeEnum.CANCEL.getType(), TradeOrderConfirmTypeEnum.NO_NEED.getType())) {
                log.info("收到二次确定订单延迟消息，无需处理。{}", orderId);
                return;
            }
            //取消订单
            LoginUser loginUser = new LoginUser();
            loginUser.setId(0L);
            CommonResult<TradeRefundCreateRespVO> refundResult = doCancelConfirmOrder(loginUser, tradeOrderDO, false);
            if (refundResult.isError() || refundResult.getData().getSuccessList().size() != 1) {
                log.error("收到二次确定订单延迟消息，自动退款失败。{}", JsonUtils.toJsonString(refundResult));
            }
            tradeOrderRepositoryService.updateOrderConfirmType(orderId, TradeOrderConfirmTypeEnum.CANCEL.getType());
            //如果是平台订单，同步下旅行社订单
            if (ObjectUtil.equal(tradeOrderDO.getSellMethod(), SellMethodEnum.OTC.getType())) {
                confirmAgencyOrder(loginUser, tradeOrderDO.getExternalOriginOrderNo(), 1);
            }
            TradeOrderLogUtils.setOrderInfo(orderId, tradeOrderDO.getOrderStatus(), tradeOrderDO.getOrderStatus(), MapUtil.<String, Object>builder().put("confirmPerson", "系统操作")
                    .put("confirmType", TradeOrderConfirmTypeEnum.CANCEL.getName()).build());
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }

    /**
     * 过期自动退过期时间
     *
     * @param overdueDay
     * @return
     */
    @Override
    public CommonResult<?> autoRefundByOverdue(String overdueDay) {
        Asserts.isTrue(StrUtil.isNotBlank(overdueDay), "过期日期不能为空");

        int pageSize = 500;
        int pageNo = 1;
        IPage<TradeDetailDO> page = new Page<>(pageNo, pageSize);
        StringBuilder result = new StringBuilder();
        try {
            while (pageNo >= 1) {
                page.setCurrent(pageNo);
                IPage<TradeDetailDO> pageData = tradeDetailMapper.selectOverdueOrderDetailForRefund(page, overdueDay);
                if (CollUtil.isEmpty(pageData.getRecords())) {
                    break;
                }
                Map<Long, List<TradeDetailDO>> tenantMap = pageData.getRecords().stream().collect(Collectors.groupingBy(TradeDetailDO::getTenantId));
                tenantMap.forEach((tenantId, detailList) -> {
                    TenantUtils.execute(tenantId, () -> {
                        TradeRefundCreateReqVO refundCreateReqVO = new TradeRefundCreateReqVO();
                        refundCreateReqVO.setRefundBackType(REFUND_BACK_TYPE_ORIGINAL);
                        refundCreateReqVO.setRefundType(REFUND_TYPE_ITEM);
                        refundCreateReqVO.setRefundMethod(REFUND_METHOD_OVERDUE_ORDER);
                        refundCreateReqVO.setRefundChannel(RefundChannelEnum.BACKEND.getType());
                        refundCreateReqVO.setRefundReason("过期自动退款");
                        refundCreateReqVO.setIgnorePlatRefund(true);

                        List<TradeRefundCreateReqDTO.RefundItem> refundItemList = detailList.stream().map(detail -> {
                            TradeRefundCreateReqDTO.RefundItem refundItem = new TradeRefundCreateReqDTO.RefundItem();
                            refundItem.setOrderId(detail.getOrderId());
                            refundItem.setOrderDetailId(detail.getId());
                            refundItem.setOriginRefundAmount(detail.getActualPrice());
                            refundItem.setRefundAmount(detail.getActualPrice());
                            refundItem.setVoucherCode(detail.getVoucherCode());
                            refundItem.setFee(BigDecimal.ZERO);
                            return refundItem;
                        }).collect(Collectors.toList());
                        refundCreateReqVO.setRefundItemList(refundItemList);

                        //发起退款
                        LoginUser loginUser = new LoginUser();
                        loginUser.setId(0L);
                        CommonResult<TradeRefundCreateRespVO> refundResult = adminTradeOrderService.refund(loginUser, refundCreateReqVO);
                        result.append(JsonUtils.toJsonString(refundResult));
                    });
                });
                pageNo++;
            }
        } catch (Exception e) {
            log.error("批量过期退异常", e);
        }

        return CommonResult.success(result.toString());
    }


    /**
     * 根据当前时间完结订单
     * 完结状态 平台订单（有效订单）出行日期三天后变成已完结
     * 内部旅行社订单（有效订单）出行日期七天后变成已完结
     */
    @Override
    public String finishOrder(Date taskDate) {
        Asserts.isTrue(taskDate != null, "任务日期不能为空");
        //平台
        Date endDate = DateUtil.endOfDay(DateUtil.offsetDay(taskDate, -4));
        StringBuilder message = new StringBuilder();
        int affectRows = tradeOrderRepositoryService.updateOrderFinishStatus(Arrays.asList(SellMethodEnum.OTA.getType(), SellMethodEnum.OTC.getType()
                , SellMethodEnum.OTA_SYSTEM.getType(), SellMethodEnum.OTC_MOVE_ORDER.getType()), DateUtil.formatDateTime(endDate));
        message.append("平台订单执行数量：").append(affectRows);
        //内部旅行社
        endDate = DateUtil.endOfDay(DateUtil.offsetDay(taskDate, -8));
        affectRows = tradeOrderRepositoryService.updateOrderFinishStatus(Arrays.asList(SellMethodEnum.WINDOW.getType(), SellMethodEnum.MINI_APP.getType()
                , SellMethodEnum.AUTO_MACHINE.getType()), DateUtil.formatDateTime(endDate));
        message.append("内部旅行社订单执行数量：").append(affectRows);
        return message.toString();
    }


    /**
     * 验证导游代退数据
     *
     * @param guideRefundReqDTO
     * @return
     */
    @Override
    public GuideRefundConfirmRespDTO getAndValidateGuideRefundData(GuideRefundReqDTO guideRefundReqDTO) {
        TradeOrderDO tradeOrderDO = tradeOrderRepositoryService.getById(guideRefundReqDTO.getOrderId());
        Asserts.isTrue(tradeOrderDO != null, "订单不存在");
        //退款中的订单不能申请
        Asserts.isTrue(ObjectUtils.equalsAny(tradeOrderDO.getOrderStatus(), TradeOrderStatusEnum.UNUSED.getStatus(), TradeOrderStatusEnum.PART_CHECK.getStatus()
                , TradeOrderStatusEnum.PARTIAL_REFUND.getStatus()), "当前订单状态不允许申请代退");
        //此处只验证代退的规格是否符合要求，大改小
        List<Long> detailIdList = guideRefundReqDTO.getRefundDetailList().stream().map(GuideRefundReqDTO.refundDetail::getTradeDetailId).collect(Collectors.toList());
        List<TradeDetailBO> tradeDetailBOList = tradeOrderRepositoryService.getTradeDetailWithBase(guideRefundReqDTO.getOrderId(), detailIdList);
        Asserts.isTrue(tradeDetailBOList.size() == detailIdList.size(), "代退明细数据不正确");
        HashMap<Long, ProductSpuRespDTO> productMap = new HashMap<>();
        BigDecimal amount = BigDecimal.ZERO;
        List<GuideRefundConfirmRespDTO.refundDetail> refundAmountDetailList = new ArrayList<>();
        for (TradeDetailBO tradeDetailBO : tradeDetailBOList) {
            Asserts.isTrue(ObjectUtils.equalsAny(tradeDetailBO.getVoucherStatus(), VoucherStatusEnum.UNUSED.getStatus(), VoucherStatusEnum.PART_VERIFIED.getStatus()), "当前订单状态不允许申请代退");
            List<GuideRefundReqDTO.refundDetail> refundDetailList = guideRefundReqDTO.getRefundDetailList().stream().filter(item -> ObjectUtil.equal(item.getTradeDetailId(), tradeDetailBO.getId())).collect(Collectors.toList());
            Asserts.isTrue(refundDetailList.size() == 1, "代退数据重复，请检查");
            //判断代退规格是否大改小，根据价格判断
            ProductSpuRespDTO productSpuRespDTO = productMap.computeIfAbsent(tradeDetailBO.getProductId()
                    , key -> productApi.getCalendarProduct(tradeDetailBO.getProductId(), DateUtil.formatDate(DateUtils.of(tradeDetailBO.getUseDate())), tradeDetailBO.getRoutePlanId()).getCheckedData());
            //获取并验证变更规格的价格
            BigDecimal price = validateChangeSpecType(tradeDetailBO, refundDetailList.get(0), productSpuRespDTO);
            Asserts.isTrue(price.compareTo(tradeDetailBO.getActualPrice()) <= 0, "差价金额{}大于产品可退金额{}", price, tradeDetailBO.getActualPrice());
            amount = amount.add(price);

            GuideRefundConfirmRespDTO.refundDetail refundDetail = new GuideRefundConfirmRespDTO.refundDetail();
            refundDetail.setTradeDetailId(tradeDetailBO.getId());
            refundDetail.setRefundAmount(price);
            refundAmountDetailList.add(refundDetail);
        }

        GuideRefundConfirmRespDTO respDTO = new GuideRefundConfirmRespDTO();
        respDTO.setRefundAmount(amount);
        respDTO.setRefundDetailList(refundAmountDetailList);
        return respDTO;
    }

    private BigDecimal validateChangeSpecType(TradeDetailBO tradeDetailBO, GuideRefundReqDTO.refundDetail refundDetail, ProductSpuRespDTO productSpuRespDTO) {
        BigDecimal originPrice = getPriceBySpecType(refundDetail.getOriginSpecType(), tradeDetailBO.getTradeDetailBaseList(), productSpuRespDTO);
        BigDecimal price = getPriceBySpecType(refundDetail.getSpecType(), tradeDetailBO.getTradeDetailBaseList(), productSpuRespDTO);
        Asserts.isTrue(price.compareTo(originPrice) <= 0, "{}不能变更为{}", refundDetail.getOriginSpecType(), refundDetail.getSpecType());
        return originPrice.subtract(price);
    }

    private BigDecimal getPriceBySpecType(String specType, List<TradeDetailBaseDO> tradeDetailBaseList, ProductSpuRespDTO productSpuRespDTO) {
        //验证价格 固定sku价格（必选且只有一种规格+通用价格） + 非必选 + 必选多规格
        //此处只考虑平台订单
        ProductSkuRespDTO productSku = getProductSku(specType, productSpuRespDTO);
        BigDecimal price = productSku == null ? BigDecimal.ZERO : productSku.getSalePrice();
        for (TradeDetailBaseDO orderDetailBase : tradeDetailBaseList) {
            ProductGroupRespDTO productGroup = getProductGroup(specType, orderDetailBase, productSpuRespDTO);
            if (ObjectUtil.equal(productGroup.getNeedChoose(), NO) || ObjectUtil.equal(productGroup.getNeedChoose(), YES) && productGroup.getSkuId() == null && ObjectUtil.notEqual(productGroup.getSpecType(), SpecTypeEnum.COMMON.getType())) {
                price = price.add(productGroup.getSalePrice());
            }
        }
        return price;
    }

    private ProductSkuRespDTO getProductSku(String specType, ProductSpuRespDTO productSpuRespDTO) {
        if (CollUtil.isEmpty(productSpuRespDTO.getProductSkuList())) {
            return null;
        }
        return productSpuRespDTO.getProductSkuList().stream().filter(productSkuRespDTO -> StrUtil.equals(specType, productSkuRespDTO.getSpecType())).findFirst()
                .orElse(null);
    }

    private ProductGroupRespDTO getProductGroup(String specType, TradeDetailBaseDO orderDetailBase, ProductSpuRespDTO productSpuRespDTO) {

        List<ProductGroupRespDTO> productGroupList = productSpuRespDTO.getProductGroupList();

        ProductGroupRespDTO productGroupRespDTO = productGroupList.stream().filter(item -> ObjectUtil.equal(item.getProductBaseId(), orderDetailBase.getProductBaseId())
                && ObjectUtil.equal(item.getSpecType(), specType)).findFirst().orElseThrow(() -> exception(GUIDE_REFUND_PRODUCT_BASE_NOT_EXISTS, orderDetailBase.getProductBaseName()));
        Asserts.isTrue(ObjectUtil.equal(productGroupRespDTO.getUseStatus(), YES), "基础产品已下架,{}", productGroupRespDTO.getProductBaseName());
        return productGroupRespDTO;
    }

    /**
     * 确认代退，平台退款金额
     *
     * @param guideRefundReqDTO
     * @return
     */
    @Override
    public GuideRefundConfirmRespDTO confirmChangeOrderDueToGuideRefund(GuideRefundReqDTO guideRefundReqDTO) {
        Asserts.isTrue(guideRefundReqDTO.getRefundId() != null, "代退业务ID不能为空");
        Asserts.isTrue(guideRefundReqDTO.getGuideRefundAmount() != null && guideRefundReqDTO.getGuideRefundAmount().compareTo(BigDecimal.ZERO) > 0
                , "代退金额不能为0");
        //1.获取改签规格价格
        GuideRefundConfirmRespDTO respDTO = getAndValidateGuideRefundData(guideRefundReqDTO);
        respDTO.setRefundId(guideRefundReqDTO.getRefundId());
        return respDTO;
    }

    @Override
    public GuideRefundRespDTO changeOrderDueToGuideRefund(GuideRefundReqDTO guideRefundReqDTO) {
        Asserts.isTrue(guideRefundReqDTO.getRefundId() != null, "代退业务ID不能为空");
        Asserts.isTrue(guideRefundReqDTO.getRefundAmount() != null, "平台退款金额不能为空");
        Asserts.isTrue(guideRefundReqDTO.getGuideRefundAmount() != null && guideRefundReqDTO.getGuideRefundAmount().compareTo(BigDecimal.ZERO) > 0
                , "代退金额不能为0");
        return null;
//        String lockKey = String.format(UPDATE_GUIDE_REFUND_LOCK, guideRefundReqDTO.getOrderId());
//        RLock lock = redissonClient.getLock(lockKey);
//        lock.lock();
//        try {
//            GuideRefundRespDTO respDTO = new GuideRefundRespDTO();
////            //获取代退业务单的状态，防止重复点击
//            GuideRefundApplyRespDTO refundApplyRespDTO = dispatchApi.getGuideRefundApply(guideRefundReqDTO.getRefundId().toString()).getCheckedData();
//            Asserts.isTrue(ObjectUtil.equal(refundApplyRespDTO.getStatus(), GuideRefundStateEnum.APPLYING.getState()), "当前申请单状态不能发起后续流程");
//
//            GuideRefundConfirmRespDTO confirmRespDTO = getAndValidateGuideRefundData(guideRefundReqDTO);
//            Asserts.isTrue(guideRefundReqDTO.getRefundAmount().compareTo(confirmRespDTO.getRefundAmount()) == 0, "平台退款金额不正确");
//            TradeOrderDO tradeOrderDO = tradeOrderRepositoryService.getById(guideRefundReqDTO.getOrderId());
//            if (ObjectUtils.equalsAny(tradeOrderDO.getSellMethod(), SellMethodEnum.OTC.getType())) {
//                //内部旅行社，旅客订单直接原路退款，平台订单再退款
//                refundInnerAgencyBeforeGuideRefund(guideRefundReqDTO, tradeOrderDO);
//
//            } else if (ObjectUtils.equalsAny(tradeOrderDO.getSellMethod(), SellMethodEnum.OTA.getType(), SellMethodEnum.OTA_SYSTEM.getType(), SellMethodEnum.OTC_MOVE_ORDER.getType())) {
//                //外部旅行社，需先扣预存款，平台订单再退款。
//                PayOrderRespVO payOrderRespVO = chargebackBeforeGuideRefund(tradeOrderDO, guideRefundReqDTO);
//                //平台退款
//                CommonResult<Boolean> commonResult = refundPlatBeforeGuideRefund(guideRefundReqDTO);
//                if (commonResult.isError() && commonResult.getData()) {
//                    log.error("导游代退，平台退款异常,退回已扣预存款{}", commonResult.getMsg());
//                    //自动退已扣预付款
//                    tradeRefundService.autoRefundByPayOrder(payOrderRespVO.getOrderPayId());
//                    Asserts.isTrue(false, commonResult.getCode(), commonResult.getMsg());
//                }
//
//                //返回支付单ID
//                respDTO.setPayOrderId(payOrderRespVO.getOrderPayId());
//
//            } else {
//                Asserts.isTrue(false, "当前渠道不支持代退");
//            }
//
//            return respDTO;
//        } finally {
//            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
//                lock.unlock();
//            }
//        }
    }

    private PayOrderRespVO chargebackBeforeGuideRefund(TradeOrderDO tradeOrderDO, GuideRefundReqDTO guideRefundReqDTO) {
        //代扣预付款，如果预付款失败，则失败
        PayOrderReqVO payOrderReqVO = new PayOrderReqVO();
        payOrderReqVO.setAccountId(tradeOrderDO.getSourceId());
        payOrderReqVO.setAccountName(tradeOrderDO.getSourceName());
        payOrderReqVO.setPayType(PayTypeEnum.ADVANCE_PAYMENT.getType());
        payOrderReqVO.setPayAmount(guideRefundReqDTO.getGuideRefundAmount());
        payOrderReqVO.setPaySource(PaySourceEnum.GUIDE_REFUND_PLAT_CHARGEBACK.getType());
        payOrderReqVO.setOrderId(guideRefundReqDTO.getRefundId());
        payOrderReqVO.setTradeType(DistributorTradeTypeEnum.GUIDE_REFUND_BALANCE_TRANS.getType());
        payOrderReqVO.setStoreId(tradeOrderDO.getStoreId());
        CommonResult<PayOrderRespVO> result = tradeOrderPayService.payOuterOrder(payOrderReqVO);
        return result.getCheckedData();
    }

    private CommonResult<Boolean> refundPlatBeforeGuideRefund(GuideRefundReqDTO guideRefundReqDTO) {
        return tradeRefundService.refundByGuideRefund(guideRefundReqDTO.getOrderId(), guideRefundReqDTO.getRefundId(), guideRefundReqDTO.getRefundAmount(), REFUND_RECORD_TYPE_GUIDE_PLAT);
    }

    private void refundInnerAgencyBeforeGuideRefund(GuideRefundReqDTO guideRefundReqDTO, TradeOrderDO tradeOrderDO) {
        //根据平台订单查询内部旅行社订单
        AtomicReference<TradeOrderDO> innerOrderAR = new AtomicReference<>();
        TenantUtils.executeIgnore(() -> {
            innerOrderAR.set(tradeOrderRepositoryService.getOrderByNo(tradeOrderDO.getExternalOriginOrderNo()));
        });
        TradeOrderDO innerOrder = innerOrderAR.get();
        TenantUtils.execute(innerOrder.getTenantId(), () -> {
            //根据内部旅行社订单，直接退款给游客
            CommonResult<Boolean> commonResult = tradeRefundService.refundByGuideRefund(innerOrder.getId(), guideRefundReqDTO.getRefundId(), guideRefundReqDTO.getGuideRefundAmount(), REFUND_RECORD_TYPE_GUIDE_INNER);
            if (commonResult.isError() && commonResult.getData()) {
                log.error("导游代退，旅行社退款异常{}", commonResult.getMsg());
                Asserts.isTrue(false, commonResult.getCode(), commonResult.getMsg());
            }
        });
    }

//    private TradeOrderBizServiceImpl getSelf() {
//        return SpringUtil.getBean(getClass());
//    }


}
