package com.tofly.qualitycontrol.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUnit;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tofly.api.DepartmentClient;
import com.tofly.api.UserClent;
import com.tofly.common.core.entity.ResultRespone;
import com.tofly.common.core.util.DateUtil;
import com.tofly.common.oauth.util.SecurityUtils;
import com.tofly.pojo.Department;
import com.tofly.pojo.User;
import com.tofly.pojo.message.Messagepush;
import com.tofly.qualitycontrol.common.QualityControlConstant;
import com.tofly.qualitycontrol.dto.*;
import com.tofly.qualitycontrol.entity.CertificationOrder;
import com.tofly.qualitycontrol.entity.Massaudit;
import com.tofly.qualitycontrol.entity.RectifyOrder;
import com.tofly.qualitycontrol.exception.QualityControlBusinessException;
import com.tofly.qualitycontrol.mapper.CertificationOrderMapper;
import com.tofly.qualitycontrol.qcenum.QualityControlMessageTopicEnum;
import com.tofly.qualitycontrol.qcenum.QualityControlMessageTypeEnum;
import com.tofly.qualitycontrol.service.*;
import com.tofly.qualitycontrol.util.ConfigUtils;
import com.tofly.qualitycontrol.vo.*;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.google.common.collect.Lists.newArrayList;
import static com.tofly.common.oauth.util.SecurityUtils.*;
import static com.tofly.qualitycontrol.util.QualityControlUtil.*;

/**
 * 认证服务实现类
 *
 * @author B
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CertificationOrderServiceImpl extends ServiceImpl<CertificationOrderMapper, CertificationOrder> implements ICertificationOrderService, QualityControlConstant {

    private final IQualityControlMessageRecipientService qualityControlMessageRecipientService;
    private final StringRedisTemplate template;
    private final IQualityControlFileService fileService;
    private final IRectifyOrderService rectifyOrderService;
    private final DepartmentClient departmentClient;
    private final ITimeConfigService timeConfigService;
    private final ConfigUtils configUtils;
    private final ZlrzSynergistService zlrzSynergistService;
    private final MassauditService massauditService;
    private final UserClent userClent;

    private final IRejectedRecordService rejectedRecordService;

    @Value("${xrty.ftp.qualityControl}")
    private String certificationOrderFilePath;
    @Value("${xrtyquality.complete.ratio}")
    private Integer ratio;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveCertificationOrder(CertificationOrderDto dto) {
        ResultRespone<Department> rr = departmentClient.getById(SecurityUtils.getUserDeptId());
        if (rr == null || rr.getResult() == null) {
            return false;
        }
        String code = rr.getResult().getCode();
        String date = DateTimeFormatter.ofPattern("yyyyMMdd").format(LocalDate.now());
        String begcode = StringUtils.isEmpty(code) ? "RZBH-" + date : code + "-" + date;

        List<CertificationOrder> orders = new ArrayList<>();
        if (CollUtil.isEmpty(dto.getClients())) {
            CertificationOrder order = new CertificationOrder();
            BeanUtils.copyProperties(dto, order);
            orders.add(order);
        } else {
            for (ZlrzClientDto client : dto.getClients()) {
                CertificationOrder order = new CertificationOrder();
                BeanUtils.copyProperties(dto, order);
                BeanUtils.copyProperties(client, order);
                orders.add(order);
            }
        }

        for (CertificationOrder certificationOrder : orders) {
            String certificationNumber = loadNumber(begcode);

            certificationOrder.setCertificationNumber(certificationNumber)
                    .setDispatchDept(String.valueOf(SecurityUtils.getUserDeptId()))
                    //.setDispatchPerson(SecurityUtils.getUserName())
                    .setDispatchPersonId(SecurityUtils.getUserId())
                    .setDispatchTime(DateUtil.getCurrentTime());
            save(certificationOrder);
            if (certificationOrder.getSynergists() != null && !certificationOrder.getSynergists().isEmpty()) {
                certificationOrder.getSynergists().forEach(r -> {
                    r.setTableName(ZLRZ_TABLE_NAME);
                    r.setGdId(certificationOrder.getId());
                    r.setSynergistType(SYNERGIST_JC);
                    if (r.getSynergistDeptId() == null) {
                        r.setSynergistDeptId(Long.parseLong(certificationOrder.getCertificationDept()));
                    }
                    zlrzSynergistService.save(r);
                });
            }
        }
        for (CertificationOrder certificationOrder : orders) {
            Messagepush messagePush = getMessagePush(certificationOrder.getId(), INSPECTION_ORDER_MESSAGE, QualityControlMessageTopicEnum.INSPECTION_PROCESS, QualityControlMessageTypeEnum.MESSAGE_TYPE_QUALITY_ORDER);
            messagePush.setRouteIp(configUtils.getJyjlUrl());
            messagePush.setRouteIpApp(configUtils.getJyjlUrlapp());
            log.info("输出检验记录路由地址：" + configUtils.getJyjlUrl());
            qualityControlMessageRecipientService.setMessageRecipient(messagePush, certificationOrder.getCertificationPersonId(), null);
        }
        return true;
    }

    /**
     * 生成工单编号
     *
     * @param begcode
     * @return
     */
    private String loadNumber(String begcode) {
        String key = begcode + "-absent";
        Long value = null;
        while (true) {
            if (template.opsForValue().setIfAbsent(key, UUID.randomUUID().toString(), 500, TimeUnit.MILLISECONDS)) {
                BoundValueOperations<String, String> ops = template.boundValueOps(begcode);
                if (template.hasKey(begcode)) {
                    value = ops.increment(1);
                } else {
                    long minutes = cn.hutool.core.date.DateUtil.between(cn.hutool.core.date.DateUtil.beginOfDay(new Date()), new Date(), DateUnit.MINUTE);
                    List<CertificationOrder> list = list(Wrappers.<CertificationOrder>lambdaQuery()
                            .eq(CertificationOrder::getDispatchDept, String.valueOf(SecurityUtils.getUserDeptId())).likeRight(CertificationOrder::getCertificationNumber, begcode));
                    if (CollectionUtils.isNotEmpty(list)) {
                        int currentMaxNumber = Integer.parseInt(list.stream().map(CertificationOrder::getCertificationNumber).max((o1, o2) -> (int) (Long.parseLong(o1.split("-")[1]) - Long.parseLong(o2.split("-")[1]))).get().replaceAll(begcode, ""));
                        ops.setIfAbsent(String.valueOf(currentMaxNumber), minutes, TimeUnit.MINUTES);
                    } else {
                        ops.setIfAbsent(String.valueOf(0), minutes, TimeUnit.MINUTES);
                    }
                    value = ops.increment(1);
                }
                template.opsForValue().getOperations().delete(key);
            }
            if (value != null) {
                break;
            }
        }
        return begcode + String.format("%05d", value);
    }


    @Override
    public IPage<BusinessMonitorVO_L> getOrderList(ReportOrderDto dto, Page<CertificationOrder> page) {

        List<BusinessMonitorVO_L> voList = newArrayList();
        Map<String, String> map = new HashMap<>();
        Map<Long, String> deptMap = new HashMap<>();

        Page<CertificationOrder> orderPage = null;
        if (dto.getType() == null || dto.getType().equals(0)) {
            orderPage = this.baseMapper.loadOrderList(dto, getUserId(), page, null);
        } else {
            orderPage = this.baseMapper.loadOrderList(dto, null, page, getUserDeptId());
        }
        if (orderPage.getRecords() != null && !orderPage.getRecords().isEmpty()) {
            orderPage.getRecords().forEach(l -> {
                BusinessMonitorVO_L vo = new BusinessMonitorVO_L();
                BeanUtils.copyProperties(l, vo);

                String currentProcess = vo.getCurrentProcess();
                vo.setCurrentProcessName(getProcessName(currentProcess));
                String rectifyDept = vo.getRectifyDept();
                vo.setRectifyDeptName(deptName(deptMap, rectifyDept));
                String dispatchDept = vo.getDispatchDept();
                vo.setDispatchDeptName(deptName(deptMap, dispatchDept));
                vo.setCertificationDeptName(deptName(deptMap, vo.getCertificationDept()));
                String metertype = vo.getMeterType();
                if (StringUtils.isNotEmpty(metertype)) {
                    if (!metertype.toUpperCase().contains("DN")) {
                        metertype = "DN" + metertype;
                    }
                }
                vo.setMeterType(metertype);
                voList.add(vo);

            });
        }
        return getIPage(page, voList, orderPage.getTotal());
    }

    private String getProcessName(String currentProcess) {
        if (StringUtils.isNotEmpty(currentProcess)) {
            switch (currentProcess) {
                case "0":
                    return "检验记录";
                case "1":
                    return "整改下达";
                case "2":
                    return "整改处置";
                case "3":
                    return "整改审核";
                case "4":
                    return "整改验证";
                case "5":
                    return "验证审核";
                default:
                    return "其它";
            }
        }
        return "";
//        String test = StringUtils.isEmpty(currentProcess) || "0".equals(currentProcess) ? "检验记录" : "1".equals(currentProcess) ? "整改下达" : "2".equals(currentProcess) ? "整改处置" : "3".equals(currentProcess) ? "整改审核" : "4".equals(currentProcess) ? "整改验证" : "5".equals(currentProcess) ? "验证审核" : "其它";
//        log.info(test);
//        return test;
    }

    private String deptName(Map<Long, String> deptMap, String deptkey) {
        if (StringUtils.isNotEmpty(deptkey) && !judgeContainsStr(deptkey)) {
            Long key = Long.parseLong(deptkey);
            if (deptMap.containsKey(key)) {
                return deptMap.get(key);
            } else {
                ResultRespone<Department> rr = departmentClient.getById(key);
                if (rr == null || rr.getResult() == null) {
                    deptMap.put(key, "");
                }
                String deptName = rr.getResult().getName();
                deptMap.put(key, deptName);
                return deptName;
            }
        }
        return null;
    }

    public boolean judgeContainsStr(String cardNum) {
        String regex = ".*[a-zA-Z]+.*";
        Matcher m = Pattern.compile(regex).matcher(cardNum);
        return m.matches();
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean certifyOrder(CertificationOrder certificationOrder, List<MultipartFile> fileList) {
        if (certificationOrder.getId() == null) {
            return false;
        }
        Long certificationOrderId = certificationOrder.getId();

        CertificationOrder order = getById(certificationOrderId);
        if (order == null) {
            return false;
        }
        certificationOrder.setCertificationNumber(order.getCertificationNumber());
        if (StringUtils.isEmpty(certificationOrder.getCertificationDept())) {
            certificationOrder.setCertificationDept(order.getCertificationDept());
        }
        if (StringUtils.isEmpty(certificationOrder.getCertificationPerson())) {
            certificationOrder.setCertificationPerson(order.getCertificationPerson());
        }
        if (certificationOrder.getCertificationPersonId() == null) {
            certificationOrder.setCertificationPersonId(order.getCertificationPersonId());
        }

        //存储文件
        String fileIdsdb = order.getFileIds();
        String fileIds = certificationOrder.getFileIds();
        StringBuilder files = saveFiles(fileList, fileIdsdb, fileIds);
        if (files == null && CollUtil.isNotEmpty(fileList)) {
            return false;
        }
        if (StringUtils.isEmpty(files)) {
            this.update(new UpdateWrapper<CertificationOrder>().lambda().set(CertificationOrder::getFileIds, "").eq(CertificationOrder::getId, certificationOrderId));
        }
        certificationOrder.setFileIds(files.toString());

        String currentProcess = INSPECTION_PROCESS;

        //认证不合格生成整改工单
        Boolean flag2 = true;
        if (TO_RECTIFY.equals(certificationOrder.getIsRectified())) {
            //下一环节生成工单
            if (FLOW_NEXT.equals(certificationOrder.getCertificationStatus())) {
                currentProcess = ISSUE_PROCESS;
                String certificationNumber = certificationOrder.getCertificationNumber();
                RectifyOrder ro = rectifyOrderService.getOne(new UpdateWrapper<RectifyOrder>().lambda().eq(RectifyOrder::getCertificationNumber, certificationNumber));

                //整改下达时限
                RectifyOrder rectifyOrder = getRectifyOrder(certificationOrder, certificationOrderId, certificationNumber, ro);
                if (ro != null) {
                    rectifyOrder.setId(ro.getId());
                    flag2 = rectifyOrderService.updateById(rectifyOrder);
                } else {
                    flag2 = rectifyOrderService.save(rectifyOrder);
                }

                if (order.getCompletionTimeLimit().getTime() < System.currentTimeMillis()) {
                    if (order.getCertificationExceptionStatus().equals(FLOW_REJECTED_STATUS)) {
                        certificationOrder.setCertificationExceptionStatus(FLOW_OVERTIME_REJECTED_STATUS);
                    } else {
                        certificationOrder.setCertificationExceptionStatus(FLOW_OVERTIME_STATUS);
                    }
                }

                //第三版代码
                List<Massaudit> lastAuditList = massauditService.list(Wrappers.<Massaudit>lambdaQuery().eq(Massaudit::getNum, 0)
                        .eq(Massaudit::getProcess, FLOW_PROCESS_ONE).eq(Massaudit::getCode, rectifyOrder.getCertificationNumber()));

                if (!lastAuditList.isEmpty()) {
                    Massaudit massaudit = lastAuditList.get(0);
                    massaudit.setAuditState(FLOW_AUDIT_DEFAULT).setCreateTime(null).setMsg(null).setInitiator(SecurityUtils.getUserId());
                    massauditService.save(massaudit);
                }

                Messagepush messagePush = getMessagePush(rectifyOrder.getId(), RECTIFY_RELEASE_MESSAGE, QualityControlMessageTopicEnum.ISSUE_PROCESS, QualityControlMessageTypeEnum.MESSAGE_TYPE_QUALITY_ORDER);
                messagePush.setRouteIp(configUtils.getZgxdUrl());
                messagePush.setRouteIpApp(configUtils.getZgxdUrlapp());
                log.info("整改下达人员{}", certificationOrder.getIssuePersonId());
                qualityControlMessageRecipientService.setMessageRecipient(messagePush, certificationOrder.getIssuePersonId(), null);
                qualityControlMessageRecipientService.removeDB(certificationOrderId, QualityControlMessageTopicEnum.INSPECTION_PROCESS);
            }
        }
        //流程终止
        else {
            Messagepush messagePush = getMessagePush(certificationOrderId, PROCESS_FINISHED_MESSAGE, QualityControlMessageTopicEnum.INSPECTION_PROCESS, QualityControlMessageTypeEnum.MESSAGE_TYPE_QUALITY_ORDER);
            qualityControlMessageRecipientService.setMessageRecipient(messagePush, certificationOrder.getDispatchPersonId());
            qualityControlMessageRecipientService.removeDB(order.getId(), QualityControlMessageTopicEnum.INSPECTION_PROCESS);
        }

        certificationOrder.setCurrentProcess(currentProcess);
        Boolean flag1 = updateById(certificationOrder);

        return flag1 && flag2;
    }


    /**
     * 批量添加检验记录信息
     *
     * @param dto      数据
     * @param fileList 文件
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Object certifyOrderBatch(CertifyOrderDto dto, List<MultipartFile> fileList) {
        CertificationOrder certificationOrder = this.getById(dto.getId());
        //已经检验过只能走修改
        if (certificationOrder.getCurrentProcess() != null) {
            return false;
        }
        Map<String, Long> fileMap = fileService.saveFileMap(fileList, certificationOrderFilePath, RECTIFY_ORDER_TABLE_NAME);
        certificationOrder.setCertificationTime(dto.getCertificationTime());
        if (dto.getInfoDtos() == null || dto.getInfoDtos().isEmpty()) {
            return DATA_LIST_NULL;
        }
        for (CertifyOrderInfoDto infoDto : dto.getInfoDtos()) {
            if (infoDto.getFileName() != null) {
                StringBuilder fileStr = new StringBuilder();
                for (String filename : infoDto.getFileName()) {
                    if (fileMap.containsKey(filename)) {
                        fileStr.append(fileMap.get(filename)).append(CSV);
                    } else {
                        return FILE_NAME_NOT_EXSIT + filename;
                    }
                }
                infoDto.setFileIds(fileStr.toString());
            }
        }
        for (int i = 0; i < dto.getInfoDtos().size(); i++) {
            CertifyOrderInfoDto infodto = dto.getInfoDtos().get(i);
            CertificationOrder order = new CertificationOrder();
            if (i == 0) {
                order = certificationOrder;
            } else {
                BeanUtils.copyProperties(certificationOrder, order);
                order.setCertificationNumber(order.getCertificationNumber() + "-" + i);
                order.setId(null);
                order.setParentId(certificationOrder.getId());
            }
            BeanUtils.copyProperties(infodto, order);
            String currentProcess = INSPECTION_PROCESS;
            if (i != 0) {
                if (!this.save(order)) {
                    throw new RuntimeException(ORDER_SAVE_ERR);
                }
            }
            Long certificationOrderId = order.getId();
            if (TO_RECTIFY.equals(order.getIsRectified())) {
                //下一环节生成工单
                if (FLOW_NEXT.equals(order.getCertificationStatus())) {
                    currentProcess = ISSUE_PROCESS;
                    String certificationNumber = order.getCertificationNumber();
                    RectifyOrder ro = rectifyOrderService.getOne(new UpdateWrapper<RectifyOrder>().lambda().eq(RectifyOrder::getCertificationNumber, certificationNumber));
                    RectifyOrder rectifyOrder = getRectifyOrder(order, certificationOrderId, certificationNumber, ro);

                    if (ro != null) {
                        rectifyOrder.setId(ro.getId());
                        if (!rectifyOrderService.updateById(rectifyOrder)) {
                            log.warn(RECTIFYORDER_UPDATE_ERR);
                            throw new RuntimeException(RECTIFYORDER_UPDATE_ERR);
                        }
                    } else {
                        if (!rectifyOrderService.save(rectifyOrder)) {
                            log.warn(RECTIFYORDER_SAVE_ERR);
                            throw new RuntimeException(RECTIFYORDER_SAVE_ERR);
                        }
                    }

                    //第二版废弃代码
//                    Long deptIdByUser = rectifyOrderMapper.getDeptIdByUser(order.getIssuePersonId());
                    //为整改下达生成一条默认的审核记录 num审核登记，默认1级别
//                    Massaudit massaudit = new Massaudit();
//                    massaudit.setInitiator(SecurityUtils.getUserId())
//                            .setAuditUser(order.getIssuePersonId())
//                            .setAuditState(FLOW_AUDIT_DEFAULT)
//                            .setProcess(FLOW_PROCESS_ONE)
//                            .setAuditDept(deptIdByUser)
//                            .setNum(1L)
//                            .setCode(certificationOrder.getCertificationNumber());
//
//                    massauditService.save(massaudit);

                    Messagepush messagePush = getMessagePush(rectifyOrder.getId(), RECTIFY_RELEASE_MESSAGE, QualityControlMessageTopicEnum.ISSUE_PROCESS, QualityControlMessageTypeEnum.MESSAGE_TYPE_QUALITY_ORDER);
                    messagePush.setRouteIp(configUtils.getZgxdUrl());
                    messagePush.setRouteIpApp(configUtils.getZgxdUrlapp());
                    qualityControlMessageRecipientService.setMessageRecipient(messagePush, order.getIssuePersonId(), null);
                    qualityControlMessageRecipientService.removeDB(order.getId(), QualityControlMessageTopicEnum.INSPECTION_PROCESS);
                }
            }
            //流程终止
            else {
                Messagepush messagePush = getMessagePush(certificationOrderId, PROCESS_FINISHED_MESSAGE, QualityControlMessageTopicEnum.INSPECTION_PROCESS, QualityControlMessageTypeEnum.MESSAGE_TYPE_QUALITY_ORDER);
                qualityControlMessageRecipientService.setMessageRecipient(messagePush, order.getDispatchPersonId());
                qualityControlMessageRecipientService.removeDB(order.getId(), QualityControlMessageTopicEnum.INSPECTION_PROCESS);
            }
            order.setCurrentProcess(currentProcess);
            if (!updateById(order)) {
                log.warn(ORDER_UPDATEBYID_ERROR);
                throw new RuntimeException(ORDER_UPDATEBYID_ERROR);
            }
            if (!TO_RECTIFY.equals(order.getIsRectified()) && IS_CB.equals(order.getIsCb())) {
                updateReadmeterhis(order.getClientNumber(), order.getYearMonth());
            }
        }
        return true;
    }

    @Override
    public Integer updateReadmeterhis(String clientNumber, String yearMonth) {
        return this.baseMapper.updateReadmeterhis(clientNumber, yearMonth);
    }

    /**
     * 工单统计接口
     *
     * @param dto 查询条件
     * @return
     */
    @Override
    public List<OrderSummaryVo> orderSummaryList(OrderDto dto) {
        List<OrderSummaryVo> listVos = null;
        if (dto.getType() == null || dto.getType().equals(0)) {
            listVos = this.baseMapper.orderSummaryList(dto, getUserId(), null);
        } else if (dto.getType().equals(1)) {
            listVos = this.baseMapper.orderSummaryList(dto, null, getUser().getDepartmentId());
        }
        return listVos;
    }

    /**
     * 上报工单统计
     *
     * @param dto 查询条件
     * @return
     */
    @Override
    public List<ReportSummaryVo> orderReportSummary(OrderDto dto) {
        List<ReportSummaryVo> vos = null;
        if (dto.getType() == null || dto.getType().equals(0)) {
            vos = this.baseMapper.orderReportSummary(dto, getUserId(), null);
        } else if (dto.getType().equals(1)) {
            vos = this.baseMapper.orderReportSummary(dto, null, getUserDeptId());
        }
        return vos;
    }

    /**
     * 工单检验统计
     *
     * @param dto
     * @return
     */
    @Override
    public List<ReportSummaryVo> orderInspectSummary(OrderDto dto) {
        List<ReportSummaryVo> vos = null;
        if (dto.getType() == null || dto.getType().equals(0)) {
            vos = this.baseMapper.orderInspectSummary(dto, getUserId(), ratio, null);
        } else if (dto.getType().equals(1)) {
            vos = this.baseMapper.orderInspectSummary(dto, null, ratio, getUser().getDepartmentId());
        }
        return vos;
    }

    /**
     * 工单详细信息
     *
     * @param id   工单id
     * @param type 工单类型，
     * @return
     */
    @Override
    public List<ReportOrderInfoVo> getOrder(Long id, Long type) {
        List<ReportOrderInfoVo> infoVos = this.baseMapper.loadOrderInfos(id, type);
        Map<Long, String> deptMap = new HashMap<>();
        if (CollUtil.isNotEmpty(infoVos)) {
            for (ReportOrderInfoVo vo : infoVos) {

                vo.setDispatchDeptName(deptName(deptMap, vo.getDispatchDept()));
                vo.setCertificationDeptName(deptName(deptMap, vo.getCertificationDept()));
                vo.setIssueDeptName(deptName(deptMap, vo.getIssueDept()));
                vo.setRectifyDeptName(deptName(deptMap, vo.getRectifyDept()));
                RectifyOrderInfoVo ovo = vo.getRectifyOrderInfoVo();
                if (ovo != null) {
                    ovo.setAuditDeptName(deptName(deptMap, ovo.getAuditDept()));
                    ovo.setValidateDeptName(deptName(deptMap, ovo.getValidateDept()));
                    ovo.setVerifyDeptName(deptName(deptMap, ovo.getVerifyDept()));
                }
                vo.setBhs(rejectedRecordService.getList(vo.getCertificationNumber()));
                List<Massaudit> auditList = massauditService.list(Wrappers.<Massaudit>lambdaQuery()
                        .eq(Massaudit::getCode, vo.getCertificationNumber())
                        .ne(Massaudit::getNum, 0)
                        .orderByAsc(Massaudit::getNum)
                        .orderByAsc(Massaudit::getCreateTime));

           /*     if (auditList != null && !auditList.isEmpty()) {
                    auditList.forEach(a -> {
                        if (StringUtils.isNotEmpty(a.getFileIds())) {
                            a.setFilePaths(baseMapper.getFilePath(Arrays.asList(a.getFileIds().split(","))));
                        }
                    });
                }*/
                //审核相关信息
                vo.setAuditInfo(auditList);
            }
        }
        return infoVos;
    }

    @Override
    public List<OrderListInfoVo> getWorkOrderList(OrderListDto dto) {
        if (dto.getReportType() != null && dto.getReportType() == 4) {
            dto.setLink(2);
        }
        List<OrderListInfoVo> infoVos = this.baseMapper.loadWorkOrderList(dto);
        if (infoVos != null && !infoVos.isEmpty()) {
            for (OrderListInfoVo infoVo : infoVos) {
                String currentProcess = infoVo.getCurrentProcess();
                if ("1".equals(currentProcess) || "5".equals(currentProcess)) {
                    List<Massaudit> list = massauditService.list(Wrappers.<Massaudit>lambdaQuery()
                            .eq("1".equals(currentProcess), Massaudit::getProcess, 0)
                            .eq("5".equals(currentProcess), Massaudit::getProcess, 1)
                            .eq(Massaudit::getCode, infoVo.getCertificationNumber())
                            .orderByAsc(Massaudit::getNum));
                    if (!list.isEmpty()) {
                        User user = userClent.getById(list.get(0).getAuditUser()).getResult();
                        infoVo.setNextPerson(user.getRealName());
                        infoVo.setNextDept(user.getDepartmentId().toString());
                    }
                }
                infoVo.setNextDeptName(departmentClient.getById(Long.parseLong(infoVo.getNextDept())).getResult().getName());
            }
        }
        fillDept(infoVos);
        return infoVos;
    }

    @Override
    public Page<OrderListInfoVo> getWorkOrderList(OrderListDto dto, Page page) {
        if (dto.getReportType() != null && dto.getReportType() == 4) {
            dto.setLink(2);
        }
        Page<OrderListInfoVo> infoVos = baseMapper.loadWorkOrderList(dto, page);

        if (infoVos != null) {
            List<OrderListInfoVo> records = infoVos.getRecords();
            if (records != null && !records.isEmpty()) {
                for (OrderListInfoVo infoVo : records) {
                    String currentProcess = infoVo.getCurrentProcess();
                    if ("1".equals(currentProcess) || "5".equals(currentProcess)) {
                        List<Massaudit> list = massauditService.list(Wrappers.<Massaudit>lambdaQuery()
                                .eq("1".equals(currentProcess), Massaudit::getProcess, 0)
                                .eq("5".equals(currentProcess), Massaudit::getProcess, 1)
                                .eq(Massaudit::getAuditState, 0)
                                .eq(Massaudit::getCode, infoVo.getCertificationNumber())
                                .orderByAsc(Massaudit::getNum));
                        if (list != null && !list.isEmpty()) {
                            User user = userClent.getById(list.get(0).getAuditUser()).getResult();
                            if (user != null) {
                                infoVo.setNextPerson(user.getRealName());
                                infoVo.setNextDept(user.getDepartmentId().toString());
                            }
                        }
                    }
                    infoVo.setNextDeptName(org.springframework.util.StringUtils.isEmpty(infoVo.getNextDept()) ? null : departmentClient.getById(Long.parseLong(infoVo.getNextDept())).getResult().getName());
                }
            }
            fillDept(records);
        }

        return infoVos;
    }

    private void fillDept(List<OrderListInfoVo> list) {
        if (CollUtil.isNotEmpty(list)) {
            Map<Long, String> deptMap = new HashMap<>();
            for (OrderListInfoVo vo : list) {
                vo.setCurrentProcessName(getProcessName(vo.getCurrentProcess()));
                vo.setDispatchDeptName(deptName(deptMap, vo.getDispatchDept()));
                vo.setCertificationDeptName(deptName(deptMap, vo.getCertificationDept()));
                //vo.setNextDeptName(deptName(deptMap, vo.getNextDept()));
                vo.setRectifyDeptName(deptName(deptMap, vo.getRectifyDept()));
                if (vo.getGdTime() != null) {
                    vo.setNextDept(null);
                    vo.setNextPerson(null);
                    vo.setNextDeptName(null);
                    vo.setCurrentProcessName("已归档");
                }
            }
        }
    }

    @Override
    public List<OrderFinishVo> getOrderFinish(OrderReportDto dto) {
        List<OrderFinishVo> list = this.baseMapper.loadOrderFinish(dto);
        Map<Long, String> deptMap = new HashMap<>();
        for (OrderFinishVo vo : list) {
            vo.setDeptName(deptName(deptMap, vo.getDept()));
        }
        return list;
    }

    @Override
    public List<OrderFinishInfoVo> getDefectType(OrderReportDto dto) {
        return this.baseMapper.loadDefectType(dto);
    }

    @Override
    public List<Map<String, Object>> getDefectTrend(OrderReportDto dto) {
        dto.setStartDate(cn.hutool.core.date.DateUtil.beginOfMonth(dto.getStartDate()));
        dto.setEndDate(cn.hutool.core.date.DateUtil.endOfMonth(dto.getEndDate()));
        StringBuilder sb = new StringBuilder();
        Date bg = dto.getStartDate();
        while (bg.getTime() <= dto.getEndDate().getTime()) {
            String format = cn.hutool.core.date.DateUtil.format(bg, TIME_FORMAT);
            sb.append("'").append(format).append("' as A").append(format.replace("-", "A")).append(",");
            bg = cn.hutool.core.date.DateUtil.offsetMonth(bg, 1);
        }
        sb.deleteCharAt(sb.length() - 1);
        List<Map<String, Object>> list = this.baseMapper.loadDefectTrend(dto, sb.toString());
        List<Map<String, Object>> rlist = getRlist(list);
        return rlist;
    }

    private List<Map<String, Object>> getRlist(List<Map<String, Object>> list) {
        Map<Long, String> deptMap = new HashMap<>();
        List<Map<String, Object>> rlist = new ArrayList<>();
        for (Map<String, Object> map : list) {
            if (map == null || map.isEmpty()) {
                continue;
            }
            Map<String, Object> longMap = map.entrySet().stream().map(r -> {
                String key = r.getKey();
                if (key.contains("a") && key.matches("^[a][0-9]*.*$")) {
                    key = key.substring(1).replace("a", "_");
                }
                T t = new T(key, r.getValue() == null ? 0 : r.getValue());
                log.info(t.toString());
                return t;
            }).collect(Collectors.toMap(T::getKey, T::getValue));
            if (longMap.containsKey("dept")) {
                longMap.put("detpName", deptName(deptMap, String.valueOf(map.get("dept"))));
            }
            rlist.add(longMap);
        }
        return rlist;
    }

    @Override
    public List<ClientAttestationVo> getClientAttestation(ClientAttestationDto dto) {
        return this.baseMapper.loadClientAttestation(dto);
    }


    @Override
    public Object getManageBenefit(OrderReportDto dto) {
        dto.setStartDate(cn.hutool.core.date.DateUtil.beginOfMonth(dto.getStartDate()));
        dto.setEndDate(cn.hutool.core.date.DateUtil.endOfMonth(dto.getEndDate()));
        //合格 true
        List list = null;
        if (dto.getIsQualified() != null && dto.getIsQualified()) {
            list = this.baseMapper.loadQualified(dto);
        } else {
            //不合格 false
            StringBuilder sb = new StringBuilder();
            Date bg = dto.getStartDate();
            while (bg.getTime() <= dto.getEndDate().getTime()) {
                String format = cn.hutool.core.date.DateUtil.format(bg, TIME_FORMAT);
                sb.append("'").append(format).append("' as A").append(format.replace("-", "A")).append(",");
                bg = cn.hutool.core.date.DateUtil.offsetMonth(bg, 1);
            }
            sb.deleteCharAt(sb.length() - 1);
            List<Map<String, Object>> lsits = this.baseMapper.loadNotQualified(dto, sb.toString());
            list = getRlist(lsits);
        }
        return list;
    }


    @Data
    @ToString
    class T {
        public T(String key, Object value) {
            this.key = key;
            this.value = value;
        }

        private String key;
        private Object value;
    }

    /**
     * 填充整改工单实体类
     *
     * @param order                上报工单
     * @param certificationOrderId 上报工单id
     * @param certificationNumber  上报工单编号
     * @param ro                   整改工单历史信息
     * @return
     */
    private RectifyOrder getRectifyOrder(CertificationOrder order, Long certificationOrderId, String certificationNumber, RectifyOrder ro) {
        //整改下达时限
        Calendar calendar1 = Calendar.getInstance();
        calendar1.add(Calendar.HOUR, timeConfigService.getById(1L).getTimeLimit());
        Date issueTimeLimit = calendar1.getTime();

        //整改验证时限
        Calendar calendar2 = Calendar.getInstance();
        calendar2.add(Calendar.HOUR, timeConfigService.getById(2L).getTimeLimit());
        Date verifyTimeLimit = calendar2.getTime();


        String rectifyNumber = null;
        if (ro == null) {
            rectifyNumber = "ZGBH-" + certificationNumber.split("-")[1];
        } else {
            rectifyNumber = ro.getRectifyNumber();
        }
        return RectifyOrder.builder()
                .rectifyNumber(rectifyNumber)
                .certificationNumber(certificationNumber)
                .clientNumber(order.getClientNumber())
                .clientName(order.getClientName())
                .clientPhone(order.getClientPhone())
                .clientAddress(order.getClientAddress())
                .meterType(order.getMeterType())
                .waterCategory(order.getWaterCategory())
                .certificationPerson(order.getCertificationPerson())
                .certificationPersonId(order.getCertificationPersonId())
                .certificationDept(order.getCertificationDept())
                .rectifyDesc(order.getRectifyDesc())
                .resultTimeLimit(order.getRectifyTimeLimit())
                .rectifyDept(order.getRectifyDept())
                .rectifyPerson(order.getRectifyPerson())
                .rectifyPersonId(order.getRectifyPersonId())
                .dispatchPersonId(order.getDispatchPersonId())
                .issueStatus(FLOW_CURRENT_PROCESS)
                .issueDept(order.getIssueDept())
                .issuePerson(order.getIssuePerson())
                .issuePersonId(order.getIssuePersonId())
                .issueTimeLimit(issueTimeLimit)
                .verifyTimeLimit(verifyTimeLimit)
                .exceptionCause(order.getExceptionCause())
                .problemLevel(order.getProblemLevel())
                .parentId(order.getParentId())
                .certificationOrderId(certificationOrderId).build();
    }


    /**
     * 存储文件
     *
     * @param fileList
     * @param fileIdsdb
     * @param fileIds
     * @return
     */
    private StringBuilder saveFiles(List<MultipartFile> fileList, String fileIdsdb, String fileIds) {
        StringBuilder fileIdList = null;
        if (CollectionUtils.isNotEmpty(fileList)) {
            fileIdList = fileService.saveFileList(fileList, certificationOrderFilePath, RECTIFY_ORDER_TABLE_NAME);
            if (fileIdList == null || fileIdList.length() == 0) {
                return null;
            }
        }
        fileIds = delRepeat(fileIds);
        String fs = fileIds;
        if (StringUtils.isNotEmpty(fileIdsdb) && !fileIdsdb.equals(fileIds)) {
            List<Long> removeFileId = new ArrayList<>();
            if (StringUtils.isEmpty(fileIds)) {
                removeFileId = Arrays.stream(fileIdsdb.split(CSV)).filter(s -> StringUtils.isNotEmpty(s)).map(s -> Long.parseLong(s.trim()))
                        .collect(Collectors.toList());
            } else {
                removeFileId = Arrays.stream(fileIdsdb.split(CSV)).filter(st -> !fs.contains(st) && StringUtils.isNotEmpty(st)).map(st -> Long.parseLong(st.trim())).collect(Collectors.toList());
            }
            // 删除对应文件数据
            if (!removeFileId.isEmpty()) {
                // 删除远程文件
                fileService.removeFileList(removeFileId);
            }
        }
        StringBuilder files = new StringBuilder();

        if (StringUtils.isEmpty(fileIds) || StringUtils.isEmpty(fileIdList)) {
            if (StringUtils.isNotEmpty(fileIds)) {
                files.append(fileIds);
            } else if (StringUtils.isNotEmpty(fileIdList)) {
                files.append(fileIdList);
            }
        } else {
            files.append(fileIds).append(CSV).append(fileIdList);
        }
        return files;
    }

    private String delRepeat(String str) {
        StringBuilder sb = new StringBuilder();
        if (StringUtils.isNotEmpty(str)) {
            List<Long> removeFileId = Arrays.stream(str.split(CSV)).filter(s -> StringUtils.isNotEmpty(s)).map(s -> Long.parseLong(s.trim())).collect(Collectors.toList());
            for (Long l : removeFileId) {
                sb.append(l).append(",");
            }
            sb.delete(sb.length() - 1, sb.length());
            return sb.toString();
        }
        return null;
    }

    @Override
    public IPage<BusinessMonitorVO_L> getCertificationList(ReportOrderDto orderDto, Page<CertificationOrder> page) {
        Long userId = getUserId();
        List<BusinessMonitorVO_L> voList = newArrayList();
        Map<String, String> map = new HashMap<>();
        //Page<CertificationOrder> orderPage = page(page,queryWrapper);
        Page<BusinessMonitorVO_L> orderPage = null;
        if (orderDto.getType() == null || orderDto.getType().equals(0)) {
            orderPage = this.baseMapper.getCertificationList(orderDto, userId, ratio, page, null);
        } else if (orderDto.getType().equals(1)) {
            orderPage = this.baseMapper.getCertificationList(orderDto, null, ratio, page, getUserDeptId());
        }
        Map<Long, String> deptMap = new HashMap<>();
        if (orderPage.getRecords() != null && !orderPage.getRecords().isEmpty()) {
            for (BusinessMonitorVO_L vo : orderPage.getRecords()) {
                String currentProcess = vo.getCurrentProcess();
                vo.setCurrentProcessName(getProcessName(currentProcess));
                String rectifyDept = vo.getRectifyDept();
                vo.setRectifyDeptName(deptName(deptMap, rectifyDept));
                String dispatchDept = vo.getDispatchDept();
                vo.setDispatchDeptName(deptName(deptMap, dispatchDept));
                vo.setCertificationDeptName(deptName(deptMap, vo.getCertificationDept()));
                String metertype = vo.getMeterType();
                if (StringUtils.isNotEmpty(metertype)) {
                    if (!metertype.toUpperCase().contains("DN")) {
                        metertype = "DN" + metertype;
                    }
                }
                vo.setMeterType(metertype);
                voList.add(vo);
            }
        }
        return getIPage(page, voList, orderPage.getTotal());
    }

    @Override
    public CertificationOrderVO_D getDetail(Long id) {

        CertificationOrderVO_D vo = getVO(getById(id), CertificationOrderVO_D.class);
        String certificationDept = vo.getCertificationDept();
        Boolean flag1 = isNotNull(certificationDept);
        if (flag1) {
            vo.setCertificationDept(departmentClient.getById(Long.valueOf(certificationDept)).getResult().getName());
        }
        List<Massaudit> auditList = massauditService.list(Wrappers.<Massaudit>lambdaQuery()
                .eq(Massaudit::getCode, vo.getCertificationNumber())
                .ne(Massaudit::getNum, 0)
                .orderByAsc(Massaudit::getNum)
                .orderByAsc(Massaudit::getCreateTime));

        vo.setAuditList(auditList);
        return vo;
    }

    @Override
    public List<Map<String, String>> getFilePath(List<Long> fileIds) {
        return fileService.getFileInfo(fileIds);
    }

    @Override
    public Boolean deleteOrder(Long id) {
        String certificationNumber = getById(id).getCertificationNumber();

        List<RectifyOrder> list = rectifyOrderService.list(Wrappers.<RectifyOrder>lambdaQuery()
                .eq(RectifyOrder::getCertificationNumber, certificationNumber));

        if (CollectionUtils.isNotEmpty(list)) {
            throw new QualityControlBusinessException("不能删除已有整改工单的认证工单");
        }
        return removeById(id);
    }

    @Override
    public Map<String, Object> getProcessCount() {
        return baseMapper.getProcessCount(SecurityUtils.getUserId());
    }
}
