package com.cool.store.service.close.impl;

import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSONObject;
import com.cool.store.constants.CommonConstants;
import com.cool.store.context.CurrentUserHolder;
import com.cool.store.context.LoginUserInfo;
import com.cool.store.context.PartnerUserHolder;
import com.cool.store.dao.*;
import com.cool.store.dao.store.StoreMasterSignerInfoDAO;
import com.cool.store.dto.store.StoreMasterIssueDTO;
import com.cool.store.entity.*;
import com.cool.store.entity.store.StoreMasterSignerInfoDO;
import com.cool.store.enums.*;
import com.cool.store.enums.close.*;
import com.cool.store.enums.master.StoreCloseReasonEnum;
import com.cool.store.exception.ServiceException;
import com.cool.store.mq.producer.SimpleMessageService;
import com.cool.store.request.close.store.*;
import com.cool.store.response.AuditInfoResponse;
import com.cool.store.service.SysRoleService;
import com.cool.store.service.UserAuthMappingService;
import com.cool.store.service.close.CloseStoreService;
import com.cool.store.utils.BeanUtil;
import com.cool.store.utils.CoolDateUtils;
import com.cool.store.utils.poi.StringUtils;
import com.cool.store.vo.PartnerUserInfoVO;
import com.cool.store.vo.close.store.*;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author suzhuhong
 * @Date 2025/9/23 15:48
 * @Version 1.0
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class CloseStoreServiceImpl implements CloseStoreService {

    private final CloseStoreInfoDAO closeStoreInfoDAO;
    private final CloseStoreAuditRecordDAO closeStoreAuditRecordDAO;
    private final UserAuthMappingService userAuthMappingService;
    private final CloseStoreFileInfoDAO closeStoreFileInfoDAO;
    private final CloseStoreFileDetailDAO closeStoreFileDetailDAO;
    private final CloseStoreAccountInfoDAO closeStoreAccountInfoDAO;
    private final CloseStoreStageInfoDAO closeStoreStageInfoDAO;
    private final StoreDao storeDao;
    private final RegionDao regionDao;
    private final EnterpriseUserRoleDao enterpriseUserRoleDao;
    private final StoreMasterSignerInfoDAO storeMasterSignerInfoDAO;
    private final SimpleMessageService simpleMessageService;
    private final CloseStoreRefundInfoDAO closeStoreRefundInfoDAO;
    private final EnterpriseUserDAO enterpriseUserDAO;
    private final SysRoleService sysRoleService;

    @Value("${mybatis.configuration.variables.enterpriseId}")
    private String enterpriseId;


    @Override
    @Transactional
    public Boolean applyCloseStore(CloseStoreApplyRequest request) {
        // 查询当前当前门店 校验门店状态
        StoreDO store = storeDao.getByStoreId(request.getStoreId());
        if (store == null){
            throw new ServiceException(ErrorCodeEnum.STORE_NOT_EXIST);
        }
        if (CommonConstants.CLOSED.equals(store.getStoreStatus())){
            throw new ServiceException(ErrorCodeEnum.STORE_NOT_OPEN);
        }
        if (!(StoreStatusEnum.OPEN.getValue().equals(store.getStoreStatus()) || StoreStatusEnum.CLOSE_UP.getValue().equals(store.getStoreStatus()))) {
            throw new ServiceException(ErrorCodeEnum.CLOSE_STORE_ONLY_SUPPORT_OPEN);
        }
        // 校验是否有正在进行的申请
        if (closeStoreInfoDAO.existOngoingRecord(request.getStoreId())) {
            throw new ServiceException(ErrorCodeEnum.CLOSE_STORE_EXIST_ONGOING_RECORD);
        }
        RegionDO regionDO = regionDao.getRegionByStoreId(store.getStoreId());
        if (Objects.isNull(regionDO)) {
            throw new ServiceException(ErrorCodeEnum.REGION_NOT_EXIST);
        }
        String userId, userName;
        if (CloseTypeEnum.INITIATE.getCloseType().equals(request.getCloseType())) {
            // 主动发起的申请人为加盟商，从C端登录用户信息中获取
            PartnerUserInfoVO user = PartnerUserHolder.getUser();
            userId = user.getPartnerId();
            userName = user.getUsername();
            if (StringUtils.isBlank(userName)) {
                userName = user.getMobile();
            }
        } else {
            userId = AIEnum.AI_ID.getCode();
            userName = AIEnum.AI_NAME.getCode();
        }
        CloseStoreInfoDO closeStoreInfoDO = new CloseStoreInfoDO();
        closeStoreInfoDO.setCloseStoreNo(generateCloseStoreNo());
        closeStoreInfoDO.setStoreId(request.getStoreId());
        closeStoreInfoDO.setRegionId(regionDO.getId());
        closeStoreInfoDO.setPlanCloseData(request.getPlanCloseDate());
        closeStoreInfoDO.setCloseType(request.getCloseType());
        closeStoreInfoDO.setCloseReason(request.getCloseReason());
        closeStoreInfoDO.setReasonDescription(request.getReasonDescription());
        closeStoreInfoDO.setCloseStatus(CloseStoreStatusEnum.UNDER_APPROVAL.getCloseStoreStatus());
        closeStoreInfoDO.setApplyUserId(userId);
        closeStoreInfoDAO.insertSelective(closeStoreInfoDO);
        // 查询督导
        List<String> auditUserIds = getAuditUserIds(regionDO.getId(), UserRoleEnum.SUPERVISION);
        closeStoreAuditRecordDAO.addRecord(closeStoreInfoDO.getId(), userId, userName, auditUserIds);
        return Boolean.TRUE;
    }

    @Override
    @Transactional
    public Boolean reApplyCloseStore(ReCloseStoreApplyRequest request) {
        CloseStoreInfoDO closeStoreInfoDO = closeStoreInfoDAO.getById(request.getCloseStoreId());
        if (Objects.isNull(closeStoreInfoDO)) {
            throw new ServiceException(ErrorCodeEnum.CLOSE_STORE_INFO_NOT_EXIST);
        }
        CloseStoreApplyRequest applyRequest = CloseStoreApplyRequest.builder()
                .planCloseDate(closeStoreInfoDO.getPlanCloseData())
                .closeReason(closeStoreInfoDO.getCloseReason())
                .reasonDescription(closeStoreInfoDO.getReasonDescription())
                .closeType(closeStoreInfoDO.getCloseType())
                .storeId(closeStoreInfoDO.getStoreId())
                .build();
        return applyCloseStore(applyRequest);
    }

    @Override
    @Transactional
    public Boolean thirdApplyCloseStore(ThirdCloseStoreApplyRequest request) {
        StoreDO storeDO = storeDao.getByStoreNum(request.getStoreNum());
        if (Objects.isNull(storeDO)) {
            throw new ServiceException(ErrorCodeEnum.STORE_NOT_EXIST);
        }
        CloseStoreApplyRequest closeRequest = request.convert(storeDO.getStoreId());
        return applyCloseStore(closeRequest);
    }

    @Override
    @Transactional
    public Boolean auditPass(CloseStoreAuditRequest request) {
        CloseStoreAuditRecordDO auditRecordDO = closeStoreAuditRecordDAO.getById(request.getAuditRecordId());
        // 校验审批权限
        auditVerify(auditRecordDO);
        CloseStoreInfoDO closeStoreInfoDO = closeStoreInfoDAO.getById(auditRecordDO.getCloseStoreId());
        if (Objects.isNull(closeStoreInfoDO)) {
            throw new ServiceException(ErrorCodeEnum.CLOSE_STORE_INFO_NOT_EXIST);
        }
        // 修改闭店申请信息
        Integer currentCloseStatus = closeStoreInfoDO.getCloseStatus();
        Integer nextCloseStatus = CloseStoreStatusEnum.getNextPassStatus(currentCloseStatus);
        if (Objects.nonNull(request.getCloseReason())) {
            closeStoreInfoDO.setCloseReason(request.getCloseReason());
        }
        closeStoreInfoDO.setActualCloseData(request.getActualCloseData());
        closeStoreInfoDO.setCloseStatus(nextCloseStatus);
        closeStoreInfoDAO.updateSelective(closeStoreInfoDO);
        // 修改闭店审批信息
        auditRecordDO.setAuditStatus(CloseStoreAuditStatusEnum.PASS.getStatus());
        auditRecordDO.setActionRemark(request.getRemark());
        auditRecordDO.setHandlerUserId(CurrentUserHolder.getUserId());
        auditRecordDO.setHandlerUserName(CurrentUserHolder.getUser().getName());
        auditRecordDO.setFinishTaskTime(new Date());
        closeStoreAuditRecordDAO.updateRecord(auditRecordDO);
        // 督导审批结束后为大区经理审批
        if (CloseStoreStatusEnum.MANAGER_UNDER_APPROVAL.getCloseStoreStatus().equals(nextCloseStatus)) {
            // 新增大区老总审批
            List<String> auditUserIds = getAuditUserIds(closeStoreInfoDO.getRegionId(), UserRoleEnum.OPERATION_GENERAL_CONSULTANT);
            closeStoreAuditRecordDAO.addApproveRecord(closeStoreInfoDO.getId(), auditUserIds);
        } else {
            // 完成闭店，再进入闭店流程
            closeStoreFlowInit(closeStoreInfoDO, closeStoreInfoDO.getStoreId(), closeStoreInfoDO.getCloseReason());
        }
        return true;
    }

    @Override
    @Transactional
    public Boolean auditReject(CloseStoreAuditRequest request) {
        CloseStoreAuditRecordDO auditRecordDO = closeStoreAuditRecordDAO.getById(request.getAuditRecordId());
        // 校验审批权限
        auditVerify(auditRecordDO);
        CloseStoreInfoDO closeStoreInfoDO = closeStoreInfoDAO.getById(auditRecordDO.getCloseStoreId());
        if (Objects.isNull(closeStoreInfoDO)) {
            throw new ServiceException(ErrorCodeEnum.CLOSE_STORE_INFO_NOT_EXIST);
        }
        closeStoreInfoDO.setCloseStatus(CloseStoreStatusEnum.REVIEW_NOT_APPROVED.getCloseStoreStatus());
        closeStoreInfoDAO.updateSelective(closeStoreInfoDO);
        // 修改闭店审批信息
        auditRecordDO.setAuditStatus(CloseStoreAuditStatusEnum.REJECTED.getStatus());
        auditRecordDO.setActionRemark(request.getRemark());
        auditRecordDO.setHandlerUserId(CurrentUserHolder.getUserId());
        auditRecordDO.setHandlerUserName(CurrentUserHolder.getUser().getName());
        auditRecordDO.setFinishTaskTime(new Date());
        closeStoreAuditRecordDAO.updateRecord(auditRecordDO);
        return true;
    }

    @Override
    @Transactional
    public Boolean cancelApply(Long closeStoreId) {
        CloseStoreInfoDO closeStoreInfoDO = closeStoreInfoDAO.getById(closeStoreId);
        if (Objects.isNull(closeStoreInfoDO)) {
            throw new ServiceException(ErrorCodeEnum.CLOSE_STORE_INFO_NOT_EXIST);
        }
        if (CloseStoreStatusEnum.CANCELED.getCloseStoreStatus().equals(closeStoreInfoDO.getCloseStatus())) {
            throw new ServiceException(ErrorCodeEnum.CLOSE_STORE_CANCELED);
        }
        // 未审批前能够取消
        if (!CloseStoreStatusEnum.UNDER_APPROVAL.getCloseStoreStatus().equals(closeStoreInfoDO.getCloseStatus())) {
            throw new ServiceException(ErrorCodeEnum.CLOSE_STORE_CANCEL_ERROR);
        }
        // 非申请人无法取消
        if (!closeStoreInfoDO.getApplyUserId().equals(PartnerUserHolder.getUser().getPartnerId())) {
            throw new ServiceException(ErrorCodeEnum.CLOSE_STORE_IS_NOT_APPLICANT);
        }
        // 修改闭店申请信息
        closeStoreInfoDO.setCloseStatus(CloseStoreStatusEnum.CANCELED.getCloseStoreStatus());
        closeStoreInfoDAO.updateSelective(closeStoreInfoDO);
        // 删除待处理的审批记录
        closeStoreAuditRecordDAO.deletePendingRecord(closeStoreId);
        return true;
    }

    @Override
    public PageInfo<CloseStoreInfoListVO> closeStoreAuditList(CloseStoreQueryRequest request) {
        closeStoreRecordQueryBefore(request);
        if (Objects.isNull(request.getAuditStatus())) {
            request.setAuditStatus(CloseStoreAuditStatusEnum.PENDING.getStatus());
        }
        LoginUserInfo user = CurrentUserHolder.getUser();
        Boolean isAdmin = enterpriseUserRoleDao.checkIsAdmin(user.getUserId());
        PageInfo<CloseStoreInfoListVO> pageInfo = closeStoreAuditRecordDAO.getCloseStoreAuditList(request, user.getUserId(), isAdmin);
        fillCloseStoreRecord(request, pageInfo.getList());
        return pageInfo;
    }

    @Override
    public PageInfo<CloseStoreInfoListVO> closeStoreInfoList(CloseStoreQueryRequest request) {
        closeStoreRecordQueryBefore(request);
        request.setQueryStore(true);
        String userId = CurrentUserHolder.getUserId();
        Boolean isAdmin = enterpriseUserRoleDao.checkIsAdmin(userId);
        List<String> regionIds = new ArrayList<>();
        if (!isAdmin) {
            List<UserAuthMappingDO> userAuthMappingDOS = userAuthMappingService.listUserAuthMappingByUserId(userId);
            if (CollectionUtils.isEmpty(userAuthMappingDOS)) {
                return new PageInfo<>();
            }
            regionIds = CollStreamUtil.toList(userAuthMappingDOS, UserAuthMappingDO::getMappingId);
        }
        PageInfo<CloseStoreInfoListVO> pageInfo = closeStoreInfoDAO.getCloseStoreInfoList(request, regionIds);
        fillCloseStoreRecord(request, pageInfo.getList());
        List<Long> closeStoreIds = CollStreamUtil.toList(pageInfo.getList(), CloseStoreInfoListVO::getCloseStoreId);
        Map<Long, Long> completeCountMap = closeStoreStageInfoDAO.getCompleteCountMap(closeStoreIds);
        Map<Long, Long> auditIdMap = closeStoreAuditRecordDAO.getPendingAuditIdByCloseStoreIds(closeStoreIds);
        pageInfo.getList().forEach(v -> {
            v.setCompleteProcessNum(completeCountMap.getOrDefault(v.getCloseStoreId(), 0L).intValue());
            v.setTotalProcessNum(CloseStoreSubStageEnum.values().length);
            v.setAuditRecordId(auditIdMap.get(v.getCloseStoreId()));
        });
        return pageInfo;
    }

    @Override
    public List<AuditInfoResponse> getAuditRecordList(Long closeStoreId) {
        CloseStoreInfoDO closeStoreInfoDO = closeStoreInfoDAO.getById(closeStoreId);
        if (Objects.isNull(closeStoreInfoDO)) {
            throw new ServiceException(ErrorCodeEnum.CLOSE_STORE_INFO_NOT_EXIST);
        }
        List<CloseStoreAuditRecordDO> list = closeStoreAuditRecordDAO.getListByCloseStoreId(closeStoreId);
        Set<String> userIds = new HashSet<>();
        list.forEach(v -> {
            if (!CommonConstants.INDEX_ONE.equals(v.getRecordType()) || CloseTypeEnum.NO_ORDER_AUTO.getCloseType().equals(closeStoreInfoDO.getCloseType())) {
                userIds.addAll(StringUtils.isNotBlank(v.getHandlerUserIds()) ? Arrays.asList(v.getHandlerUserIds().split(",")) : Collections.emptyList());
            }
        });
        Map<String, EnterpriseUserDO> userMap = enterpriseUserDAO.getUserMap(new ArrayList<>(userIds));
        List<AuditInfoResponse> result = new ArrayList<>();
        for (int i = 0; i < list.size(); i++) {
            CloseStoreAuditRecordDO auditRecordDO = list.get(i);
            AuditInfoResponse auditInfo = AuditInfoResponse.builder()
                    .type(getAuditInfoType(auditRecordDO.getRecordType(), auditRecordDO.getAuditStatus()))
                    // 0加盟商发起 1云流水发起 2督导审批 3大区经理审批
                    .execute(i == 0 ? (CloseTypeEnum.INITIATE.getCloseType().equals(closeStoreInfoDO.getCloseType()) ? 0 : 1) : i + 1)
                    .status(CommonConstants.INDEX_ZERO.equals(auditRecordDO.getAuditStatus()) ? 0 : 1)
                    .createTime(auditRecordDO.getCreateTime())
                    .remark(auditRecordDO.getActionRemark())
                    .actualUserId(auditRecordDO.getHandlerUserId())
                    .build();
            List<AuditInfoResponse.AuditUserInfoVO> auditUserList = Arrays.stream(auditRecordDO.getHandlerUserIds().split(","))
                    .filter(StringUtils::isNotBlank)
                    .map(v -> {
                        String userName = null, avatar = null;
                        if (CommonConstants.INDEX_ZERO.equals(auditInfo.getExecute())) {
                            userName = auditRecordDO.getHandlerUserName();
                        } else {
                            EnterpriseUserDO user = userMap.get(v);
                            if (Objects.nonNull(user)) {
                                userName = user.getName();
                                avatar = user.getAvatar();
                            }
                        }
                        return new AuditInfoResponse.AuditUserInfoVO(v, userName, avatar);
                    })
                    .collect(Collectors.toList());
            auditInfo.setList(auditUserList);
            result.add(auditInfo);
        }
        return result;
    }

    public static Integer getAuditInfoType(Integer recordType, Integer auditStatus) {
        if (CommonConstants.INDEX_ONE.equals(recordType)) {
            return OperationLogAuditEnum.SUBMIT_AUDIT.getCode();
        } else {
            switch (auditStatus) {
                case 0:
                    return OperationLogAuditEnum.WAIT_AUDIT.getCode();
                case 1:
                    return OperationLogAuditEnum.PASS.getCode();
                case 2:
                    return OperationLogAuditEnum.REFUSE.getCode();
                default:
                    return null;
            }
        }
    }

    @Override
    public CloseStoreInfoDetailVO getCloseStoreInfoDetail(Long closeStoreId, Boolean queryAuditId) {
        CloseStoreInfoDO closeStoreInfoDO = closeStoreInfoDAO.getById(closeStoreId);
        if (Objects.isNull(closeStoreInfoDO)) {
            throw new ServiceException(ErrorCodeEnum.CLOSE_STORE_INFO_NOT_EXIST);
        }
        CloseStoreInfoDetailVO vo = new CloseStoreInfoDetailVO();
        BeanUtil.copyProperties(closeStoreInfoDO, vo);

        StoreDO storeDO = storeDao.getByStoreId(closeStoreInfoDO.getStoreId());
        if (Objects.nonNull(storeDO)) {
            BeanUtil.copyPropertiesIgnoreId(storeDO, vo);
        }
        StoreMasterSignerInfoDO signerInfoDO = storeMasterSignerInfoDAO.getByStoreId(closeStoreInfoDO.getStoreId());
        if (Objects.nonNull(signerInfoDO)) {
            BeanUtil.copyPropertiesIgnoreId(signerInfoDO, vo);
        }
        if (Boolean.TRUE.equals(queryAuditId)) {
            CloseStoreAuditRecordDO pendingAuditRecord = closeStoreAuditRecordDAO.getPendingAuditRecord(closeStoreId);
            if (Objects.nonNull(pendingAuditRecord)) {
                vo.setAuditId(pendingAuditRecord.getId());
            }
        }
        return vo;
    }

    @Override
    public CloseStoreInfoDetailVO getCloseStoreInfoDetailByAuditId(Long closeStoreAuditId) {
        CloseStoreAuditRecordDO auditRecordDO = closeStoreAuditRecordDAO.getById(closeStoreAuditId);
        if (Objects.isNull(auditRecordDO)) {
            throw new ServiceException(ErrorCodeEnum.CLOSE_STORE_AUDIT_RECORD_NOT_EXIST);
        }
        CloseStoreInfoDetailVO vo = getCloseStoreInfoDetail(auditRecordDO.getCloseStoreId(), null);
        vo.setAuditId(auditRecordDO.getId());
        return vo;
    }

    @Override
    public List<StoreCloseReasonVO> getStoreCloseReasonList(Integer closeType) {
        return Arrays.stream(StoreCloseReasonEnum.values())
                .filter(v -> Objects.isNull(closeType) || v.getCloseNature().getCloseType().getCloseType().equals(closeType))
                .map(v -> new StoreCloseReasonVO(v.getCode(), v.getDesc(), v.getCloseNature().getCloseType().getCloseType()))
                .collect(Collectors.toList());
    }

    @Override
    public CloseStoreSimpleVO getCloseStoreSimpleInfo(Long closeStoreId) {
        CloseStoreInfoDetailVO detail = getCloseStoreInfoDetail(closeStoreId, null);
        CloseStoreSimpleVO vo = BeanUtil.toBean(detail, CloseStoreSimpleVO.class);
        vo.setCompleteProcessNum(closeStoreStageInfoDAO.getCompleteCount(closeStoreId));
        vo.setTotalProcessNum(CloseStoreSubStageEnum.values().length);
        List<CloseStoreStageInfoDO> stageInfoList = closeStoreStageInfoDAO.getList(closeStoreId);
        List<CloseStoreSubStageStatusVO> subStageList = BeanUtil.toList(stageInfoList, CloseStoreSubStageStatusVO.class);
        vo.setStageList(subStageList);
        return vo;
    }

    @Override
    public PageInfo<MiniCloseStoreSimpleVO> getMiniCloseStoreSimpleInfoList(MiniCloseStoreQueryRequest request) {
        String userId = PartnerUserHolder.getUser().getPartnerId();
        PageHelper.startPage(request.getPageNum(), request.getPageSize());
        List<CloseStoreInfoDO> list = closeStoreInfoDAO.getListByApplyUserId(userId, CloseTypeEnum.INITIATE.getCloseType(), request.getStoreId());
        PageInfo<CloseStoreInfoDO> pageInfo = new PageInfo<>(list);
        PageInfo<MiniCloseStoreSimpleVO> voPage = BeanUtil.toPage(pageInfo, MiniCloseStoreSimpleVO.class);

        Set<String> storeIds = CollStreamUtil.toSet(list, CloseStoreInfoDO::getStoreId);
        List<StoreDO> storeList = storeDao.getEffectiveStoreByStoreIds(new ArrayList<>(storeIds));
        Map<String, StoreDO> storeMap = CollStreamUtil.toMap(storeList, StoreDO::getStoreId, v -> v);

        voPage.getList().forEach(v -> {
            StoreDO storeDO = storeMap.get(v.getStoreId());
            if (Objects.nonNull(storeDO)) {
                BeanUtil.copyPropertiesIgnoreId(storeDO, v, "createTime");
            }
        });
        return voPage;
    }

    @Override
    public List<CloseStoreStatusVO> getCloseStoreStatusList() {
        return Arrays.stream(CloseStoreStatusEnum.values())
                .filter(v -> v != CloseStoreStatusEnum.MANAGER_UNDER_APPROVAL)
                .map(v -> new CloseStoreStatusVO(v.getCloseStoreStatus(), v.getCloseStoreStatusName()))
                .collect(Collectors.toList());
    }

    @Override
    @Transactional
    public void closeStoreProcessFlow(Long closeStoreId, CloseStoreSubStageEnum currentSubStage) {
        CloseStoreStageInfoDO currentStage = closeStoreStageInfoDAO.getByStage(closeStoreId, currentSubStage.getCloseStoreStageEnum().getCloseStoreStage(), currentSubStage.getCloseStoreSubStage());
        CloseStoreSubStageStatusEnum stageStatus = CloseStoreSubStageStatusEnum.getByStatus(currentStage.getShopSubStageStatus());
        // 已结束或未开始的流程不流转
        if (Objects.nonNull(stageStatus) && !CloseStoreSubStageStatusEnum.CLOSE_STORE_SUB_STAGE_STATUS_00.equals(stageStatus) && !stageStatus.isTerminated()) {
            // 下个子阶段状态
            CloseStoreSubStageStatusEnum nextStageStatus = CloseStoreSubStageStatusEnum.getNextStageStatus(stageStatus);
            if (Objects.nonNull(nextStageStatus)) {
                log.info("进入子阶段下一阶段:{}, status:{}[{}]", nextStageStatus.getShopSubStageName(), nextStageStatus.getShopSubStageStatusName(), nextStageStatus.getShopSubStageStatus());
                currentStage.setShopSubStageStatus(nextStageStatus.getShopSubStageStatus());
                currentStage.setIsTerminated(nextStageStatus.isTerminated() ? 1 : 0);
                currentStage.setUpdateTime(new Date());
                if (nextStageStatus.isTerminated()) {
                    currentStage.setActualCompleteTime(CoolDateUtils.getCurrentDateTime());
                }
                closeStoreStageInfoDAO.updateSelective(currentStage);
                if (nextStageStatus.isTerminated()) {
                    // 当前子阶段结束，开始下一个子阶段
                    log.info("当前子阶段结束，进入下一个子阶段");
                    openNextSubStage(closeStoreId, currentSubStage);
                }
            }
        }

    }

    /**
     * 开启下一个子阶段
     * @param closeStoreId 闭店申请ID
     * @param currentSubStage 当前子阶段
     */
    public void openNextSubStage(Long closeStoreId, CloseStoreSubStageEnum currentSubStage) {
        // 根据当前子阶段获取下一个需要开启的子阶段列表
        List<CloseStoreSubStageEnum> nextSubStages = CloseStoreSubStageEnum.getNextSubStage(currentSubStage);
        if (CollectionUtils.isEmpty(nextSubStages)) {
            // 不存在下一子阶段，校验当前所有子阶段状态，修改闭店申请状态
            log.info("当前子阶段结束，不存在下一子阶段");
            verifyAndUpdateCloseStoreStatus(closeStoreId);
            return;
        }
        log.info("开启子阶段:{}", StringUtils.join(CollStreamUtil.toList(nextSubStages, CloseStoreSubStageEnum::getCloseStoreSubStageName), ","));
        List<Integer> subStageList = CollStreamUtil.toList(nextSubStages, CloseStoreSubStageEnum::getCloseStoreSubStage);
        List<CloseStoreStageInfoDO> stageInfoList = closeStoreStageInfoDAO.getBySubStage(closeStoreId, subStageList);
        Map<Integer, Map<Integer, CloseStoreStageInfoDO>> stageMap = CollStreamUtil.group2Map(stageInfoList, CloseStoreStageInfoDO::getShopStage, CloseStoreStageInfoDO::getShopSubStage);

        List<CloseStoreStageInfoDO> updateStageList = new ArrayList<>();
        for (CloseStoreSubStageEnum nextSubStage : nextSubStages) {
            CloseStoreStageInfoDO stageInfoDO = stageMap.getOrDefault(nextSubStage.getCloseStoreStageEnum().getCloseStoreStage(), Collections.emptyMap())
                    .get(nextSubStage.getCloseStoreSubStage());
            if (Objects.nonNull(stageInfoDO)) {
                // 获取子阶段开始的状态
                CloseStoreSubStageStatusEnum openStageStatus = CloseStoreSubStageStatusEnum.getOpenStageStatus(nextSubStage);
                if (Objects.nonNull(openStageStatus)) {
                    CloseStoreStageInfoDO updateStageInfo = CloseStoreStageInfoDO.builder()
                            .id(stageInfoDO.getId())
                            .shopSubStageStatus(openStageStatus.getShopSubStageStatus())
                            .build();
                    updateStageList.add(updateStageInfo);
                }
            }
        }
        if (CollectionUtils.isNotEmpty(updateStageList)) {
            closeStoreStageInfoDAO.updateBatchSelective(updateStageList);
        }
    }

    /**
     * 校验当前所有子阶段状态，修改闭店申请状态
     * @param closeStoreId 闭店申请ID
     */
    public void verifyAndUpdateCloseStoreStatus(Long closeStoreId) {
        if (!closeStoreStageInfoDAO.existUnfinishedStage(closeStoreId)) {
            // 所有子阶段都完成，修改闭店申请状态为已完成
            CloseStoreInfoDO closeStoreInfoDO = closeStoreInfoDAO.getById(closeStoreId);
            if (Objects.nonNull(closeStoreInfoDO)) {
                log.info("所有子阶段完成");
                closeStoreInfoDAO.updateSelective(CloseStoreInfoDO.builder().id(closeStoreId).closeStatus(CloseStoreStatusEnum.COMPLETED.getCloseStoreStatus()).build());
            }
        }
    }


    /**
     * 查询前置处理
     */
    private void closeStoreRecordQueryBefore(CloseStoreQueryRequest request) {
        request.setQueryStore(StringUtils.isNotBlank(request.getStoreNameOrNum()) || StringUtils.isNotBlank(request.getJoinBrandList()));
        request.setQuerySigner(StringUtils.isNotBlank(request.getSignerName()) || StringUtils.isNotBlank(request.getSignerMobile()));
        if (StringUtils.isNotBlank(request.getJoinBrandList())) {
            request.setJoinBrands(Arrays.stream(request.getJoinBrandList().split(",")).map(Integer::parseInt).collect(Collectors.toList()));
        }
    }

    /**
     * 补充字段
     */
    private void fillCloseStoreRecord(CloseStoreQueryRequest request, List<CloseStoreInfoListVO> list) {
        Set<String> storeIds = new HashSet<>();
        Set<String> signerStoreIds = new HashSet<>();
        if (!request.getQueryStore() || !request.getQuerySigner()) {
            for (CloseStoreInfoListVO v : list) {
                if (!request.getQueryStore()) {
                    storeIds.add(v.getStoreId());
                }
                if (!request.getQuerySigner()) {
                    signerStoreIds.add(v.getStoreId());
                }
            }
        }
        Map<String, StoreDO> storeMap = Collections.emptyMap();
        Map<String, StoreMasterSignerInfoDO> signerMap = Collections.emptyMap();
        if (CollectionUtil.isNotEmpty(storeIds)) {
            List<StoreDO> storeList = storeDao.getEffectiveStoreByStoreIds(new ArrayList<>(storeIds));
            storeMap = CollStreamUtil.toMap(storeList, StoreDO::getStoreId, v -> v);
        }
        if (CollectionUtil.isNotEmpty(signerStoreIds)) {
            signerMap = storeMasterSignerInfoDAO.getSignerMapByStoreIds(new ArrayList<>(signerStoreIds));
        }
        if (!request.getQueryStore() || !request.getQuerySigner()) {
            for (CloseStoreInfoListVO v : list) {
                StoreDO storeDO = storeMap.get(v.getStoreId());
                if (Objects.nonNull(storeDO)) {
                    BeanUtil.copyPropertiesIgnoreId(storeDO, v);
                }
                StoreMasterSignerInfoDO signerInfoDO = signerMap.get(v.getStoreId());
                if (Objects.nonNull(signerInfoDO)) {
                    BeanUtil.copyPropertiesIgnoreId(signerInfoDO, v);
                }
            }
        }
    }

    /**
     * 进入闭店流程初始化
     */
    private void closeStoreFlowInit(CloseStoreInfoDO closeStoreInfoDO, String storeId, Integer closeReason) {
        Long closeStoreId = closeStoreInfoDO.getId();
        // 闭店资料初始化
        closeStoreFileInfoDAO.init(closeStoreId);
        closeStoreFileDetailDAO.init(closeStoreId);
        // 闭店账号初始化
        closeStoreAccountInfoDAO.init(closeStoreId);
        // 闭店流程初始化
        closeStoreStageInfoDAO.initStageInfo(closeStoreId);
        // 门店改为闭店，闭店时间为当前时间
        StoreCloseReasonEnum closeReasonEnum = StoreCloseReasonEnum.getByCode(closeReason);
        assert closeReasonEnum != null;
        storeDao.closeStore(storeId, closeReasonEnum.getCode(), closeReasonEnum.getCloseNature().getCode(), closeStoreInfoDO.getActualCloseData());
        // 用mq通知主应用下发门店主数据
        try {
            StoreMasterIssueDTO storeMasterIssueDTO = new StoreMasterIssueDTO(enterpriseId, Collections.singletonList(storeId));
            simpleMessageService.send(JSONObject.toJSONString(storeMasterIssueDTO), RocketMqTagEnum.STORE_MASTER_ISSUE);
        } catch (Exception e) {
            log.error("mq通知主应用下发门店主数据失败");
        }
    }

    /**
     * 审批校验
     * @param auditRecordDO 审批记录
     */
    private void auditVerify(CloseStoreAuditRecordDO auditRecordDO) {
        if (Objects.isNull(auditRecordDO)) {
            throw new ServiceException(ErrorCodeEnum.CLOSE_STORE_AUDIT_RECORD_NOT_EXIST);
        }
        if (!CloseStoreAuditStatusEnum.PENDING.getStatus().equals(auditRecordDO.getAuditStatus())) {
            throw new ServiceException(ErrorCodeEnum.CLOSE_STORE_HAS_BEEN_COMPLETED);
        }
        // 是否有审批权限
        String currentUserId = CurrentUserHolder.getUserId();
        if (sysRoleService.checkIsAdmin(currentUserId)) {
            return;
        }
        if (StringUtils.isBlank(auditRecordDO.getHandlerUserIds())) {
            throw new ServiceException(ErrorCodeEnum.NO_APPROVAL_AUTHORITY);
        }
        List<String> userIds = Arrays.asList(auditRecordDO.getHandlerUserIds().split(","));
        if (!userIds.contains(currentUserId)) {
            throw new ServiceException(ErrorCodeEnum.NO_APPROVAL_AUTHORITY);
        }
    }

    /**
     * 获取拥有区域管辖权限的指定角色用户
     * @param regionId 区域id
     * @param userRoleEnum 角色枚举
     * @return 用户id列表
     */
    private List<String> getAuditUserIds(Long regionId, UserRoleEnum userRoleEnum) {
        List<EnterpriseUserDO> allUserByRoleEnumAndRegionId = userAuthMappingService.getAllUserByRoleEnumAndRegionId(userRoleEnum, regionId);
        return ListUtils.emptyIfNull(allUserByRoleEnumAndRegionId).stream().map(EnterpriseUserDO::getUserId).distinct().collect(Collectors.toList());
    }

    /**
     * 生成闭店申请单号
     */
    private String generateCloseStoreNo(){
        return "C" + CoolDateUtils.getTodayMillis();
    }
}
