package com.cool.store.job;

import cn.hutool.core.collection.CollStreamUtil;
import com.alibaba.fastjson.JSONObject;
import com.cool.store.constants.CommonConstants;
import com.cool.store.dao.*;
import com.cool.store.dao.tp.TpApplyFormDAO;
import com.cool.store.dao.wallet.WalletTradeDAO;
import com.cool.store.dto.*;
import com.cool.store.dto.store.StoreOrderTimeDTO;
import com.cool.store.entity.*;
import com.cool.store.entity.tp.TpApplyFormDO;
import com.cool.store.entity.wallet.WalletTradeDO;
import com.cool.store.enums.*;
import com.cool.store.enums.tp.TpFormStatusEnum;
import com.cool.store.enums.close.CloseTypeEnum;
import com.cool.store.enums.master.StoreCloseReasonEnum;
import com.cool.store.enums.wallet.WalletTradeModuleEnum;
import com.cool.store.mapper.ApplyLicenseMapper;
import com.cool.store.mapper.LineInfoMapper;
import com.cool.store.mapper.TrainingExperienceMapper;
import com.cool.store.mq.producer.SimpleMessageService;
import com.cool.store.mq.util.HttpRestTemplateService;
import com.cool.store.request.ZxjpApiRequest;
import com.cool.store.request.bigdata.LatestOrderDateRequest;
import com.cool.store.request.tp.TpApplyQueryRequest;
import com.cool.store.request.close.store.CloseStoreApplyRequest;
import com.cool.store.response.bigdata.LatestOrderDateResponse;
import com.cool.store.service.*;
import com.cool.store.service.close.CloseStoreRefundService;
import com.cool.store.service.close.CloseStoreService;
import com.cool.store.service.fees.WalletPayInfoService;
import com.cool.store.service.impl.CommonService;
import com.cool.store.service.store.PreAllocationRecordService;
import com.cool.store.service.tp.TpApplyService;
import com.cool.store.utils.MDCUtils;
import com.cool.store.utils.poi.DateUtils;
import com.cool.store.utils.poi.StringUtils;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class XxlJobHandler {


    @Value("${mybatis.configuration.variables.enterpriseId}")
    private String eid;
    @Resource
    TrainingExperienceMapper trainingExperienceMapper;
    @Value("${xfsg.url}")
    private String xfsgUrl;
    @Resource
    private HttpRestTemplateService httpRestTemplateService;
    @Resource
    LineInfoMapper lineInfoMapper;
    @Resource
    private PreparationService preparationService;
    @Resource
    private LineInterviewDAO lineInterviewDAO;
    @Resource
    private LineInfoDAO lineInfoDAO;
    @Resource
    private ShopInfoDAO shopInfoDAO;
    @Resource
    private ShopStageInfoDAO shopStageInfoDAO;
    @Resource
    private CoolStoreStartFlowService coolStoreStartFlowService;
    @Resource
    private AcceptanceInfoDAO acceptanceInfoDAO;
    @Resource
    private DecorationService decorationService;
    @Resource
    private CommonService commonService;
    @Resource
    private EmployeeTrainingDAO employeeTrainingDAO;
    @Resource
    private XfsgEhrService xfsgEhrService;
    @Resource
    private TempUserDetailDAO tempUserDetailDAO;
    @Resource
    private EnterpriseUserDAO enterpriseUserDAO;
    @Resource
    private UserAuthMappingService userAuthMappingService;
    @Resource
    private OpenAcceptanceInfoDAO openAcceptanceInfoDAO;
    @Resource
    private SimpleMessageService simpleMessageService;
    @Resource
    ApplyLicenseMapper applyLicenseMapper;
    @Resource
    private TallyBookService   tallyBookService;
    @Resource
    ShopAccountDAO accountDAO;
    @Resource
    ShopAccountDAO shopAccountDAO;
    @Resource
    ShopAccountService shopAccountService;

    @Resource
    PushService pushService;
    @Resource
    StoreDao storeDao;
    @Resource
    ThirdBigDataService thirdBigDataService;
    @Resource
    TpApplyFormDAO tpApplyFormDAO;
    @Resource
    TpApplyService tpApplyService;
    @Resource
    CloseStoreService closeStoreService;
    @Resource
    CloseStoreRefundInfoDAO closeStoreRefundInfoDAO;
    @Resource
    ThirdXgjService thirdXgjService;
    @Resource
    CloseStoreRefundService closeStoreRefundService;
    @Resource
    WalletPayInfoService walletPayInfoService;
    @Resource
    WalletTradeDAO walletTradeDAO;
    @Resource
    PreAllocationRecordService preAllocationRecordService;
    @Resource
    SplitOrderService splitOrderService;
    @Resource
    WithdrawApplicationService withdrawApplicationService;


    /**
     * @Auther: wangshuo
     * @Date: 2024/4/29
     * @description: 每天更新装修阶段进场时间等
     */
    @XxlJob("updateEntryTime")
    public void updateEntryTime() {
        log.info("----定时任务每天更新装修阶段进场时间，施工完成时间等----");
        boolean hasNext = true;
        int pageNum = 1;
        int pageSize = 50;
        while (hasNext) {
            PageHelper.startPage(pageNum, pageSize);
            //获取表中进场时间为空的
            List<AcceptanceInfoDO> acceptanceInfoDOS = acceptanceInfoDAO.selectByEntryTimeNull();
            if (CollectionUtils.isEmpty(acceptanceInfoDOS)) {
                log.info("------定时任务结束每天更新至预约状态结束------");
                return;
            }
            for (AcceptanceInfoDO acceptanceInfoDO : acceptanceInfoDOS) {
                int flag = CommonConstants.ZERO;
                while (flag < CommonConstants.TWO) {
                    try {
                        Long shopId = acceptanceInfoDO.getShopId();
                        //施工子阶段 更新装修阶段进场时间等
                        decorationService.getConstruction(shopId);
                        break;
                    } catch (Exception e) {
                        log.error("定时任务设置进场时间失败,shopId:{},e:{}", acceptanceInfoDO.getShopId(), e.getMessage());
                        flag++;
                    }
                }
            }
            hasNext = acceptanceInfoDOS.size() >= pageSize;
            pageNum++;
        }
        log.info("------定时任务结束每天更新至预约状态结束------");
        XxlJobHelper.handleSuccess();
    }


    /**
     * @Auther: wangshuo
     * @Date: 2024/5/10
     * @description:实际进场时间+5天，发送钉钉通知到工程监理
     */
    @XxlJob("threeAcceptanceBookingMessage")
    public void threeAcceptanceBookingMessage() {
        log.info("------定时任务三方验收待预约钉钉通知-----");
        boolean hasNext = true;
        int pageNum = 1;
        int pageSize = 50;
        while (hasNext) {
            PageHelper.startPage(pageNum, pageSize);
            //进场时间不为空的
            List<AcceptanceInfoDO> acceptanceInfoDOS = acceptanceInfoDAO
                    .selectListNotNullEntryTime();
            if (CollectionUtils.isEmpty(acceptanceInfoDOS)) {
                log.info("------定时任务结束三方验收待预约钉钉通知------");
                return;
            }
            for (AcceptanceInfoDO acceptanceInfoDO : acceptanceInfoDOS) {
                int flag = CommonConstants.ZERO;
                //进场时间
                while (flag < CommonConstants.TWO) {
                    try {
                        Date approach = acceptanceInfoDO.getActualEntryTime();
                        LocalDate plusFDays = DateUtils.getPlusFDays(approach, CommonConstants.FOUR);
                        if (plusFDays.equals(LocalDate.now())) {
                            ShopInfoDO shopInfo = shopInfoDAO.getShopInfo(acceptanceInfoDO.getShopId());
                            List<EnterpriseUserDO> supervisor = userAuthMappingService
                                    .getUserByRoleEnumAndRegionIdList(UserRoleEnum.ENGINEER_DEP_SUPERVISOR, shopInfo.getRegionId());
                            LineInfoDO lineInfo = lineInfoDAO.getLineInfo(shopInfo.getLineId());
                            for (EnterpriseUserDO enterpriseUserDO : supervisor) {
                                Map<String, String> messageMap = new HashMap<>();
                                messageMap.put("storeName", shopInfo.getShopName());
                                messageMap.put("partnerUsername", lineInfo.getUsername());
                                messageMap.put("partnerMobile", lineInfo.getMobile());
                                commonService.sendMessage(Arrays.asList(enterpriseUserDO.getUserId()), MessageEnum.MESSAGE_24, messageMap);
                            }
                        }
                        break;
                    } catch (Exception e) {
                        log.error("------定时任务三方验收待预约钉钉通知失败,shopId:{},e:{}", acceptanceInfoDO.getShopId(), e.getMessage());
                        flag++;
                    }
                }
            }
            hasNext = acceptanceInfoDOS.size() >= pageSize;
            pageNum++;
        }
    }

    /**
     * 店铺新店开业状态更新
     */
    @XxlJob("shopOpenAcceptanceStatusUpdate")
    public void shopOpenAcceptanceStatusUpdate() {
        log.info("------店铺新店开业状态更新------");
        int num = openAcceptanceInfoDAO.shopOpenAcceptanceStatusUpdate();
        log.info("------店铺新店开业状态更新完成num:{}------", num);
        XxlJobHelper.handleSuccess();
    }


    @XxlJob("partnerSyncLicense")
    public void partnerSyncLicense() {
        log.info("------start sync license------");
        boolean hasNext = true;
        int pageNum = 1;
        int pageSize = 10;
        List<Long> updateSyncList = new ArrayList<>();
        while (hasNext) {
            PageHelper.startPage(pageNum, pageSize);
            List<LicenseTransactDO> licenseTransactDOS = applyLicenseMapper.queryNotSyncList();
            if (CollectionUtils.isEmpty(licenseTransactDOS)) {
                log.info("------sync license is empty------");
                break;
            }
            List<Long> shopIds = licenseTransactDOS.stream().map(LicenseTransactDO::getShopId).collect(Collectors.toList());
            List<LicenseSyncDTO> infoDOS = shopInfoDAO.getShopAndStoreList(eid, shopIds);
            if (CollectionUtils.isEmpty(infoDOS)) {
                log.info("------sync store is empty------");
            }
            Map<Long, LicenseTransactDO> transactDOMap = licenseTransactDOS.stream().collect(Collectors.toMap(LicenseTransactDO::getShopId, x -> x));
            List<LicenseSyncInfoDTO> pushList = new ArrayList<>();
            List<LicenseTransactDO> pushBusinessList = new ArrayList<>();
            infoDOS.forEach(x -> {
                LicenseTransactDO licenseTransactDO = transactDOMap.get(x.getShopId());
                Integer currentStoreSyncCount = 0;
                if (licenseTransactDO != null) {
                    // 同步营业执照
                    if (StringUtils.isNotEmpty(licenseTransactDO.getCreditUrl())) {
                        pushList.add(createLicenseSyncInfoDTO(x.getStoreId(), CommonConstants.ONE,
                                licenseTransactDO.getCreditUrl(), licenseTransactDO.getIssueTime(), licenseTransactDO.getValidity()));
                        currentStoreSyncCount++;
                        pushBusinessList.add(licenseTransactDO);
                    }

                    // 同步食品经营许可证
                    if (StringUtils.isNotEmpty(licenseTransactDO.getFoodBusinessLicenseUrl())) {
                        pushList.add(createLicenseSyncInfoDTO(x.getStoreId(), CommonConstants.THREE,
                                licenseTransactDO.getFoodBusinessLicenseUrl(), licenseTransactDO.getFoodBusinessStartTime(), licenseTransactDO.getFoodBusinessEndTime()));
                        currentStoreSyncCount++;
                    }

                    // 如果食品证为空且为二证合一，使用营业执照的图片
                    if (StringUtils.isEmpty(licenseTransactDO.getFoodBusinessLicenseUrl()) &&
                            Integer.valueOf(CommonConstants.ONE).equals(licenseTransactDO.getTwoCertificatesOne())) {
                        pushList.add(createLicenseSyncInfoDTO(x.getStoreId(), CommonConstants.THREE,
                                licenseTransactDO.getCreditUrl(), licenseTransactDO.getIssueTime(), licenseTransactDO.getValidity()));
                        currentStoreSyncCount++;
                    }

                    if (currentStoreSyncCount == CommonConstants.TWO) {
                        updateSyncList.add(licenseTransactDO.getId());
                    }

                }
            });
            // 发送消息
            if (!pushList.isEmpty()) {
                LicenseDTO licenseDTO = new LicenseDTO();
                licenseDTO.setEnterpriseId(eid);
                licenseDTO.setRequests(pushList);
                log.info("licenseDTO:{}",JSONObject.toJSONString(licenseDTO));
                simpleMessageService.send(JSONObject.toJSONString(licenseDTO), RocketMqTagEnum.PARTNER_LICENSE_SYNC_QUEUE);
            }
            //工商信息变更
            if (!pushBusinessList.isEmpty()){
                Map<Long, String> transactMap = infoDOS.stream().collect(Collectors.toMap(LicenseSyncDTO::getShopId, LicenseSyncDTO::getStoreId));
                BusinessDTO businessDTO = new BusinessDTO();
                businessDTO.setEnterpriseId(eid);
                businessDTO.setTransactMap(transactMap);
                businessDTO.setRequests(pushBusinessList);
                simpleMessageService.send(JSONObject.toJSONString(businessDTO), RocketMqTagEnum.BUSINESS_SYNC);
            }

            hasNext = licenseTransactDOS.size() >= pageSize;
            pageNum++;
        }

        log.info("licenseDTO:{}",JSONObject.toJSONString(updateSyncList));
        if (CollectionUtils.isNotEmpty(updateSyncList)) {
            applyLicenseMapper.updateSyncFlagByIds(updateSyncList);
        }
        log.info("------sync complete-------");
        XxlJobHelper.handleSuccess();
    }



    private LicenseSyncInfoDTO createLicenseSyncInfoDTO(String storeId, Integer licenseType, String pictureUrl,
                                                        Date startTime, Date endTime) {
        LicenseSyncInfoDTO licenseSyncInfoDTO = null;
        try {
            licenseSyncInfoDTO = new LicenseSyncInfoDTO();
            licenseSyncInfoDTO.setStoreId(storeId);
            licenseSyncInfoDTO.setLicenseTypeId(licenseType);
            licenseSyncInfoDTO.setPicture(pictureUrl);
            licenseSyncInfoDTO.setExpiryType(ExpiryTypeEnum.TEMP.getExpiryType());
            licenseSyncInfoDTO.setExpiryBeginDate(startTime.getTime());

            if (endTime != null) {
                licenseSyncInfoDTO.setExpiryEndDate(endTime.getTime());
            } else {
                // 如果没有有效期，则设置为长期有效
                licenseSyncInfoDTO.setExpiryType(ExpiryTypeEnum.LONG.getExpiryType());
            }
        } catch (Exception e) {
            log.error("createLicenseSyncInfoDTO:{},Exception:{}",JSONObject.toJSONString(licenseSyncInfoDTO),e.getMessage());
        }
        return licenseSyncInfoDTO;
    }


    /**
     * @Auther: wangshuo
     * @Date: 2025/3/28
     * @description:每个月为可以生成记账的门店生成初始化数据
     */
    @XxlJob("initTallyBook")
    public void initTallyBook() {
        log.info("------start initTallyBook------");
        boolean hasNext = true;
        int pageNum = 1;
        int pageSize = 10;
        List<Long> shopIdList = new ArrayList<>();
        while (hasNext) {
            PageHelper.startPage(pageNum, pageSize);
            //获取成功开店的门店
            List<ShopInfoDO> shopList = shopInfoDAO.getShopIdBySuccessOpen(eid);
            if (CollectionUtils.isEmpty(shopList)) {
                log.info("------initTallyBook is empty------");
                break;
            }
            for (ShopInfoDO shopInfoDO : shopList){
                try {
                    tallyBookService.initData( shopInfoDO.getId(), shopInfoDO.getPartnerId());
                }catch (Exception e){
                    log.info("生成记账本数据出错：shopId:{},Exception:{}",shopInfoDO.getId(),e.getMessage());
                }
            }
          if (shopList.size() < pageSize){
              hasNext = false;
          }
          pageNum++;
        }
    }

    @XxlJob("rePush")
    public void rePush() {
        log.info("------start rePush------");
        boolean hasNext = true;
        int pageNum = 1;
        int pageSize = 10;
        while (hasNext) {
            PageHelper.startPage(pageNum, pageSize);
            //获取成功开店的门店
            List<ShopAccountDO> accountDOS = accountDAO.getALlFail();
            if (CollectionUtils.isEmpty(accountDOS)) {
                log.info("------rePush is empty------");
                break;
            }
            for (ShopAccountDO accountDO : accountDOS){
                try {
                    //如果是POS推送成功 修改状态  还要修改阶段数据
                    ZxjpApiRequest data = shopAccountService.getData(accountDO.getShopId(), DownSystemTypeEnum.POS);
                    Boolean successFlag = pushService.pushDataToPOS(data);
                    OpenStatusEnum openStatusEnum = successFlag ? OpenStatusEnum.OPENSTATUSENUM_5 : OpenStatusEnum.OPENSTATUSENUM_6;
                    shopAccountDAO.updateEntryStatusByShopIdAndSystemName(accountDO.getShopId(),Arrays.asList(ShopAccountEnum.HUOMA.getSystemName()),openStatusEnum.getCode());
                }catch (Exception e){
                    log.info("rePush error-> accountDO:{},error:{}",JSONObject.toJSONString(accountDO),e.getMessage());
                }
            }
            if (accountDOS.size() < pageSize){
                hasNext = false;
            }
            pageNum++;
        }
    }

    @XxlJob("latestOrderDate")
    public void latestOrderDate() {
        log.info("------start latestOrderDate------");
        MDCUtils.put(CommonConstants.REQUEST_ID, UUID.randomUUID().toString());
        String param = XxlJobHelper.getJobParam();
        List<String> storeStatus = null;
        if (StringUtils.isNotBlank(param)) {
            storeStatus = Arrays.asList(param.split(","));
        }
        boolean hasNext = true;
        int pageNum = 1;
        int pageSize = CommonConstants.BATCH_SIZE;
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        while (hasNext) {
            PageHelper.startPage(pageNum, pageSize);
            List<StoreDO> storeList = storeDao.getAllStoreIdAndNum(storeStatus);
            if (CollectionUtils.isEmpty(storeList)) {
                break;
            }
            hasNext = storeList.size() >= pageSize;
            List<String> storeNums = CollStreamUtil.toList(storeList, StoreDO::getStoreNum);
            Map<String, String> storeIdMap = CollStreamUtil.toMap(storeList, StoreDO::getStoreNum, StoreDO::getStoreId);
            LatestOrderDateRequest request = new LatestOrderDateRequest(1, pageSize, String.join(",", storeNums));
            List<LatestOrderDateResponse> resList = thirdBigDataService.getLatestOrderDate(request);
            log.info("接口请求门店数量:{}，返回门店数:{}", storeList.size(), resList.size());
            if (CollectionUtils.isNotEmpty(resList)) {
                try {
                    List<StoreOrderTimeDTO> updateList = resList.stream()
                            .map(v -> {
                                Date date = parseDate(v, dateFormat);
                                return Objects.nonNull(date) ? new StoreOrderTimeDTO(storeIdMap.get(v.getStore_code()), date) : null;
                            })
                            .filter(Objects::nonNull)
                            .collect(Collectors.toList());
                    storeDao.batchInsertOrUpdateOrderTime(updateList);
                } catch (Exception e) {
                    log.error("获取最新订货时间失败", e);
                }
            }
            pageNum++;
        }
        log.info("------end latestOrderDate------");
    }

    /**
     * 学校店自动发起闭店
     */
    @XxlJob("schoolStoreApplyClose")
    public void schoolStoreApplyClose() {
        MDCUtils.put(CommonConstants.REQUEST_ID, UUID.randomUUID().toString());
        log.info("------start schoolStoreApplyClose------");
        String param = XxlJobHelper.getJobParam();
        String monthQueryLimit = "3";
        if (StringUtils.isNotBlank(param)) {
            monthQueryLimit = param;
        }
        autoApplyClose(monthQueryLimit, Arrays.asList("store_school_internal", "store_school_external"), true);
        log.info("------end schoolStoreApplyClose------");
    }

    /**
     * 普通店自动发起闭店
     */
    @XxlJob("normalStoreApplyClose")
    public void normalStoreApplyClose() {
        MDCUtils.put(CommonConstants.REQUEST_ID, UUID.randomUUID().toString());
        log.info("------start normalStoreApplyClose------");
        String param = XxlJobHelper.getJobParam();
        String monthQueryLimit = "1";
        if (StringUtils.isNotBlank(param)) {
            monthQueryLimit = param;
        }
        autoApplyClose(monthQueryLimit, Arrays.asList("store_school_internal", "store_school_external"), false);
        log.info("------end normalStoreApplyClose------");
    }

    private void autoApplyClose(String monthQueryLimit, List<String> businessTypes, Boolean inBusinessType) {
        boolean hasNext = true;
        int pageNum = 1;
        int pageSize = CommonConstants.BATCH_SIZE;
        LocalDate latestDate = LocalDate.now().minusMonths(Long.parseLong(monthQueryLimit)).plusDays(1);
        while (hasNext) {
            PageHelper.startPage(pageNum, pageSize);
            List<StoreDO> storeList = storeDao.getNoOrderStore(latestDate, businessTypes, inBusinessType);
            if (CollectionUtils.isEmpty(storeList)) {
                break;
            }
            hasNext = storeList.size() >= pageSize;
            for (StoreDO storeDO : storeList) {
                try {
                    CloseStoreApplyRequest applyRequest = CloseStoreApplyRequest.builder()
                            .planCloseDate(DateUtils.parseDate(LocalDate.now().plusMonths(1).toString()))
                            .closeReason(StoreCloseReasonEnum.REASON0.getCode())
                            .closeType(CloseTypeEnum.NO_ORDER_AUTO.getCloseType())
                            .storeId(storeDO.getStoreId())
                            .build();
                    closeStoreService.applyCloseStore(applyRequest);
                } catch (Exception e) {
                    log.info("自动闭店申请发起失败, storeId:{}, storeName:{}", storeDO.getStoreId(), storeDO.getStoreName());
                    log.info("自动闭店申请发起失败", e);
                }
            }
            pageNum++;
        }
    }

    public Date parseDate(LatestOrderDateResponse v, DateFormat format) {
        try {
            return format.parse(v.getLatest_buy_date());
        } catch (ParseException e) {
            log.error("日期转化失败,storeCode:{},latestBuyDate:{}", v.getStore_code(), v.getLatest_buy_date());
        }
        return null;
    }

    /**
     * 十二分制惩处申请单复议逾期
     */
    @XxlJob("tpPenaltyAppealOverdue")
    public void tpPenaltyAppealOverdue() {
        MDCUtils.put(CommonConstants.REQUEST_ID, UUID.randomUUID().toString());
        log.info("------start tpPenaltyAppealOverdue------");
        boolean hasNext = true;
        int pageNum = 1;
        int pageSize = CommonConstants.BATCH_SIZE;
        TpApplyQueryRequest request = new TpApplyQueryRequest();
        request.setStatusList(Arrays.asList(TpFormStatusEnum.PASS.getStatus(), TpFormStatusEnum.INEFFECTIVE.getStatus()));
        request.setIsPenalty(true);
        request.setIsDraft(0);
        request.setOverdue(true);
        while (hasNext) {
            PageHelper.startPage(pageNum, pageSize);
            List<TpApplyFormDO> list = tpApplyFormDAO.getEffectiveList(request);
            if (CollectionUtils.isEmpty(list)) {
                break;
            }
            hasNext = list.size() >= pageSize;
            List<Long> applyIds = CollStreamUtil.toList(list, TpApplyFormDO::getId);
            try {
                tpApplyFormDAO.updateStatusBatch(applyIds, TpFormStatusEnum.EFFECTIVE);
                list.forEach(form -> {
                    try {
                        tpApplyService.scoreChange(form);
                    } catch (Exception e) {
                        log.info("积分变动失败，formId:{}, storeId:{}", form.getId(), form.getStoreId());
                        log.info("积分变动失败", e);
                    }
                });
            } catch (Exception e) {
                log.error("超过申诉期，更新申请单状态失败", e);
            }
            pageNum++;
        }
        log.info("------end tpPenaltyAppealOverdue------");
    }

    /**
     * 退款订单状态更新
     */
    @XxlJob("refundOrderStatus")
    public void refundOrderStatus() {
        MDCUtils.put(CommonConstants.REQUEST_ID, UUID.randomUUID().toString());
        log.info("------start refundOrderStatus------");
        boolean hasNext = true;
        int pageNum = 1;
        int pageSize = CommonConstants.BATCH_SIZE;
        List<CloseStoreRefundInfoDO> updateList = new ArrayList<>();
        List<CloseStoreRefundInfoDO> completeList = new ArrayList<>();
        while (hasNext) {
            PageHelper.startPage(pageNum, pageSize);
            List<CloseStoreRefundInfoDO> list = closeStoreRefundInfoDAO.getUnfinishedRecords();
            if (CollectionUtils.isEmpty(list)) {
                break;
            }
            hasNext = list.size() >= pageSize;
            closeStoreRefundService.refreshRefund(list, updateList, completeList);
            pageNum++;
        }
        if (CollectionUtils.isNotEmpty(updateList)) {
            for (List<CloseStoreRefundInfoDO> list : Lists.partition(updateList, CommonConstants.BATCH_SIZE)) {
                try {
                    closeStoreRefundInfoDAO.updateRefundStatusBatchById(list);
                } catch (Exception e) {
                    log.error("退款状态更新失败");
                }
            }
        }
        if (CollectionUtils.isNotEmpty(completeList)) {
            for (CloseStoreRefundInfoDO refundInfoDO : completeList) {
                try {
                    closeStoreRefundService.completeRefund(refundInfoDO.getId(), refundInfoDO.getRefundTime());
                } catch (Exception e) {
                    log.error("退款状态更新失败, refundId:{}", refundInfoDO.getId());
                    log.error("退款状态更新失败", e);
                }
            }
        }
        log.info("------end refundOrderStatus------");
    }

    /**
     * 钱包批量转账分账支付状态查询
     */
    @XxlJob("batchTransferQuery")
    public void batchTransferQuery() {
        MDCUtils.put(CommonConstants.REQUEST_ID, UUID.randomUUID().toString());
        log.info("------start batchTransferQuery------");
        boolean hasNext = true;
        int pageNum = 1;
        int pageSize = CommonConstants.BATCH_SIZE;
        while (hasNext) {
            PageHelper.startPage(pageNum, pageSize);
            List<String> batchCodes = walletTradeDAO.getPayingOrderBatchCode(WalletTradeModuleEnum.FRANCHISE_PAY.getModule(), 1);
            hasNext = batchCodes.size() >= pageSize;
            if (CollectionUtils.isEmpty(batchCodes)) {
                break;
            }
            for (String batchCode : batchCodes) {
                try {
                    walletPayInfoService.queryAndUpdateBatchTransferStatus(batchCode);
                } catch (Exception e) {
                    log.error("钱包批量转账分账支付状态查询失败, batchCode:{}", batchCode, e);
                }
            }
            pageNum++;
        }
        log.info("------end batchTransferQuery------");
    }

    @XxlJob("batchTransferStandardStore")
    public void batchTransferStandardStore() {
        MDCUtils.put(CommonConstants.REQUEST_ID, UUID.randomUUID().toString());
        log.info("------start batchTransferStandardStore------");
        boolean hasNext = true;
        int pageNum = 1;
        int pageSize = CommonConstants.BATCH_SIZE;
        while (hasNext) {
            PageHelper.startPage(pageNum, pageSize);
            List<String> batchCodes = walletTradeDAO.getPayingOrderBatchCode(WalletTradeModuleEnum.STANDARD_STORE.getModule(), 1);
            hasNext = batchCodes.size() >= pageSize;
            if (CollectionUtils.isEmpty(batchCodes)) {
                break;
            }
            for (String batchCode : batchCodes) {
                try {
                    preAllocationRecordService.queryAndUpdateBatchTransferStatus(batchCode);
                } catch (Exception e) {
                    log.error("钱包批量转账分账支付状态查询失败, batchCode:{}", batchCode, e);
                }
            }
            pageNum++;
        }
        log.info("------end batchTransferStandardStore------");
        //开始单个分账状态查询
        transferStandardStore();
    }


    public void transferStandardStore() {
        log.info("------start transferStandardStore------");
        boolean hasNext = true;
        int pageNum = 1;
        int pageSize = CommonConstants.BATCH_SIZE;
        while (hasNext) {
            PageHelper.startPage(pageNum, pageSize);
            List<WalletTradeDO> list = walletTradeDAO.getPayingOrder(WalletTradeModuleEnum.STANDARD_STORE.getModule(), 1);
            hasNext = list.size() >= pageSize;
            if (CollectionUtils.isEmpty(list)) {
                break;
            }
            for (WalletTradeDO walletTradeDO : list) {
                try {
                    preAllocationRecordService.transStatusRefresh(walletTradeDO);
                } catch (Exception e) {
                    log.error("钱包单费用类型转账分账支付状态查询失败, walletTradeDO:{}", walletTradeDO, e);
                }
            }
            pageNum++;
        }
        log.info("------end transferStandardStore------");
    }

    @XxlJob("transfer")
    public void transfer() {
        MDCUtils.put(CommonConstants.REQUEST_ID, UUID.randomUUID().toString());
        log.info("------start transfer------");
        boolean hasNext = true;
        int pageNum = 1;
        int pageSize = CommonConstants.BATCH_SIZE;
        while (hasNext) {
            PageHelper.startPage(pageNum, pageSize);
            List<WalletTradeDO> walletTradeDOS = walletTradeDAO.transferTradeList(WalletTradeModuleEnum.TRANSFER.getModule(), 1);
            hasNext = walletTradeDOS.size() >= pageSize;
            if (CollectionUtils.isEmpty(walletTradeDOS)) {
                break;
            }
            for (WalletTradeDO walletTradeDO : walletTradeDOS) {
                try {
                    splitOrderService.updateWalletTrade(walletTradeDO);
                } catch (Exception e) {
                    log.error("钱包转账分账支付状态查询失败, transfer:{}", walletTradeDO.getTradeId(), e);
                }
            }
            pageNum++;
        }
        log.info("------end transfer------");
    }

    @XxlJob("withdrawUpdate")
    public void withdrawUpdate() {
        MDCUtils.put(CommonConstants.REQUEST_ID, UUID.randomUUID().toString());
        log.info("------start withdrawUpdate------");
        boolean hasNext = true;
        int pageNum = 1;
        int pageSize = CommonConstants.BATCH_SIZE;
        while (hasNext) {
            PageHelper.startPage(pageNum, pageSize);
            List<WalletTradeDO> walletTradeDOS = walletTradeDAO.transferTradeList(WalletTradeModuleEnum.TRANSFER.getModule(), 2);
            hasNext = walletTradeDOS.size() >= pageSize;
            if (CollectionUtils.isEmpty(walletTradeDOS)) {
                break;
            }
            for (WalletTradeDO walletTradeDO : walletTradeDOS) {
                try {
                    withdrawApplicationService.updateTrade(walletTradeDO);
                } catch (Exception e) {
                    log.error("钱包提现支付状态查询失败, withdrawUpdate:{}", walletTradeDO.getTradeId(), e);
                }
            }
            pageNum++;
        }
        log.info("------end withdrawUpdate------");
    }
}
