package com.pz.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.json.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.pz.common.config.KbProperties;
import com.pz.common.core.domain.PageQuery;
import com.pz.common.core.domain.model.LoginUser;
import com.pz.common.core.page.TableDataInfo;
import com.pz.common.enums.CommonOrderStatus;
import com.pz.common.enums.TotalOrderStatus;
import com.pz.common.exception.ServiceException;
import com.pz.common.helper.LoginHelper;
import com.pz.common.utils.HttpUtils;
import com.pz.common.utils.JsonUtils;
import com.pz.merchant.domain.Company;
import com.pz.merchant.domain.Employees;
import com.pz.merchant.domain.EmployeesDivide;
import com.pz.merchant.domain.vo.EmployeesVo;
import com.pz.merchant.domain.vo.SonOrderVo;
import com.pz.merchant.mapper.CompanyMapper;
import com.pz.merchant.mapper.EmployeesDivideMapper;
import com.pz.merchant.mapper.EmployeesMapper;
import com.pz.merchant.service.ISonOrderService;
import com.pz.merchant.service.impl.SonOrderServiceBuilder;
import com.pz.system.datastructure.OrderDelayQueue;
import com.pz.system.datastructure.TotalOrderDelayOperator;
import com.pz.system.domain.*;
import com.pz.system.domain.bo.CreateOrderBo;
import com.pz.system.domain.bo.TotalOrderBo;
import com.pz.system.domain.vo.AccompanyDemandVo;
import com.pz.system.domain.vo.StoreGoodsVo;
import com.pz.system.domain.vo.TotalOrderVo;
import com.pz.system.domain.vo.UserAddressVo;
import com.pz.system.mapper.*;
import com.pz.system.service.IPayService;
import com.pz.system.service.ITotalOrderService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * 总订单Service业务层处理
 *
 * @author ruoyi
 * @date 2023-09-08
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class TotalOrderServiceImpl implements ITotalOrderService {
    private final TotalOrderMapper baseMapper;

    private final SonOrderServiceBuilder serviceBuilder;

    private final YypzOrderMapper yypzOrderMapper;

    private final ZqghOrderMapper zqghOrderMapper;

    private final ZyphOrderMapper zyphOrderMapper;

    private final DbghOrderMapper dbghOrderMapper;

    private final DbmyOrderMapper dbmyOrderMapper;

    private final DbwzOrderMapper dbwzOrderMapper;

    private final StoreOrderMapper storeOrderMapper;

    private final BusinessMapper businessMapper;

    private final UserVsitorMapper userVsitorMapper;

    private final ServicesMapper servicesMapper;

    private final StoreGoodsTagMapper storeGoodsTagMapper;

    private final StoreGoodsMapper storeGoodsMapper;

    private final IPayService iPayService;

    private final HospitalMapper hospitalMapper;

    private final DoctorMapper doctorMapper;

    private final DepartmentMapper departmentMapper;

    private final EmployeesMapper employeesMapper;

    private final EmployeesDivideMapper employeesDivideMapper;

    private final PaymentRecordMapper paymentRecordMapper;

    private final OrderDelayQueue delayQueue;

    private final KbProperties kbProperties;

    private final UserAddressMapper userAddressMapper;

    private final SysUserMapper sysUserMapper;

    private final UserRefundMapper userRefundMapper;

    private final CompanyMapper companyMapper;

    // 时间格式化
    private static final DateTimeFormatter FORMATTER = new DateTimeFormatterBuilder()
        .parseCaseInsensitive()
        .append(DateTimeFormatter.ISO_LOCAL_DATE)
        .appendLiteral(' ')
        .append(DateTimeFormatter.ISO_LOCAL_TIME)
        .toFormatter(Locale.getDefault(Locale.Category.FORMAT));

    @Override
    public TotalOrderVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询总订单详情
     */
    @Override
    public TotalOrderVo queryByAppId(Integer id) {
        // TODO 待优化
        TotalOrderVo totalOrderVo = baseMapper.selectByOrderId(id);

        // 获取陪诊员用户id
        Optional.ofNullable(employeesMapper.selectVoById(totalOrderVo.getEmId()))
            .map(EmployeesVo::getUid)
            .ifPresent(totalOrderVo::setEUserId);
        Optional.ofNullable(employeesMapper.selectVoById(totalOrderVo.getEmId()))
            .map(EmployeesVo::getName)
            .ifPresent(totalOrderVo::setEmName);
        if (totalOrderVo.getBusinessId() == 1) {// 预约陪诊

            YypzOrder yypzOrder = yypzOrderMapper.selectOne(new LambdaQueryWrapper<YypzOrder>().eq(YypzOrder::getOrderId, totalOrderVo.getId()));
            totalOrderVo.setServiceStatus(
                yypzOrder.getStatus()
            );
            // totalOrderVo = BeanUtil.toBean(yypzOrder, TotalOrderVo.class);
            Optional.ofNullable(hospitalMapper.selectById(yypzOrder.getHid()))
                .map(Hospital::getName)
                .ifPresent(totalOrderVo::setHospital);
            Optional.ofNullable(userVsitorMapper.selectById(yypzOrder.getVisitor()))
                .map(UserVsitor::getName)
                .ifPresent(totalOrderVo::setVisitor);
            Optional.ofNullable(departmentMapper.selectById(yypzOrder.getDid()))
                .map(Department::getTitle)
                .ifPresent(totalOrderVo::setDepartment);
            //totalOrderVo.setHospital(hospitalMapper.selectById(yypzOrder.getHid()).getName());
            //totalOrderVo.setVisitor(userVsitorMapper.selectById(yypzOrder.getVisitor()).getName());
            //totalOrderVo.setDepartment(departmentMapper.selectById(yypzOrder.getDid()).getTitle());
            totalOrderVo.setPhone(yypzOrder.getPhone());
            totalOrderVo.setVisitTime(yypzOrder.getVisitTime());
            totalOrderVo.setOverTime(yypzOrder.getOverTime());
            totalOrderVo.setVoucher(yypzOrder.getVoucher());
            totalOrderVo.setPzRemark(yypzOrder.getRemark());


        } else if (totalOrderVo.getBusinessId() == 2) {// 代办挂号

            DbghOrder dbghOrder = dbghOrderMapper.selectOne(new LambdaQueryWrapper<DbghOrder>().eq(DbghOrder::getOrderId, totalOrderVo.getId()));
            totalOrderVo.setServiceStatus(
                dbghOrder.getStatus()
            );
            // totalOrderVo = BeanUtil.toBean(dbghOrder, TotalOrderVo.class);
            Optional.ofNullable(hospitalMapper.selectById(dbghOrder.getHid()))
                .map(Hospital::getName)
                .ifPresent(totalOrderVo::setHospital);
            Optional.ofNullable(userVsitorMapper.selectById(dbghOrder.getVisitor()))
                .map(UserVsitor::getName)
                .ifPresent(totalOrderVo::setVisitor);
            Optional.ofNullable(departmentMapper.selectById(dbghOrder.getDid()))
                .map(Department::getTitle)
                .ifPresent(totalOrderVo::setDepartment);
            /*totalOrderVo.setHospital(hospitalMapper.selectById(dbghOrder.getHid()).getName());
            totalOrderVo.setDepartment(departmentMapper.selectById(dbghOrder.getDid()).getTitle());
            totalOrderVo.setVisitor(userVsitorMapper.selectById(dbghOrder.getVisitor()).getName());*/
            totalOrderVo.setVisitTime(dbghOrder.getVisitTime());
            totalOrderVo.setOverTime(dbghOrder.getOverTime());
            totalOrderVo.setVoucher(dbghOrder.getVoucher());
            totalOrderVo.setPzRemark(dbghOrder.getRemark());

        } else if (totalOrderVo.getBusinessId() == 3) {// 代办问诊

            DbwzOrder dbwzOrder = dbwzOrderMapper.selectOne(new LambdaQueryWrapper<DbwzOrder>().eq(DbwzOrder::getOrderId, totalOrderVo.getId()));
            totalOrderVo.setServiceStatus(
                dbwzOrder.getStatus()
            );
            // totalOrderVo = BeanUtil.toBean(dbwzOrder, TotalOrderVo.class);
            // totalOrderVo = BeanUtil.toBean(dbwzOrder, TotalOrderVo.class);
            Optional.ofNullable(servicesMapper.selectById(totalOrderVo.getServiceId()))
                .map(Services::getName)
                .ifPresent(totalOrderVo::setProject);
            Optional.ofNullable(userVsitorMapper.selectById(dbwzOrder.getVisitor()))
                .map(UserVsitor::getName)
                .ifPresent(totalOrderVo::setVisitor);
            Optional.ofNullable(departmentMapper.selectById(dbwzOrder.getDid()))
                .map(Department::getTitle)
                .ifPresent(totalOrderVo::setDepartment);
           /* totalOrderVo.setProject(servicesMapper.selectVoById(totalOrderVo.getServiceId()).getName());
            totalOrderVo.setDepartment(departmentMapper.selectById(dbwzOrder.getDid()).getTitle());
            totalOrderVo.setVisitor(userVsitorMapper.selectById(dbwzOrder.getVisitor()).getName());*/
            totalOrderVo.setVisitTime(dbwzOrder.getVisitTime());
            totalOrderVo.setChiefComplaint(dbwzOrder.getChiefComplaint());
            totalOrderVo.setHistoryOfPresentIllness(dbwzOrder.getHistoryOfPresentIllness());
            totalOrderVo.setPastHistory(dbwzOrder.getPastHistory());
            totalOrderVo.setLastMedicalTreatmentSituation(dbwzOrder.getLastMedicalTreatmentSituation());
            totalOrderVo.setPostTreatmentCondition(dbwzOrder.getPostTreatmentCondition());
            totalOrderVo.setRelatedReports(dbwzOrder.getRelatedReports());
            totalOrderVo.setServiceRequirements(dbwzOrder.getServiceRequirements());
            totalOrderVo.setOverTime(dbwzOrder.getOverTime());
            totalOrderVo.setVoucher(dbwzOrder.getVoucher());
            totalOrderVo.setPzRemark(dbwzOrder.getRemark());
            totalOrderVo.setIndications(dbwzOrder.getIndications());

        } else if (totalOrderVo.getBusinessId() == 4) {// 住院陪护

            ZyphOrder zyphOrder = zyphOrderMapper.selectOne(new LambdaQueryWrapper<ZyphOrder>().eq(ZyphOrder::getOrderId, totalOrderVo.getId()));
            totalOrderVo.setServiceStatus(
                zyphOrder.getStatus()
            );
            // totalOrderVo = BeanUtil.toBean(zyphOrder, TotalOrderVo.class);
            Optional.ofNullable(hospitalMapper.selectById(zyphOrder.getHid()))
                .map(Hospital::getName)
                .ifPresent(totalOrderVo::setHospital);
            Optional.ofNullable(userVsitorMapper.selectById(zyphOrder.getVisitor()))
                .map(UserVsitor::getName)
                .ifPresent(totalOrderVo::setVisitor);
            Optional.ofNullable(departmentMapper.selectById(zyphOrder.getDid()))
                .map(Department::getTitle)
                .ifPresent(totalOrderVo::setDepartment);
            /*totalOrderVo.setHospital(hospitalMapper.selectById(zyphOrder.getHid()).getName());
            totalOrderVo.setVisitor(userVsitorMapper.selectById(zyphOrder.getVisitor()).getName());
            totalOrderVo.setDepartment(departmentMapper.selectById(zyphOrder.getDid()).getTitle());*/
            totalOrderVo.setPhrq(zyphOrder.getStartDay() + "-" + zyphOrder.getEndDay());
            totalOrderVo.setPhsj(zyphOrder.getStartTime() + "-" + zyphOrder.getEndTime());
            totalOrderVo.setOverTime(zyphOrder.getOverTime());
            totalOrderVo.setVoucher(zyphOrder.getVoucher());
            totalOrderVo.setPzRemark(zyphOrder.getRemark());


        } else if (totalOrderVo.getBusinessId() == 5) {// 代办买药

            DbmyOrder dbmyOrder = dbmyOrderMapper.selectOne(new LambdaQueryWrapper<DbmyOrder>().eq(DbmyOrder::getOrderId, totalOrderVo.getId()));
            totalOrderVo.setServiceStatus(
                dbmyOrder.getStatus()
            );
            totalOrderVo.setYpName(dbmyOrder.getYpName());
            totalOrderVo.setYdAddress(dbmyOrder.getYdAddress());
            totalOrderVo.setIsCf(dbmyOrder.getIsCf());
            totalOrderVo.setPrescriptionAttachment(dbmyOrder.getPrescriptionAttachment());
            totalOrderVo.setWay(dbmyOrder.getWay());
            totalOrderVo.setRecipient(dbmyOrder.getRecipient());
            totalOrderVo.setAddress(dbmyOrder.getAddress());
            totalOrderVo.setAddressInfo(dbmyOrder.getAddressInfo());
            totalOrderVo.setPhone(dbmyOrder.getPhone());
            totalOrderVo.setIsRefrigerate(dbmyOrder.getIsRefrigerate());
            totalOrderVo.setOverTime(dbmyOrder.getOverTime());
            totalOrderVo.setVoucher(dbmyOrder.getVoucher());
            totalOrderVo.setPzRemark(dbmyOrder.getRemark());

        } else if (totalOrderVo.getBusinessId() == 6) {// 诊前挂号

            ZqghOrder zqghOrder = zqghOrderMapper.selectOne(new LambdaQueryWrapper<ZqghOrder>().eq(ZqghOrder::getOrderId, totalOrderVo.getId()));
            totalOrderVo.setServiceStatus(
                zqghOrder.getStatus()
            );
            Optional.ofNullable(hospitalMapper.selectById(zqghOrder.getHid()))
                .map(Hospital::getName)
                .ifPresent(totalOrderVo::setHospital);
            /*Optional.ofNullable(userVsitorMapper.selectById(zqghOrder.getVisitor()))
                .map(UserVsitor::getName)
                .ifPresent(totalOrderVo::setVisitor);*/
            Optional.ofNullable(departmentMapper.selectById(zqghOrder.getDid()))
                .map(Department::getTitle)
                .ifPresent(totalOrderVo::setDepartment);
            Optional.ofNullable(doctorMapper.selectById(zqghOrder.getDoctorId()))
                .map(Doctor::getName)
                .ifPresent(totalOrderVo::setDoctor);
            /*totalOrderVo.setHospital(hospitalMapper.selectById(zqghOrder.getHid()).getName());
            totalOrderVo.setDepartment(departmentMapper.selectById(zqghOrder.getDid()).getTitle());
            totalOrderVo.setHospital(hospitalMapper.selectById(zqghOrder.getHid()).getName());
            totalOrderVo.setDoctor(doctorMapper.selectById(zqghOrder.getDoctorId()).getName());*/
            totalOrderVo.setTimeOfAppointment(zqghOrder.getTimeOfAppointment());
            totalOrderVo.setOverTime(zqghOrder.getOverTime());
            totalOrderVo.setVoucher(zqghOrder.getVoucher());
            totalOrderVo.setPzRemark(zqghOrder.getRemark());

        } else if (totalOrderVo.getBusinessId() == 0) {// 商城订单

            StoreOrder storeOrder = storeOrderMapper.selectOne(new LambdaQueryWrapper<StoreOrder>().eq(StoreOrder::getOrderId, totalOrderVo.getId()));
            totalOrderVo.setServiceStatus(
                storeOrder.getStatus()
            );

            StoreGoodsVo storeGoods = storeGoodsMapper.selectVoById(storeOrder.getGoodsId());
            if(null != storeGoods){
                List<Integer> ids = JsonUtils.parseArray(storeGoods.getTags(), Integer.class);
                List<StoreGoodsTag> storeGoodsTags = storeGoodsTagMapper.selectList(new LambdaQueryWrapper<StoreGoodsTag>().in(StoreGoodsTag::getId, ids).select(StoreGoodsTag::getTitle));
                totalOrderVo.setTags(storeGoodsTags);
                totalOrderVo.setStoreGoodsVo(storeGoods);
                totalOrderVo.setName(storeGoods.getTitle());
                totalOrderVo.setSmallCover(storeGoods.getSmallCover());
                totalOrderVo.setPrice(storeGoods.getSalePrice());
                totalOrderVo.setIntro(storeGoods.getIntro());
                totalOrderVo.setGoodsId(storeGoods.getId());
            }
            UserAddressVo userAddressVo = userAddressMapper.selectVoById(storeOrder.getAddressId());
            if(null != userAddressVo){
                totalOrderVo.setUserAddressVo(userAddressVo);
            }
            if (StringUtils.isNotEmpty(storeOrder.getLogisticsCode())) {
                TotalOrderBo totalOrderBo = new TotalOrderBo();
                if(null != userAddressVo){
                    totalOrderBo.setPhone(userAddressVo.getPhone());
                }

                totalOrderBo.setId(totalOrderVo.getId());
                totalOrderBo.setLogisticsCode(storeOrder.getLogisticsCode());
                totalOrderVo.setObject(selectLogisticsStatus(totalOrderBo));
            }
            totalOrderVo.setNum(storeOrder.getNum());
        }
        return totalOrderVo;
    }

    /**
     * 查询总订单列表
     */
    @Override
    public TableDataInfo<TotalOrderVo> queryPageList(TotalOrderBo bo, PageQuery pageQuery) {
        // TODO 待优化
        LambdaQueryWrapper<TotalOrder> lqw = buildQueryWrapper(bo);
        IPage<TotalOrderVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        Optional.ofNullable(result.getRecords()).ifPresent(totalOrderVos -> {
            totalOrderVos.forEach(totalOrderVo -> {
                // 陪诊人员
                if (totalOrderVo.getEmId() != 0) {
                    Optional.ofNullable(employeesMapper.selectVoById(totalOrderVo.getEmId()).getName())
                        .ifPresent(totalOrderVo::setEmName);
                }

                // 业务
                Business business = businessMapper.selectById(totalOrderVo.getBusinessId());
                if (null != business) {
                    totalOrderVo.setName(business.getName());
                }

                // 服务封面
                Services services = servicesMapper.selectById(totalOrderVo.getServiceId());
                if (null != services) {
                    totalOrderVo.setCover(services.getCover());
                }

                if (totalOrderVo.getBusinessId() == 1) {// 预约陪诊

                    totalOrderVo.setServiceStatus(
                        yypzOrderMapper.selectOne(new LambdaQueryWrapper<YypzOrder>().eq(YypzOrder::getOrderId, totalOrderVo.getId())).getStatus()
                    );


                } else if (totalOrderVo.getBusinessId() == 2) {// 代办挂号

                    totalOrderVo.setServiceStatus(
                        dbghOrderMapper.selectOne(new LambdaQueryWrapper<DbghOrder>().eq(DbghOrder::getOrderId, totalOrderVo.getId())).getStatus()
                    );


                } else if (totalOrderVo.getBusinessId() == 3) {// 代办问诊

                    totalOrderVo.setServiceStatus(
                        dbwzOrderMapper.selectOne(new LambdaQueryWrapper<DbwzOrder>().eq(DbwzOrder::getOrderId, totalOrderVo.getId())).getStatus()
                    );

                } else if (totalOrderVo.getBusinessId() == 4) {// 住院陪护

                    totalOrderVo.setServiceStatus(
                        zyphOrderMapper.selectOne(new LambdaQueryWrapper<ZyphOrder>().eq(ZyphOrder::getOrderId, totalOrderVo.getId())).getStatus()
                    );

                } else if (totalOrderVo.getBusinessId() == 5) {// 代办买药

                    totalOrderVo.setServiceStatus(
                        dbmyOrderMapper.selectOne(new LambdaQueryWrapper<DbmyOrder>().eq(DbmyOrder::getOrderId, totalOrderVo.getId())).getStatus()
                    );

                } else if (totalOrderVo.getBusinessId() == 6) {// 诊前挂号

                    totalOrderVo.setServiceStatus(
                        zqghOrderMapper.selectOne(new LambdaQueryWrapper<ZqghOrder>().eq(ZqghOrder::getOrderId, totalOrderVo.getId())).getStatus()
                    );


                } else if (totalOrderVo.getBusinessId() == 0) {// 商城订单

                    StoreOrder storeOrder = storeOrderMapper.selectOne(new LambdaQueryWrapper<StoreOrder>().eq(StoreOrder::getOrderId, totalOrderVo.getId()));
                    totalOrderVo.setServiceStatus(
                        storeOrder.getStatus()
                    );

                    StoreGoods storeGoods = storeGoodsMapper.selectById(storeOrder.getGoodsId());
                    if(StringUtils.isNotEmpty(storeGoods.getTags())){
                        List<Integer> ids = JsonUtils.parseArray(storeGoods.getTags(), Integer.class);
                        List<StoreGoodsTag> storeGoodsTags = storeGoodsTagMapper.selectList(new LambdaQueryWrapper<StoreGoodsTag>().in(StoreGoodsTag::getId, ids).select(StoreGoodsTag::getTitle));
                        totalOrderVo.setTags(storeGoodsTags);
                    }
                    totalOrderVo.setPrice(storeGoods.getPrice());
                    totalOrderVo.setCover(storeGoods.getSmallCover());
                    totalOrderVo.setName(storeGoods.getTitle());
                }
            });

        });
        return TableDataInfo.build(result);
    }

    /**
     * 查询总订单列表
     */
    @Override
    public List<TotalOrderVo> queryList(TotalOrderBo bo) {
        LambdaQueryWrapper<TotalOrder> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<TotalOrder> buildQueryWrapper(TotalOrderBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<TotalOrder> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getOrderSn()), TotalOrder::getOrderSn, bo.getOrderSn());
        lqw.eq(bo.getUid() != null, TotalOrder::getUid, bo.getUid());
        lqw.eq(bo.getEmId() != null, TotalOrder::getEmId, bo.getEmId());
        lqw.eq(bo.getCityId() != null, TotalOrder::getCityId, bo.getCityId());
        lqw.eq(bo.getBusinessId() != null, TotalOrder::getBusinessId, bo.getBusinessId());
        lqw.eq(bo.getServiceId() != null, TotalOrder::getServiceId, bo.getServiceId());
        lqw.eq(StringUtils.isNotBlank(bo.getPayMoney()), TotalOrder::getPayMoney, bo.getPayMoney());
        lqw.eq(bo.getStatus() != null, TotalOrder::getStatus, bo.getStatus());
        lqw.eq(bo.getIsSatisfaction() != null, TotalOrder::getIsSatisfaction, bo.getIsSatisfaction());
        lqw.eq(StringUtils.isNotBlank(bo.getEvaluationContent()), TotalOrder::getEvaluationContent, bo.getEvaluationContent());
        lqw.eq(StringUtils.isNotBlank(bo.getRefundReason()), TotalOrder::getRefundReason, bo.getRefundReason());
        lqw.eq(StringUtils.isNotBlank(bo.getRefundAmount()), TotalOrder::getRefundAmount, bo.getRefundAmount());
        lqw.orderByDesc(TotalOrder::getId);
        return lqw;
    }

    /**
     * 新增总订单
     */
    @Override
    public Boolean insertByBo(TotalOrderBo bo) {
        TotalOrder add = BeanUtil.toBean(bo, TotalOrder.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public TotalOrderVo createOrder(CreateOrderBo bo) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        TotalOrderVo totalOrderVo = new TotalOrderVo();

        String orderSn = getOrderSn();
        bo.setStatus(0);
        // 组装总订单数据新增
        TotalOrder totalOrder = BeanUtil.toBean(bo, TotalOrder.class);
        totalOrder.setOrderSn(orderSn);
        totalOrder.setUid(loginUser.getUserId().intValue());

        baseMapper.insert(totalOrder);
        bo.setOrderId(totalOrder.getId().intValue());

        totalOrderVo.setOrderSn(totalOrder.getId() + "");
        totalOrderVo.setPayMoney(bo.getPayMoney());

        // 计算订单过期时间(当前时间加上30分钟)
        long expirationTime = System.currentTimeMillis() + TimeUnit.MINUTES.toMillis(30);
        // 未付款的订单延迟24小时自动取消
        TotalOrderDelayOperator totalOrderDelayOperator = new TotalOrderDelayOperator(totalOrder.getId(), expirationTime, id -> {
            TotalOrder order = baseMapper.selectById(id);

            order.setStatus(TotalOrderStatus.CANCEL.getCode());
            baseMapper.updateById(totalOrder);

        });
        delayQueue.addOrder(totalOrderDelayOperator);

        if (bo.getBusinessId() == 1) {// 预约陪诊


            YypzOrder yypzOrder = BeanUtil.toBean(bo, YypzOrder.class);
            yypzOrder.setHid(bo.getHospitalId());
            yypzOrder.setDid(bo.getDepartmentId());
            yypzOrder.setVisitor(bo.getVisitorId());
            yypzOrder.setRemark("");
            yypzOrderMapper.insert(yypzOrder);

        } else if (bo.getBusinessId() == 2) {// 代办挂号


            DbghOrder dbghOrder = BeanUtil.toBean(bo, DbghOrder.class);
            dbghOrder.setHid(bo.getHospitalId());
            dbghOrder.setDid(bo.getDepartmentId());
            dbghOrder.setVisitor(bo.getVisitorId());
            dbghOrder.setRemark("");
            dbghOrderMapper.insert(dbghOrder);

        } else if (bo.getBusinessId() == 3) {// 代办问诊

            DbwzOrder dbwzOrder = BeanUtil.toBean(bo, DbwzOrder.class);
            dbwzOrder.setDid(bo.getDepartmentId());
            dbwzOrder.setVisitor(bo.getVisitorId());
            dbwzOrderMapper.insert(dbwzOrder);
            dbwzOrder.setRemark("");
        } else if (bo.getBusinessId() == 4) {// 住院陪护

            ZyphOrder zyphOrder = BeanUtil.toBean(bo, ZyphOrder.class);
            zyphOrder.setDid(bo.getDepartmentId());
            zyphOrder.setHid(bo.getHospitalId());
            zyphOrder.setVisitor(bo.getVisitorId());
            zyphOrderMapper.insert(zyphOrder);
            zyphOrder.setRemark("");
        } else if (bo.getBusinessId() == 5) {// 代办买药

            DbmyOrder dbmyOrder = BeanUtil.toBean(bo, DbmyOrder.class);
            dbmyOrder.setRemark("");
            dbmyOrderMapper.insert(dbmyOrder);

        } else if (bo.getBusinessId() == 6) {// 诊前挂号

            ZqghOrder zqghOrder = BeanUtil.toBean(bo, ZqghOrder.class);
            zqghOrder.setHid(bo.getHospitalId());
            zqghOrder.setDid(bo.getDepartmentId());
            zqghOrder.setDoctorId(bo.getDoctorId());
            zqghOrder.setRemark("");
            zqghOrderMapper.insert(zqghOrder);

        } else if (bo.getBusinessId() == 0) {// 商城订单

            StoreOrder storeOrder = BeanUtil.toBean(bo, StoreOrder.class);
            StoreGoods storeGoods1 = storeGoodsMapper.selectById(storeOrder.getGoodsId());
            if (storeGoods1.getInventory() == 0) {
                throw new ServiceException("商品库存不足!");
            }

            storeOrder.setStoreId(storeGoods1.getStoreId());
            // 扣除库存
            storeGoods1.setId(storeOrder.getGoodsId());
            storeGoods1.setInventory(storeGoods1.getInventory() - storeOrder.getNum());
            storeGoods1.setSaleNum(storeGoods1.getSaleNum() + 1);
            storeGoodsMapper.updateById(storeGoods1);

            storeOrderMapper.insert(storeOrder);

        }
        return totalOrderVo;
    }

    /**
     * 修改总订单
     */
    @Override
    public Boolean updateByBo(TotalOrderBo bo) {
        TotalOrder update = BeanUtil.toBean(bo, TotalOrder.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    @Override
    public Boolean cancelOrder(TotalOrderBo bo) {
        TotalOrder totalOrder = baseMapper.selectById(bo.getId());

        ISonOrderService orderService = serviceBuilder.getSonOrderService(totalOrder.getBusinessId());
        Objects.requireNonNull(orderService, "订单业务属性出错");

        SonOrderVo sonOrderSimpleDataByTotalId = orderService.getSonOrderSimpleDataByTotalId(totalOrder.getId().intValue());
        // 待办问诊 已接单下取消订单调用退款接口
        // 已接单、待服务状态下等待陪诊员开始服务或取消订单
        TotalOrderBo totalOrderBo = new TotalOrderBo();
        totalOrderBo.setId(totalOrder.getId());
        if (totalOrder.getBusinessId() == 3 && totalOrder.getStatus() == 1 && sonOrderSimpleDataByTotalId.getOrderStatus() == 1) {
            totalOrderBo.setIsRefund(0);
            return this.refundOrder(totalOrderBo);

        }
        // 进行中、待完成状态下等待陪诊员完成服务
        if (totalOrder.getBusinessId() == 3 && totalOrder.getStatus() == 6) {
            totalOrderBo.setIsRefund(1);
            return this.refundOrder(totalOrderBo);
        }

        // 待办买药已接单 代发货下取消订单调用退款接口
        if (totalOrder.getBusinessId() == 5
            && totalOrder.getStatus() == 1
            && sonOrderSimpleDataByTotalId.getOrderStatus() == 1
        ) {
            totalOrderBo.setIsRefund(0);
            return this.refundOrder(totalOrderBo);
        }

        // 已接单、待收货状态下等待药品到达后确认
        if (totalOrder.getBusinessId() == 5
            && totalOrder.getStatus() == 2
            && sonOrderSimpleDataByTotalId.getOrderStatus() == 2
            && totalOrder.getRefundAmount() == 0) {
            totalOrderBo.setIsRefund(1);
            return this.refundOrder(totalOrderBo);
        }

        // 已付款 未结单直接退款
        if (sonOrderSimpleDataByTotalId.getOrderStatus() == 0 && totalOrder.getStatus() == 1) {
            totalOrderBo.setIsRefund(0);
            return this.refundOrder(totalOrderBo);
        }

        // 商城订单已支付未结单取消退款
        if (totalOrder.getBusinessId() == 0 && totalOrder.getStatus() == 1 && sonOrderSimpleDataByTotalId.getOrderStatus() == 0) {
            totalOrderBo.setIsRefund(0);
            return this.refundOrder(totalOrderBo);
        }

        // 用户未付款 陪诊员为接单 和 用户未付款陪诊员已接单直接取消
        if ((sonOrderSimpleDataByTotalId.getOrderStatus() == 0 && totalOrder.getStatus() == 0) || (sonOrderSimpleDataByTotalId.getOrderStatus() == 1 && totalOrder.getStatus() == 0)) {
            // yypzOrderMapper.selectOne(new LambdaQueryWrapper<YypzOrder>().eq(YypzOrder::getOrderId,totalOrder));
            totalOrder.setStatus(TotalOrderStatus.CANCEL.getCode());
            if (totalOrder.getBusinessId() == 0) {
                StoreOrder storeOrder = storeOrderMapper.selectById(sonOrderSimpleDataByTotalId.getSonOrderId());
                StoreGoods storeGoods = storeGoodsMapper.selectById(storeOrder.getGoodsId());
                storeGoods.setSaleNum(storeGoods.getSaleNum() - 1);
                storeGoods.setInventory(storeGoods.getInventory() + 1);

                storeGoodsMapper.updateById(storeGoods);
            }
            return baseMapper.updateById(totalOrder) > 0;
        } else {
            throw new ServiceException("该订单已分配给陪诊员,不允许取消订单!");
        }
    }

    @Override
    public Boolean finishOrder(TotalOrderBo bo) {

        TotalOrder totalOrder = BeanUtil.toBean(bo, TotalOrder.class);
        totalOrder.setStatus(TotalOrderStatus.DONE.getCode());

        TotalOrder totalOrder1 = baseMapper.selectById(totalOrder.getId());

        // 除了商城订单和诊前挂号不需要给陪诊员和商户分成
        if (totalOrder1.getBusinessId() != 0 && totalOrder1.getBusinessId() != 6) {
            Services services = servicesMapper.selectById(totalOrder1.getServiceId());
            // 添加订单分成记录
            EmployeesDivide employeesDivide = new EmployeesDivide();
            employeesDivide.setOrderId(totalOrder1.getId().intValue());
            employeesDivide.setOrderPrice(totalOrder1.getPayMoney() + "");

            double money = 0;

            if(services.getFenmo() == 0){
                money = totalOrder1.getPayMoney();
            }else if(services.getFenmo() != 0){
                double fenmo = (double) services.getFenmo() / 100;

                double v = totalOrder1.getPayMoney() * fenmo;

                money = totalOrder1.getPayMoney() - v;;
            }

                Employees employees = employeesMapper.selectById(totalOrder1.getEmId());
                /**
                 * 1. 如果该陪诊员不属于任何商户,则陪诊员每完成一个订单,收益都会相应增加
                 * 2. 如果该陪诊员属于某个商户,则该陪诊员每完成一个订单,收益不会增加(因为陪诊员完成订单后,收益暂归商户所有)
                 */

                employeesDivide.setProportion(services.getFenmo());
                employeesDivide.setEmId(employees.getId());

                if (employees.getCompanyId() != 0) {

                    Company company = companyMapper.selectById(employees.getCompanyId());
                    company.setTotalRevenue((Double.parseDouble(company.getTotalRevenue()) + money) + "");
                    company.setBalance((Double.parseDouble(company.getBalance()) + money) + "");
                    employeesDivide.setCompanyId(employees.getCompanyId());

                    companyMapper.updateById(company);
                    employeesDivide.setDividePrice(money + "");
                } else {

                    employees.setTotalRevenue((Double.parseDouble(employees.getTotalRevenue()) + money) + "");
                    employees.setBalance((Double.parseDouble(employees.getBalance()) + money) + "");

                    employeesMapper.updateById(employees);
                    employeesDivide.setDividePrice(money + "");

                }

                employeesDivideMapper.insert(employeesDivide);


        }
        if(totalOrder1.getBusinessId() == 0 && totalOrder1.getStatus() == 1){
            ISonOrderService orderService = serviceBuilder.getSonOrderService(totalOrder1.getBusinessId());

            // 修改子订单状态
            orderService.switchSonOrderStatus(totalOrder1.getId(), CommonOrderStatus.DONE.getCode());

        }
        return baseMapper.updateById(totalOrder) > 0;
    }

    @Override
    public Object payOrder(TotalOrderBo bo) {
        LoginUser loginUser = LoginHelper.getLoginUser();
        TotalOrder totalOrder = baseMapper.selectById(Integer.parseInt(bo.getOrderSn()));
        Object payment = null;
        int money = (int) (totalOrder.getPayMoney() * 100);
        try {
            String openId = sysUserMapper.selectById(loginUser.getUserId()).getOpenId();
            WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
            orderRequest.setBody(bo.getOrderTitle());
            orderRequest.setOutTradeNo(totalOrder.getOrderSn());
            orderRequest.setTotalFee(money);// 元转成分
            if(null != bo.getPaymentType()){
                if(bo.getPaymentType() == 0){
                    orderRequest.setOpenid(openId);
                    orderRequest.setTradeType("JSAPI");
                }else if(bo.getPaymentType() == 1){
                    orderRequest.setTradeType("APP");
                    TotalOrder totalOrder1 = baseMapper.selectOne(new LambdaQueryWrapper<TotalOrder>().eq(TotalOrder::getOrderSn, totalOrder.getOrderSn()));
                    if (totalOrder1.getStatus() == 0) {
                        // 修改订单状态为已支付
                        totalOrder1.setStatus(1);
                        baseMapper.updateById(totalOrder1);
                        // 添加支付记录
                        PaymentRecord paymentRecord = new PaymentRecord();
                        paymentRecord.setPayType(0);
                        paymentRecord.setOrderId(totalOrder1.getId().intValue());
                        paymentRecord.setMoney(totalOrder1.getPayMoney());
                        paymentRecord.setUid(totalOrder1.getUid());
                        paymentRecordMapper.insert(paymentRecord);

                        return true;
                    }
                }
            }else {
                orderRequest.setOpenid(openId);
                orderRequest.setTradeType("JSAPI");
            }
            orderRequest.setSpbillCreateIp("127.0.0.1");
            orderRequest.setNotifyUrl("https://peizheng.shanpeikj.com/api/applet/totalOrder/orderPayCallBack");


            payment = iPayService.createOrder(orderRequest);
        } catch (Exception e) {

            throw new ServiceException("微信支付失败!");
        }

        return payment;
    }

    @Override
    public boolean orderPayCallBack(WxPayOrderNotifyResult result) {
        String orderNum = result.getOutTradeNo();
        TotalOrder totalOrder = baseMapper.selectOne(new LambdaQueryWrapper<TotalOrder>().eq(TotalOrder::getOrderSn, orderNum));
        if (totalOrder.getStatus() == 0) {
            // 修改订单状态为已支付
            totalOrder.setStatus(1);
            baseMapper.updateById(totalOrder);
            // 添加支付记录
            PaymentRecord paymentRecord = new PaymentRecord();
            paymentRecord.setPayType(0);
            paymentRecord.setOrderId(totalOrder.getId().intValue());
            paymentRecord.setMoney(totalOrder.getPayMoney());
            paymentRecord.setUid(totalOrder.getUid());
            paymentRecordMapper.insert(paymentRecord);
            return true;
        }
        return false;
    }

    @Override
    public boolean orderRefundCallBack(WxPayRefundNotifyResult wxPayRefundNotifyResult) {
        WxPayRefundNotifyResult.ReqInfo reqInfo = wxPayRefundNotifyResult.getReqInfo();
        // 订单号
        String outTradeNo = reqInfo.getOutTradeNo();
        TotalOrder totalOrder = baseMapper.selectOne(new LambdaQueryWrapper<TotalOrder>().eq(TotalOrder::getOrderSn, outTradeNo));
        totalOrder.setStatus(TotalOrderStatus.REFUND.getCode());

        ISonOrderService orderService = serviceBuilder.getSonOrderService(totalOrder.getBusinessId());
        Objects.requireNonNull(orderService, "订单业务属性出错");

        SonOrderVo sonOrderSimpleDataByTotalId = orderService.getSonOrderSimpleDataByTotalId(totalOrder.getId().intValue());

        // 已付款 未结单直接退款
        if (sonOrderSimpleDataByTotalId.getOrderStatus() == 0 && totalOrder.getStatus() == 1) {
            totalOrder.setStatus(TotalOrderStatus.CANCEL.getCode());
        }

        // 修改子订单状态
        boolean sonOrderFlag = orderService.switchSonOrderStatus(totalOrder.getId(), CommonOrderStatus.REFUND.getCode());

        UserRefund userRefund = userRefundMapper.selectOne(new LambdaQueryWrapper<UserRefund>().eq(UserRefund::getOrderId, totalOrder.getId()));

        // 除了商城订单和诊前挂号不需要给陪诊员和商户分成
        if (totalOrder.getBusinessId() != 0 && totalOrder.getBusinessId() != 6 && null != userRefund && sonOrderSimpleDataByTotalId.getOrderStatus() == 3) {
            Services services = servicesMapper.selectById(totalOrder.getServiceId());
            double money = 0;
            if (services.getFenmo() == 0) {
                money = totalOrder.getPayMoney();
            }else if(services.getFenmo() != 0){
                double fenmo = (double) services.getFenmo() / 100;

                double v = totalOrder.getPayMoney() * fenmo;

                money = totalOrder.getPayMoney() - v;
            }

                Employees employees = employeesMapper.selectById(totalOrder.getEmId());
                /**
                 * 1. 如果该陪诊员不属于任何商户,则陪诊员每完成一个订单,收益都会相应增加
                 * 2. 如果该陪诊员属于某个商户,则该陪诊员每完成一个订单,收益不会增加(因为陪诊员完成订单后,收益暂归商户所有)
                 */

                if (employees.getCompanyId() != 0) {

                    Company company = companyMapper.selectById(employees.getCompanyId());
                    company.setTotalRevenue((Double.parseDouble(company.getTotalRevenue()) - money) + "");
                    company.setBalance((Double.parseDouble(company.getBalance()) - money) + "");

                    companyMapper.updateById(company);

                } else {

                    employees.setTotalRevenue(employees.getTotalRevenue());
                    employees.setTotalRevenue((Double.parseDouble(employees.getTotalRevenue()) - money) + "");
                    employees.setBalance((Double.parseDouble(employees.getBalance()) - money) + "");
                    employeesMapper.updateById(employees);

                }
        }

        if (!sonOrderFlag) {
            throw new ServiceException("子订单状态修改出错,接单失败");
        }
        totalOrder.setSuborderStatus(CommonOrderStatus.REFUND.getCode());
        if (baseMapper.updateById(totalOrder) > 0) {
            // 添加退款记录
            PaymentRecord paymentRecord = new PaymentRecord();
            paymentRecord.setPayType(1);
            paymentRecord.setOrderId(totalOrder.getId().intValue());
            paymentRecord.setMoney(totalOrder.getRefundAmount());
            paymentRecord.setUid(totalOrder.getUid());
            paymentRecordMapper.insert(paymentRecord);
            return true;
        }

        return false;
    }

    @Override
    public Boolean refundOrder(TotalOrderBo bo) {

        TotalOrder totalOrder = baseMapper.selectById(bo.getId());

        ISonOrderService orderService = serviceBuilder.getSonOrderService(totalOrder.getBusinessId());
        Objects.requireNonNull(orderService, "订单业务属性出错");

        SonOrderVo sonOrderSimpleDataByTotalId = orderService.getSonOrderSimpleDataByTotalId(totalOrder.getId().intValue());
        if (null == sonOrderSimpleDataByTotalId) {
            throw new ServiceException("子订单状态出错!");
        }
        int IsRefund = getIsRefund(totalOrder.getBusinessId(), totalOrder.getStatus(), sonOrderSimpleDataByTotalId.getOrderStatus());
        // 订单退款金额
        double money = 0;

        if (null != bo.getIsPcRefund() && bo.getIsPcRefund() == 1){
            money = totalOrder.getRefundAmount();
            //pc是否同意退款1-完成退款,2-取消退款
            if(bo.getIsPcRefundStatus() == 1 ){
                WxPayRefundRequest request = new WxPayRefundRequest();

                request.setOutTradeNo(totalOrder.getOrderSn());
                request.setOutRefundNo(UUID.randomUUID().toString());
                request.setTotalFee((int) (totalOrder.getPayMoney() * 100));
                request.setRefundFee((int) (money * 100));
                request.setNotifyUrl("https://peizheng.shanpeikj.com/api/applet/totalOrder/orderRefundCallBack");

                try {
                    iPayService.refund(request);
                    return true;
                } catch (WxPayException e) {
                    e.printStackTrace();
                    return false;
                }
            }else if(bo.getIsPcRefundStatus() == 2){

                //后台取消直接将订单完成
                totalOrder.setStatus(TotalOrderStatus.DONE.getCode());

                baseMapper.updateById(totalOrder);
                return orderService.switchSonOrderStatus(totalOrder.getId(), CommonOrderStatus.DONE.getCode());

            }
        }

        if (IsRefund == 0) {// 陪诊员订单未完成用户主动退款直接退到账户
            // 主订单必须为付款并且子订单为已接单
            if (totalOrder.getStatus() != 1 && sonOrderSimpleDataByTotalId.getOrderStatus() != 1) {
                throw new ServiceException("退款出错!");
            }
            /**
             *责任归属:用户下单,陪诊人员接单后,客户单方面取消,客户为本次订单负责:
             *
             * (1)订单开始前12小时取消--无责退款
             *
             * (2)订单开始前6小时取消--需承担服务项目金额的30%
             *
             * (3)订单开始前3小时取消--需承担服务项目金额的50%
             */

            // 待办问诊和待办买药走取消订单退款
            /*if(totalOrder.getBusinessId() == 3 || totalOrder.getBusinessId() == 5){
                throw new ServiceException("待办问诊和待办买药退款失败!");
            }*/

            /**
             * 待办买药
             */
            if (totalOrder.getBusinessId() == 5) {
                money = totalOrder.getPayMoney();
            } else if (totalOrder.getBusinessId() == 0) {// 商城订单
                money = totalOrder.getPayMoney();
            } else {
                // 一般陪诊订单
                // 一般订单开始服务时间
                String serveTime = orderService.getFinishTime(totalOrder.getId().intValue());
                if (StringUtils.isNotEmpty(serveTime)) {
                    try {
                        money = getMoney(serveTime, totalOrder.getPayMoney());// 计算退款金额
                    } catch (Exception e) {
                        money = totalOrder.getPayMoney();
                        e.printStackTrace();
                    }
                } else {
                    money = totalOrder.getPayMoney();
                }
            }

            WxPayRefundRequest request = new WxPayRefundRequest();

            request.setOutTradeNo(totalOrder.getOrderSn());
            request.setOutRefundNo(UUID.randomUUID().toString());
            request.setTotalFee((int) (totalOrder.getPayMoney() * 100));
            request.setRefundFee((int) (money * 100));
            request.setNotifyUrl("https://peizheng.shanpeikj.com/api/applet/totalOrder/orderRefundCallBack");

            try {
                iPayService.refund(request);
            } catch (WxPayException e) {
                e.printStackTrace();
            }

            totalOrder.setRefundAmount(money);
        } else if (IsRefund == 1) {// 陪诊员订单完成走审批流程
            if (sonOrderSimpleDataByTotalId.getOrderStatus() != 2) {
                throw new ServiceException("订单状态错误");
            }
            // 修改主订单退款理由
            totalOrder.setRefundAmount(totalOrder.getPayMoney());
            totalOrder.setRefundReason(bo.getRefundReason());
            // 添加退款审核记录
            UserRefund userRefund = new UserRefund();
            userRefund.setRefundNo(getOrderSn());
            userRefund.setOrderId(totalOrder.getId().intValue());
            userRefund.setBusinessId(totalOrder.getBusinessId());
            userRefund.setSonOrderId(sonOrderSimpleDataByTotalId.getSonOrderId());
            userRefund.setPhone(bo.getPhone());
            userRefund.setStatus(0);
            userRefundMapper.insert(userRefund);
        }


        // 修改子订单状态
        boolean sonOrderFlag = orderService.switchSonOrderStatus(totalOrder.getId(), CommonOrderStatus.BEING_REFUND.getCode());

        if (!sonOrderFlag) {
            throw new ServiceException("子订单状态修改出错");
        }
        /*if (totalOrder.getBusinessId() == 0) {// 商城订单

            storeOrderMapper.update(null, new LambdaUpdateWrapper<StoreOrder>()
                .eq(StoreOrder::getOrderId, totalOrder.getId())
                .set(StoreOrder::getStatus, ShopOrderStatus.BEING_REFUND.getCode()));

        }*/
        totalOrder.setSuborderStatus(CommonOrderStatus.BEING_REFUND.getCode());
        baseMapper.updateById(totalOrder);
        return true;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(TotalOrder entity) {
        // TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除总订单
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            // TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 陪诊员端 需求广场
     *
     * @return 待分配陪诊员订单
     */
    @Override
    public TableDataInfo<AccompanyDemandVo> queryUndistributedOrder(Integer cityCode, PageQuery page) {
        QueryWrapper<TotalOrder> wrapper = Wrappers.query();
        // 筛选未分配订单
        wrapper.apply("total_order.em_id = 0")  // 未分配陪诊员订单
            .in("total_order.status", 0, 1) // 待支付、已支付
            .between("total_order.business_id", 1, 5)
            .eq(cityCode != null, "total_order.city_id", cityCode)  // 筛选城市
            .orderByDesc("total_order.id");
        IPage<AccompanyDemandVo> result = baseMapper.selectUndistributedTotalOrder(page.build(), wrapper);
        // 装载子订单信息
        result.getRecords().forEach(order -> {
            ISonOrderService orderService = serviceBuilder.getSonOrderService(order.getBusinessId());
            SonOrderVo sonOrder;
            if (orderService != null && (sonOrder = orderService.getSonOrderSimpleDataByTotalId(order.getOrderId())) != null) {
                order.setAvatar(sonOrder.getAvatar());
                order.setSonOrderStatus(sonOrder.getOrderStatus());
                order.setHospital(sonOrder.getHospital());
                order.setVisitTime(sonOrder.getVisitTime());
                order.setUserName(sonOrder.getUserName());
            }
        });
        return TableDataInfo.build(result);
    }

    /**
     * 陪诊员端 订单评价
     *
     * @return 待分配陪诊员订单
     */
    @Override
    public TableDataInfo<AccompanyDemandVo> queryOrderComment(Integer emId, PageQuery page) {
        QueryWrapper<TotalOrder> wrapper = Wrappers.query();
        // 筛选未分配订单
        wrapper.eq("total_order.em_id", emId)  // 未分配陪诊员订单
            .eq("total_order.status", 2) // 订单已完成
            .ne("total_order.is_satisfaction", 0)
            .between("total_order.business_id", 1, 5)
            .orderByDesc("total_order.id");
        IPage<AccompanyDemandVo> result = baseMapper.selectUndistributedTotalOrder(page.build(), wrapper);
        // 装载子订单信息
        result.getRecords().forEach(order -> {
            ISonOrderService orderService = serviceBuilder.getSonOrderService(order.getBusinessId());
            SonOrderVo sonOrder;
            if (orderService != null && (sonOrder = orderService.getSonOrderSimpleDataByTotalId(order.getOrderId())) != null) {
                order.setAvatar(sonOrder.getAvatar());
                order.setSonOrderStatus(sonOrder.getOrderStatus());
                order.setHospital(sonOrder.getHospital());
                order.setVisitTime(sonOrder.getVisitTime());
                order.setUserName(sonOrder.getUserName());
            }
        });
        return TableDataInfo.build(result);
    }

    /**
     * 陪诊员接单
     *
     * @param emId    陪诊员ID
     * @param orderId 主订单ID
     * @return 操作结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean orderReceiving(Integer emId, Integer orderId) {
        TotalOrder totalOrder = baseMapper.selectById(orderId);
        Objects.requireNonNull(totalOrder, "订单不存在");
        if (totalOrder.getEmId() != 0) {
            throw new ServiceException("该订单已分配给其他陪诊员,不允许重复分配");
        }
        ISonOrderService orderService = serviceBuilder.getSonOrderService(totalOrder.getBusinessId());
        Objects.requireNonNull(orderService, "订单业务属性出错");
        // 已接单状态
        int target = 1;
        // 代办挂号需额外处理(去除判断)
      /*   if (totalOrder.getBusinessId() == 2 && totalOrder.getStatus() == 1) {
            // 若接单(待办挂号)时,订单已支付,则子订单状态应该修改为6(进行中)
            target = 6;
        } */
        // 修改子订单状态
        boolean sonOrderFlag = orderService.switchSonOrderStatus(totalOrder.getId(), target);
        if (!sonOrderFlag) {
            throw new ServiceException("子订单状态修改出错,接单失败");
        }
        // 绑定主订单陪诊员
        totalOrder.setEmId(emId);
        // 设置主订单中子订单状态为已接单
        totalOrder.setSuborderStatus(target);
        boolean flag = baseMapper.updateById(totalOrder) > 0;
        if (!flag) {
            throw new ServiceException("接单失败");
        }
        return true;
    }


    /**
     * 查询订单信息
     *
     * @param id 订单ID
     * @return 订单信息
     */
    @Override
    public AccompanyDemandVo queryTotalOrderById(Long id) {
        AccompanyDemandVo order = baseMapper.selectTotalOrderById(id);
        Objects.requireNonNull(order, "未查询到订单信息");
        // 装载子订单数据
        ISonOrderService orderService = serviceBuilder.getSonOrderService(order.getBusinessId());
        SonOrderVo sonOrder;
        if (orderService != null && (sonOrder = orderService.getSonOrderSimpleDataByTotalId(order.getOrderId())) != null) {
            order.setSonOrderStatus(sonOrder.getOrderStatus());
            order.setAvatar(sonOrder.getAvatar());
            order.setHospital(sonOrder.getHospital());
            order.setVisitTime(sonOrder.getVisitTime());
            order.setUserName(sonOrder.getUserName());
        }
        return order;
    }

    @Override
    public Object selectLogisticsStatus(TotalOrderBo totalOrderBo) {
        String host = "http://kop.kuaidihelp.com";
        String path = "/api";
        String requestMethod = "POST";
        Map<String, String> headers = new HashMap<String, String>();
// 根据API的要求,定义相对应的Content-Type
        headers.put("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
        Map<String, String> querys = new HashMap<String, String>();
        Map<String, String> bodys = new HashMap<String, String>();

        String appId = kbProperties.getAppId();
        String method = "express.info.get";
// 当前时间戳
        String ts = new Date().getTime() + "";
        String appKey = kbProperties.getAppKey();

// 计算签名
        String signStr = appId + method + ts + appKey;
        String sign = getMD5(signStr, 32);

        bodys.put("app_id", appId);
        bodys.put("method", method);
        bodys.put("ts", ts);
        bodys.put("sign", sign);
        ObjectMapper objectMapper = new ObjectMapper();
        Map<String, String> data = new HashMap<String, String>();
        data.put("waybill_codes", totalOrderBo.getLogisticsCode());
        data.put("result_sort", "0");
        if (null != totalOrderBo.getPhone() && !totalOrderBo.getPhone().equals("")) {
            data.put("phone", "1");
        }
        String jsonStr = null;
        try {
            jsonStr = objectMapper.writeValueAsString(data);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
// data参数是个json格式的字符串  建议使用函数或方法去生成
        bodys.put("data", jsonStr);
        System.out.println(bodys);
        try {
            /**
             * 重要提示如下:
             * HttpUtils请从
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/src/main/java/com/aliyun/api/gateway/demo/util/HttpUtils.java
             * 下载
             *
             * 相应的依赖请参照
             * https://github.com/aliyun/api-gateway-demo-sign-java/blob/master/pom.xml
             */
            HttpResponse response = HttpUtils.doPost(host, path, requestMethod, headers, querys, bodys);
            System.out.println(response.toString());
            String responseBody = EntityUtils.toString(response.getEntity());
            // 将响应体数据转换为 JSON 对象
            JSONObject jsonResponse = new JSONObject(responseBody);
            return jsonResponse;

        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException();
        }

    }

    public String getOrderSn() {
        long timestamp = System.currentTimeMillis();
        String timestampStr = Long.toString(timestamp);
        Random random = new Random();
        int randomNum = random.nextInt(100000000);
        String randomStr = String.format("%08d", randomNum); // 将随机数转换为指定长度的字符串
        return timestampStr + randomStr;
    }

    public List<Integer> getTages(String tags) {
        // 去除空格和方括号
        String numbersString = tags.replaceAll("[\\[\\] ]", "");

        // 分割字符串
        String[] numberStrings = numbersString.split(",");

        // 转换为整数列表
        List<Integer> numberList = new ArrayList<>();
        for (String numberString : numberStrings) {
            int number = Integer.parseInt(numberString);
            numberList.add(number);
        }
        return numberList;
    }

    // 计算md5
    public static String getMD5(String plainText, int length) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");// 获取MD5实例
            md.update(plainText.getBytes());// 此处传入要加密的byte类型值
            byte[] digest = md.digest();// 此处得到的是md5加密后的byte类型值

            /*
               下边的运算就是自己添加的一些二次小加密,记住这个千万不能弄错乱,
                   否则在解密的时候,你会发现值不对的(举例:在注册的时候加密方式是一种,
                在我们登录的时候是不是还需要加密它的密码然后和数据库的进行比对,但是
            最后我们发现,明明密码对啊,就是打不到预期效果,这时候你就要想一下,你是否
             有改动前后的加密方式)
            */
            int i;
            StringBuilder sb = new StringBuilder();
            for (int offset = 0; offset < digest.length; offset++) {
                i = digest[offset];
                if (i < 0)
                    i += 256;
                if (i < 16)
                    sb.append(0);
                sb.append(Integer.toHexString(i));// 通过Integer.toHexString方法把值变为16进制
            }
            return sb.toString().substring(0, length);// 从下标0开始,length目的是截取多少长度的值
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }
    }

    public static long getHour(String date) {
        LocalDateTime startTime = LocalDateTime.parse(date, FORMATTER);

        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();

        // 计算当前时间和订单开始时间之间的时间差
        Duration duration = Duration.between(now, startTime);

        return duration.toHours();
    }

    public double getMoney(String serveTime, double payMoney) {
        double money = 0;
        double deduction = 0;
        double remainingAmount = 0;

        long hour = getHour(serveTime);

        if (hour > 6) {
            money = payMoney;
        } else if (hour >= 3) {
            // 计算扣除30%后的金额
            deduction = payMoney * 0.3;
            remainingAmount = payMoney - deduction;
            money = remainingAmount;
        } else if (hour >= 0) {
            // 计算扣除50%后的金额
            deduction = payMoney * 0.5;
            remainingAmount = payMoney - deduction;
            money = remainingAmount;
        }
        return money;
    }

    public static void main(String[] args) {
        String serveTime = "2023-09-21 16:45:42";
        double payMoney = 0.5;

        double money = 0;
        double deduction = 0;
        double remainingAmount = 0;

        long hour = getHour(serveTime);

        if (hour > 6) {
            money = payMoney;
        } else if (hour >= 3) {
            // 计算扣除30%后的金额
            deduction = payMoney * 0.3;
            remainingAmount = payMoney - deduction;
            money = remainingAmount;
        } else if (hour >= 0) {
            // 计算扣除50%后的金额
            deduction = payMoney * 0.5;
            remainingAmount = payMoney - deduction;
            money = remainingAmount;
        }

        System.out.println(money);
    }
    public int getIsRefund(int businessId, int businessStatus, int ServiceStatus) {
        int IsRefund = 0;
        if ((businessStatus == 1 && ServiceStatus == 0) || (businessStatus == 1 && ServiceStatus == 1)) {
            IsRefund = 0;
        } else if (businessStatus == 2 && ServiceStatus == 2) {
            IsRefund = 1;
        } else if (businessId == 3 && businessStatus == 1 && ServiceStatus == 2) {
            IsRefund = 1;
        }
        return IsRefund;
    }
}