package com.sunxung.factoring.service.loanmanagement.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sunxung.factoring.component.exception.BusinessException;
import com.sunxung.factoring.component.exception.ValidatorException;
import com.sunxung.factoring.component.util.*;
import com.sunxung.factoring.dict.impl.FileModuleDict;
import com.sunxung.factoring.dict.impl.ProjectInitiationStatusDict;
import com.sunxung.factoring.entity.financing.payment.PaymentApply;
import com.sunxung.factoring.entity.financing.payment.PaymentCondition;
import com.sunxung.factoring.entity.financing.payment.PaymentConditionFileRef;
import com.sunxung.factoring.entity.financing.payment.PaymentInfo;
import com.sunxung.factoring.entity.financing.review.ReviewFinancingInfo;
import com.sunxung.factoring.entity.financing.review.ReviewMasterContract;
import com.sunxung.factoring.entity.financing.review.ReviewMasterContractDebtor;
import com.sunxung.factoring.entity.financing.review.ReviewQuotaDisburse;
import com.sunxung.factoring.entity.loanmanagement.*;
import com.sunxung.factoring.entity.project.BusinessAssignee;
import com.sunxung.factoring.entity.project.BusinessProcessingLog;
import com.sunxung.factoring.entity.project.ProjectInformation;
import com.sunxung.factoring.entity.project.vo.BusinessProcessingTaskVo;
import com.sunxung.factoring.entity.project.vo.ProjectInformationVo;
import com.sunxung.factoring.entity.project.vo.SearchBusinessProcessingTask;
import com.sunxung.factoring.entity.supplier.SupplierInfo;
import com.sunxung.factoring.entity.sys.Dictionary;
import com.sunxung.factoring.entity.sys.FileStorage;
import com.sunxung.factoring.entity.sys.User;
import com.sunxung.factoring.entity.sys.UserDO;
import com.sunxung.factoring.mapper.loanmanagement.ExemptionMattersMapper;
import com.sunxung.factoring.service.entprise.IEnterpriseService;
import com.sunxung.factoring.service.financing.apply.ICFinancingBasicInfoService;
import com.sunxung.factoring.service.financing.payment.IPaymentApplyService;
import com.sunxung.factoring.service.financing.payment.IPaymentConditionFileRefService;
import com.sunxung.factoring.service.financing.payment.IPaymentConditionService;
import com.sunxung.factoring.service.financing.payment.IPaymentInfoService;
import com.sunxung.factoring.service.financing.review.ReviewFinancingInfoService;
import com.sunxung.factoring.service.financing.review.ReviewMasterContractDebtorService;
import com.sunxung.factoring.service.financing.review.ReviewMasterContractService;
import com.sunxung.factoring.service.financing.review.ReviewQuotaDisburseService;
import com.sunxung.factoring.service.loanmanagement.*;
import com.sunxung.factoring.service.project.BusinessAssigneeService;
import com.sunxung.factoring.service.project.BusinessProcessingLogService;
import com.sunxung.factoring.service.project.IProjectInformationService;
import com.sunxung.factoring.service.supplier.ISupplierInfoService;
import com.sunxung.factoring.service.sys.CUserService;
import com.sunxung.factoring.service.sys.DictionaryService;
import com.sunxung.factoring.service.sys.FileStorageService;
import com.sunxung.factoring.service.sys.UserService;
import com.sunxung.factoring.service.sys.flowable.FlowableService;
import com.sunxung.factoring.service.sys.systemMsg.SystemMsgService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * <p>
 * 豁免事项跟进和付款关系表 服务实现类
 * </p>
 *
 * @author liutao
 * @since 2023-04-25
 */
@Service("exemptionMattersService")
public class ExemptionMattersServiceImpl extends ServiceImpl<ExemptionMattersMapper, ExemptionMatters> implements
        IExemptionMattersService {

    @Autowired
    private IPaymentApplyService paymentApplyService;

    @Autowired
    private FileStorageService fileStorageService;

    @Autowired
    private IExemptionMattersRefService exemptionMattersRefService;

    @Autowired
    private IExemptionMattersHistoryService exemptionMattersHistoryService;

    @Autowired
    private IExemptionMattersRefHistoryService exemptionMattersRefHistoryService;

    @Autowired
    private BusinessAssigneeService assigneeService;

    @Autowired
    private FlowableService flowableService;

    @Autowired
    private UserService userService;

    @Autowired
    private IPaymentInfoService paymentInfoService;

    @Autowired
    private IExemptionMattersApprovalService exemptionMattersApprovalService;

    @Autowired
    private ReviewQuotaDisburseService reviewQuotaDisburseService;

    @Autowired
    private ReviewFinancingInfoService reviewFinancingInfoService;

    @Autowired
    private ReviewMasterContractService reviewMasterContractService;

    @Autowired
    private ICFinancingBasicInfoService financingBasicInfoService;

    @Autowired
    private ReviewMasterContractDebtorService reviewMasterContractDebtorService;

    @Resource(name = "supplierInfoService")
    private ISupplierInfoService supplierInfoService;

    @Resource(name = "projectInformationService")
    private IProjectInformationService projectInformationService;

    @Autowired
    private IEnterpriseService enterpriseService;

    @Autowired
    private CUserService cUserService;

    @Autowired
    private UserService bUserService;

    @Autowired
    private DictionaryService dictionaryService;

    @Autowired
    private IPaymentConditionService paymentConditionService;

    @Autowired
    private IPaymentConditionFileRefService paymentConditionFileRefService;

    //    @Autowired
//    private PaymentApplyMapper applyMapper;
//    @Autowired
//    private MailService mailService;
    //    @Autowired
//    private EntCustomerMarketingInfoService marketingInfoService;
//    @Autowired
//    private SystemEmailService systemEmailService;
    @Autowired
    private SystemMsgService systemMsgService;
    @Autowired
    private BusinessProcessingLogService businessProcessingLogService;

    @Override
    public void startProcess(Long paymentApplyId) {

        if (paymentApplyId == null) {
            throw new ValidatorException(CodeUtil.FAIL, "付款申请id不能为空！");
        }

        PaymentApply paymentApply = paymentApplyService.getById(paymentApplyId);
        if (paymentApply == null) {
            throw new BusinessException(CodeUtil.FAIL, "未查询到付款信息！");
        }
        PaymentInfo paymentInfo = paymentInfoService.getById(paymentApply.getPaymentInfoId());

        List<PaymentCondition> conditions = paymentApplyService.findConditions(paymentApplyId);
        boolean anyMatch = conditions.stream().anyMatch(r -> r.getFollow() != null && r.getFollow().equals("1"));
        if (anyMatch) {
            //获取项目经理
            ProjectInformationVo projectInformationVo = projectInformationService.getByBusinessNo(paymentInfo.getBusinessNo());
            ProjectInformation projectInformation = projectInformationService.get(projectInformationVo.getProjectInformationId());
            SupplierInfo supplierInfo = supplierInfoService.get(projectInformation.getcSupplierInfoId());
            UserDO cUser = cUserService.getById(supplierInfo.getSysUserId());
            User user = bUserService.get(cUser.getProjectManager());

            //获取合同编号
            ReviewQuotaDisburse reviewQuotaDisburse = reviewQuotaDisburseService.getById(paymentInfo.getQuotaDisburseId());
            ReviewMasterContract reviewMasterContract = reviewMasterContractService.lambdaQuery().eq(ReviewMasterContract::getReviewQuotaDisburseId, reviewQuotaDisburse.getId()).one();
            List<ReviewMasterContractDebtor> reviewMasterContractDebtors = reviewMasterContractDebtorService
                    .lambdaQuery().eq(ReviewMasterContractDebtor::getReviewMasterContractId, reviewMasterContract.getId()).list();

            //开启豁免事项跟进流程
            // 付款申请人、处理人为项目经理
            Map<String, Object> procVariables = new HashMap<>(1);
            procVariables.put(ConstantUtil.EXEMPTION_MATTER_ADD + ConstantUtil.ASSIGNEE, user.getId());
            Map<String, Object> msgVariables = new HashMap<>(2);
            msgVariables.put(ConstantUtil.FLOWABLE_MSG_TITLE, reviewQuotaDisburse.getBusinessNumber());
            msgVariables.put(ConstantUtil.FLOWABLE_MSG_CONTENT,
                    "业务编号为“" + projectInformation.getBusinessNumber() +
                            "”——合同编号为“" + reviewMasterContract.getContractNo() +
                            "”——付款编号为“" + paymentApply.getPaymentNo() + "”的项目已进入“"
                            + "豁免事项跟进—formBusiness”阶段，"
                            + ConstantUtil.FLOWABLE_MSG_ASSIGNEE);

            String debtorListStr = reviewMasterContractDebtors.stream().map(r -> r.getCompanyName()).collect(Collectors.joining(FlowableUtil.splitChar));
            ExemptionMatters exemptionMatters = new ExemptionMatters();

            exemptionMatters.setExemptionStatus(ProjectInitiationStatusDict.ChildEnum.PROCESSING.getCode());
            exemptionMatters.setPaymentApplyId(paymentApplyId);
            save(exemptionMatters);
            // 查询条件：供应商/核心企业/债务人/合同编号
            String queryBusiness = projectInformationVo.getMainEnterprise() + FlowableUtil.splitChar +
                    projectInformationVo.getEnterprise() + FlowableUtil.splitChar +
                    debtorListStr + FlowableUtil.splitChar +
                    reviewMasterContract.getContractNo();
            //开启流程
            flowableService.startProcessInstance(exemptionMatters, procVariables,
                    FlowableUtil.generateBusinessKey(exemptionMatters, ConstantUtil.EXEMPTION_MATTERS, queryBusiness), msgVariables
                    , ConstantUtil.EXEMPTION_MATTERS);
        }

    }

    @Override
    public ExemptionMatters get(Long id) {
        ExemptionMatters exemptionMatters = baseMapper.getExemptionMattersById(id);
        if (exemptionMatters != null) {
            Dictionary status = dictionaryService.getByCode(exemptionMatters.getExemptionStatus());
            exemptionMatters.setExemptionStatus(status.getName());
            exemptionMatters.setStatusDictionary(status);
            PaymentApply paymentApply = paymentApplyService.getById(exemptionMatters.getPaymentApplyId());
            PaymentInfo paymentInfo = paymentInfoService.getById(paymentApply.getPaymentInfoId());
            ReviewFinancingInfo reviewFinancingInfo = reviewFinancingInfoService
                    .lambdaQuery().eq(ReviewFinancingInfo::getReviewQuotaDisburseId, paymentInfo.getQuotaDisburseId()).one();
            exemptionMatters.setFinancingAmount(reviewFinancingInfo.getFinancingAmount());
            exemptionMatters.setCurrencyCode(reviewFinancingInfo.getCurrencyCode());
        }
        return exemptionMatters;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(PaymentApply paymentApply) {
        String taskId = paymentApply.getTaskId();
        Long businessKey = paymentApply.getId();
        ExemptionMatters exemptionMatters = get(businessKey);
        //保存关联关系历史表历史信息
        ExemptionMattersHistory exemptionMattersHistory = new ExemptionMattersHistory();
        exemptionMattersHistory.setPaymentApplyId(exemptionMatters.getPaymentApplyId());
        exemptionMattersHistoryService.save(exemptionMattersHistory);
        List<PaymentCondition> conditions = paymentApply.getConditionList();
        conditions.stream().filter(r -> StringUtil.isNotEmpty(r.getSupplement())).forEach(r -> {
            //更新 补充说明
            paymentConditionService.lambdaUpdate().eq(PaymentCondition::getId, r.getId()).set(PaymentCondition::getSupplement, r.getSupplement()).update();
            exemptionMattersRefService.lambdaUpdate().eq(ExemptionMattersRef::getPaymentConditionId, r.getId()).remove();
            List<Long> fileIds = r.getFileIds();
            if (CollectionUtil.isNotEmpty(fileIds)) {
                for (Long fileId : fileIds) {
                    ExemptionMattersRef exemptionMattersRef = new ExemptionMattersRef();
                    exemptionMattersRef.setExemptionMattersId(businessKey);
                    exemptionMattersRef.setPaymentConditionId(r.getId());
                    exemptionMattersRef.setFileId(fileId);
                    exemptionMattersRefService.save(exemptionMattersRef);
                    //保存文件历史表
                    ExemptionMattersRefHistory exemptionMattersRefHistory = new ExemptionMattersRefHistory();
                    exemptionMattersRefHistory.setFileId(exemptionMattersRef.getFileId());
                    exemptionMattersRefHistory.setPaymentConditionId(exemptionMattersRef.getPaymentConditionId());
                    exemptionMattersRefHistory.setExemptionMattersId(exemptionMattersHistory.getId());
                    exemptionMattersRefHistoryService.save(exemptionMattersRefHistory);
                }
            }
        });
        List<Long> legalSpecials = userService.findUserIdByRole(ConstantUtil.LEGAL_SPECIALIST);
        if (legalSpecials == null || legalSpecials.size() == 0) {
            throw new ValidatorException(CodeUtil.FAIL, ConstantUtil.LEGAL_SPECIALIST + "角色内无任何用户！");
        }
        String candidate = assigneeService.getCandidateByBusiness(exemptionMatters.getId(), ConstantUtil.EXEMPTION_MATTERS, ConstantUtil.ASSIGNEE_LEGAL_SPECIALIST);
        if (StringUtil.isEmpty(candidate)) {
            String legalSpecialist = legalSpecials.stream().map(c -> c.toString()).collect(Collectors.joining(","));
            BusinessAssignee assignee = new BusinessAssignee(exemptionMatters.getId(), ConstantUtil.EXEMPTION_MATTERS);
            assignee.setCandidateId(legalSpecialist);
            assignee.setAssigneeType(ConstantUtil.ASSIGNEE_LEGAL_SPECIALIST);
            assigneeService.add(assignee);
        }

        PaymentInfo paymentInfo = paymentInfoService.getById(paymentApply.getPaymentInfoId());
        //获取合同编号
        ReviewQuotaDisburse reviewQuotaDisburse = reviewQuotaDisburseService.getById(paymentInfo.getQuotaDisburseId());
        ReviewMasterContract reviewMasterContract = reviewMasterContractService
                .lambdaQuery().eq(ReviewMasterContract::getReviewQuotaDisburseId, reviewQuotaDisburse.getId()).one();

        //完成流程进入下一步
        Map<String, Object> procVariables = new HashMap<>(1);
        procVariables.put(ConstantUtil.EXEMPTION_MATTER_APPROVAL + ConstantUtil._CANDIDATE,
                assigneeService.getCandidateByBusiness(exemptionMatters.getId(), exemptionMatters.getClass().getSimpleName(), ConstantUtil.ASSIGNEE_LEGAL_SPECIALIST));
        Map<String, Object> msgVariables = new HashMap<>(2);
        msgVariables.put(ConstantUtil.FLOWABLE_MSG_TITLE, reviewQuotaDisburse.getBusinessNumber());
        msgVariables.put(ConstantUtil.FLOWABLE_MSG_CONTENT,
                "业务编号为“" + reviewQuotaDisburse.getBusinessNumber() + "”——合同编号为“" + reviewMasterContract.getContractNo()
                        + "”——付款编号为“" + paymentApply.getPaymentNo() + "”的项目已进入“"
                        + "豁免事项跟进—formBusiness”阶段，");
        Boolean success = flowableService.completeMyTask(taskId, exemptionMatters, procVariables, null, exemptionMattersHistory.getId(),
                msgVariables, ConstantUtil.EXEMPTION_MATTERS, legalSpecials);
        if (success == null || !success) {
            throw new ValidatorException(CodeUtil.FAIL, "豁免事项跟进-资料审核时出错啦！");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void approval(ExemptionMattersApproval exemptionMattersApproval) {
        String taskId = exemptionMattersApproval.getTaskId();
        Long businessKey = exemptionMattersApproval.getBusinessKey();
        ExemptionMatters exemptionMatters = get(businessKey);
        exemptionMattersApproval.setExemptionMattersId(exemptionMatters.getId());
        exemptionMattersApprovalService.save(exemptionMattersApproval);
        PaymentApply paymentApply = paymentApplyService.getById(exemptionMatters.getPaymentApplyId());
        PaymentInfo paymentInfo = paymentInfoService.getById(paymentApply.getPaymentInfoId());
        Map<String, Object> msgVariables = new HashMap<>(2);
        msgVariables.put(ConstantUtil.FLOWABLE_MSG_TITLE, paymentInfo.getBusinessNo());
        String result;
        switch (exemptionMattersApproval.getApprovalConclusion()) {
            case ConstantConversionUtil.APPROVAL_RESULT_BACK:
                result = ConstantConversionUtil.APPROVAL_RESULT_BACK_DISPLAY;
                msgVariables.put(ConstantUtil.FLOWABLE_MSG_CONTENT,
                        "业务编号为“" + paymentInfo.getBusinessNo() +
                                "”——付款编号为“" + paymentApply.getPaymentNo() + "”的项目已进入“"
                                + "豁免事项跟进—formBusiness”阶段，");
                break;
            case ConstantConversionUtil.APPROVAL_RESULT_PASS:
                exemptionMatters.setExemptionStatus(ProjectInitiationStatusDict.ChildEnum.COMPLETED.getCode());
                updateById(exemptionMatters);
                result = ConstantConversionUtil.APPROVAL_RESULT_PASS_DISPLAY;
                msgVariables.put(ConstantUtil.FLOWABLE_MSG_CONTENT,
                        "业务编号为“" + paymentInfo.getBusinessNo() +
                                "”——付款编号为“" + paymentApply.getPaymentNo() + "”的豁免事项已审批通过,");

                /***审批通过则需要发送 知晓消息 **/

                BusinessProcessingLog businessProcessingLog = businessProcessingLogService
                        .findLatestByTaskDefKey("exemption_matters_approval", exemptionMatters.getClass().getSimpleName(),
                                exemptionMatters.getId());

                //获取合同编号
                ReviewQuotaDisburse reviewQuotaDisburse = reviewQuotaDisburseService.getById(paymentInfo.getQuotaDisburseId());
                ReviewMasterContract reviewMasterContract = reviewMasterContractService
                        .lambdaQuery().eq(ReviewMasterContract::getReviewQuotaDisburseId, reviewQuotaDisburse.getId()).one();

                systemMsgService.sendFlowMsgImmediately(reviewMasterContract.getApplicantCompanyName(),
                        "业务编号为“" + paymentInfo.getBusinessNo() +
                                "”——合同编号为“" + paymentInfo.getContractNo() +
                                "”——付款编号为“" + paymentApply.getPaymentNo() +
                                "”的豁免事项已审批通过,请知晓！",
                        Arrays.asList(businessProcessingLog.getAssignee().getId()), exemptionMatters.getId(),
                        ConstantConversionUtil.flowBusinessModuleCodes.get(exemptionMatters.getClass().getSimpleName()), false, null);

                break;
            default:
                result = "";
        }
        if (StringUtil.isEmpty(result)) {
            throw new ValidatorException(CodeUtil.FAIL, "审核结论有误！");
        }

        Boolean success = flowableService.completeMyTask(taskId, exemptionMatters, null, result,
                exemptionMattersApproval.getId(), msgVariables, exemptionMatters.getClass().getSimpleName());
        if (success == null || !success) {
            throw new ValidatorException(CodeUtil.FAIL, "豁免事项跟进-资料审核时出错啦！");
        }
    }

    @Override
    public List<BusinessProcessingTaskVo> findBySearch(SearchBusinessProcessingTask search) {
        List<BusinessProcessingTaskVo> taskVos = baseMapper.findBySearch(search);
        if (CollectionUtil.isNotEmpty(taskVos)) {
            taskVos.forEach(businessProcessingTaskVo -> {
                //填充融资金额
                ExemptionMatters exemptionMatters = getById(businessProcessingTaskVo.getId());
                PaymentApply paymentApply = paymentApplyService.getById(exemptionMatters.getPaymentApplyId());
                PaymentInfo paymentInfo = paymentInfoService.getById(paymentApply.getPaymentInfoId());
                ReviewFinancingInfo reviewFinancingInfo = reviewFinancingInfoService
                        .lambdaQuery().eq(ReviewFinancingInfo::getReviewQuotaDisburseId, paymentInfo.getQuotaDisburseId()).one();
                businessProcessingTaskVo.setFinancingAmount(reviewFinancingInfo.getFinancingAmount());
            });
        }
        return taskVos;
    }

    @Override
    public List<ExemptionMatters> getByPayBasicId(Long payBasicId) {
        return baseMapper.getByPayBasicId(payBasicId);
    }

    @Override
    public List<ExemptionMatters> getByCreditSubject(String socialCreditCode) {
        return baseMapper.getByCreditSubject(socialCreditCode);
    }

    @Override
    public ExemptionMatters getDetail(Long exemptionMattersId) {
        ExemptionMatters exemptionMatters = get(exemptionMattersId);
        PaymentApply paymentApply = paymentApplyService.getById(exemptionMatters.getPaymentApplyId());
        PaymentInfo paymentInfo = paymentInfoService.getById(paymentApply.getPaymentInfoId());
        List<PaymentCondition> conditions = paymentConditionService
                .lambdaQuery().eq(PaymentCondition::getPaymentApplyId, paymentApply.getId()).list();
        conditions.forEach(r -> {
            //填充附件
            List<PaymentConditionFileRef> conditionFileRefs = paymentConditionFileRefService
                    .lambdaQuery().eq(PaymentConditionFileRef::getPaymentConditionId, r.getId()).list();
            if (CollectionUtil.isNotEmpty(conditionFileRefs)) {
                List<FileStorage> fileStorages = conditionFileRefs.stream()
                        .map(conditionFileRef -> fileStorageService.get(conditionFileRef.getFileId())).collect(Collectors.toList());
                r.setExemptionFile(fileStorages);
            }
            if (StringUtil.isEmpty(r.getSupplement())) {
                r.setSupplement("");
            }
            List<ExemptionMattersRef> exemptionMattersRefs = exemptionMattersRefService.lambdaQuery().eq(ExemptionMattersRef::getPaymentConditionId, r.getId()).list();
            if (CollectionUtil.isNotEmpty(exemptionMattersRefs)) {
                List<FileStorage> fileStorages = exemptionMattersRefs.stream().map(exemptionMattersRef -> fileStorageService.get(exemptionMattersRef.getFileId())).collect(Collectors.toList());
                r.setFiles(fileStorages);
            }
        });
        //付款条件
        paymentApply.setConditionList(conditions);
        //付款类型
        Dictionary paymentType = dictionaryService.getByCode(paymentApply.getPaymentType());
        paymentApply.setPaymentType(paymentType.getName());
        //
        exemptionMatters.setPaymentApply(paymentApply);
        return exemptionMatters;
    }

    @Override
    public void download(Long exemptionMattersId, HttpServletResponse response) {
        ExemptionMatters exemptionMatters = get(exemptionMattersId);
        PaymentApply paymentApply = paymentApplyService.getById(exemptionMatters.getPaymentApplyId());
        List<PaymentCondition> conditions = paymentConditionService
                .lambdaQuery().eq(PaymentCondition::getPaymentApplyId, paymentApply.getId()).list();
        List<FileStorage> allFileStorage = new ArrayList<>();
        conditions.forEach(r -> {
            List<ExemptionMattersRef> exemptionMattersRefs = exemptionMattersRefService.lambdaQuery().eq(ExemptionMattersRef::getPaymentConditionId, r.getId()).list();
            if (CollectionUtil.isNotEmpty(exemptionMattersRefs)) {
                List<FileStorage> fileStorages = exemptionMattersRefs.stream().map(exemptionMattersRef ->
                        fileStorageService.get(exemptionMattersRef.getFileId())
                ).collect(Collectors.toList());
                allFileStorage.addAll(fileStorages);
            }
        });
        if (CollectionUtil.isEmpty(allFileStorage)) {
            throw new BusinessException(CodeUtil.FAIL, "无可下载的文件！");
        }
        renameFileStorageList(allFileStorage);
        // 文件打包下载
        fileStorageService.downloadZipFile(allFileStorage, "豁免事项跟进文件", FileModuleDict.ChildEnum.EXEMPTION_MATTERS_FILE, response);

    }

//    @Override
//    public void sendEmailJob() {
//        Date date = DateUtil.subDay(new Date(), 1);
//        List<ExemptionMatters> exemptionMatters = baseMapper.findAllByDate(date);
//        if (CollectionUtil.isNotEmpty(exemptionMatters)) {
//            List<Long> assignees = exemptionMatters.stream().map(ExemptionMatters::getManagerId).distinct().collect(Collectors.toList());
//            if (CollectionUtil.isNotEmpty(assignees)) {
//                for (Long id : assignees) {
//                    List<ExemptionMatters> collect = exemptionMatters.stream().filter(e -> e.getManagerId().compareTo(id) == 0).collect(Collectors.toList());
//                    if (CollectionUtil.isNotEmpty(collect)) {
//                        List<Map<String, String>> list = new ArrayList<>();
//                        for (ExemptionMatters exemptionMatter : collect) {
//                            Map<String, String> map = new LinkedHashMap<>();
//
//                            PaymentApply paymentApply = paymentApplyService.getById(exemptionMatter.getPaymentApplyId());
//                            PaymentInfo paymentInfo = paymentInfoService.getById(paymentApply.getPaymentInfoId());
//
//                            ReviewQuotaDisburse reviewQuotaDisburse = reviewQuotaDisburseService.getById(paymentInfo.getQuotaDisburseId());
//                            ReviewMasterContract masterContract = reviewMasterContractService
//                                    .lambdaQuery().eq(ReviewMasterContract::getReviewQuotaDisburseId, reviewQuotaDisburse.getId()).one();
//                            String applicantCompanyName = masterContract.getApplicantCompanyName();
//                            //todo 主企业
//                            String creditSubjectName = paymentInfo.getContractNo();
//                            List<ReviewMasterContractDebtor> debtorList = masterContract.getDebtorList();
//                            String debtorListStr = debtorList.stream().map(r -> r.getCompanyName()).collect(Collectors.joining(FlowableUtil.splitChar));
//                            debtorListStr = debtorListStr.replace(FlowableUtil.splitChar, ",");
//                            map.put("businessNo", paymentInfo.getBusinessNo());
//                            map.put("contractNo", paymentInfo.getContractNo());
//                            map.put("quotaDisburseBatch", paymentInfo.getQuotaDisburseBatch() + "");
//                            map.put("debtorListStr", debtorListStr);
//                            map.put("applicantCompanyName", applicantCompanyName);
//                            map.put("creditSubjectName", creditSubjectName);
//                            String amt = NumberFormatUtil.convertDecimal(reviewQuotaDisburse.getReviewFinancingInfo().getFinancingAmount(),
//                                    NumberFormatUtil.THOUSAND_SEPARATOR_TWO_DECIMAL);
//                            map.put("financingAmmount", amt + reviewQuotaDisburse.getReviewFinancingInfo().getCurrencyType().getCode());
//                            list.add(map);
//                        }
//                        //发送消息
//                        sendEmail(id, list, date);
//                    }
//                }
//            }
//        }
//    }

    private void sendEmail(Long userId, List<Map<String, String>> list, Date date) {
        //构建邮件模板内容
        StringBuilder builder = new StringBuilder();
        builder.append("<!DOCTYPE html>\n" +
                "<html>\n" +
                "<head>\n" +
                "<meta charset=\"utf-8\">\n" +
                "<title>豁免事项跟进知会</title>\n" +
                "<style>\n" +
                ".desc-box {\n" +
                "margin-top: 20px;\n" +
                "}\n" +
                ".desc-box > div {\n" +
                "margin-bottom: 20px;\n" +
                "}\n" +
                ".desc-title {\n" +
                "margin-left: 40px;\n" +
                "}\n" +
                "table,td,th\n" +
                "{\n" +
                "border:1px solid black;\n" +
                "}\n" +
                "table\n" +
                "{\n" +
                "width:100%;\n" +
                "border: 0px;\n" +
                "border-collapse:collapse;\n" +
                "}\n" +
                "th\n" +
                "{\n" +
                "height:50px;\n" +
                "}\n" +
                ".table-header\n" +
                "{\n" +
                "text-align: center;\n" +
                "height: 40px;\n" +
                "font-weight: bold;\n" +
                "}\n" +
                ".table-header td {\n" +
                "}\n" +
                ".table-body th  {\n" +
                "height: 30px;\n" +
                "text-align: center;\n" +
                "font-weight: normal;\n" +
                "}\n" +
                "</style>\n" +
                "</head>\n" +
                "<body>\n" +
                "<div class=\"desc-box\">\n" +
                "<div>您好：</div>\n" +
                "<div class=\"desc-title\">" + cn.hutool.core.date.DateUtil.format(date, "yyyy年MM月dd日") + "以下支用通过付款审批，有豁免事项需要补充（未完成补充无法提起新的支用），豁免内容详情请于SOP中豁免事项列表查看。</div>\n" +
                "</div>\n" +
                "<table border=\"0\">\n" +
                "<tr class=\"table-header\">\n" +
                "<td>业务编号</td>\n" +
                "<td>授信主体</td>\n" +
                "<td>债权人</td>\n" +
                "<td>债务人</td>\n" +
                "<td>合同编号</td>\n" +
                "<td>额度支用批次</td>\n" +
                "<td>融资金额</td>\n" +
                "</tr>\n");
        for (Map map : list) {
            builder.append(
                    "<tr class=\"table-body\">\n" +
                            "<th>" + map.get("businessNo") + "</th>\n" +
                            "<th>" + map.get("creditSubjectName") + "</th>\n" +
                            "<th>" + map.get("applicantCompanyName") + "</th>\n" +
                            "<th>" + map.get("debtorListStr") + "</th>\n" +
                            "<th>" + map.get("contractNo") + "</th>\n" +
                            "<th>" + map.get("quotaDisburseBatch") + "</th>\n" +
                            "<th>" + map.get("financingAmmount") + "</th>\n" +
                            "</tr>\n");
        }
        builder.append("</table>\n" +
                "</body>\n" +
                "</html>");
        String subject = "豁免事项跟进知会";
        //收件人：项目经理
        User user = userService.get(userId);
        List<Long> operationSpecialist = userService.findUserIdByRole(ConstantUtil.OPERATION_SPECIALIST);
        if (operationSpecialist == null || operationSpecialist.size() == 0) {
            throw new ValidatorException(CodeUtil.FAIL, ConstantUtil.OPERATION_SPECIALIST + "角色内无任何用户！");
        }

    }


    private void renameFileStorageList(List<FileStorage> fileStorageList) {
        //根据文件原名进行去重
        Map<String, Integer> nameCounts = new HashMap<>();
        for (FileStorage file : fileStorageList) {
            nameCounts.put(file.getOriginalName(), nameCounts.getOrDefault(file.getOriginalName(), 0) + 1);
        }
        Set<String> duplicates = new HashSet<>();
        for (Map.Entry<String, Integer> entry : nameCounts.entrySet()) {
            if (entry.getValue() > 1) {
                duplicates.add(entry.getKey());
            }
        }
        Map<String, Integer> renameCounts = new HashMap<>();
        for (int i = 0; i < fileStorageList.size(); i++) {
            FileStorage fileStorage = fileStorageList.get(i);
            if (duplicates.contains(fileStorage.getOriginalName())) {
                int count = renameCounts.getOrDefault(fileStorage.getOriginalName(), 0) + 1;
                int index = fileStorage.getOriginalName().lastIndexOf(".");
                String newName = fileStorage.getOriginalName().substring(0, index) + DateUtil.dateToString(new Date(), "yyyyMMdd") + "-" + count + fileStorage.getFileType();
                renameCounts.put(fileStorage.getOriginalName(), count);
                fileStorage.setOriginalName(newName);
                fileStorageList.set(i, fileStorage);
            }
        }
    }

    public File downloadZip(List<FileStorage> fileStorageList, String name, FileModuleDict.ChildEnum moduleType) {

        try {
            name = new String(name.getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e1) {
            throw new BusinessException(CodeUtil.FAIL, "下载附件转码失败：" + e1.getMessage());
        }
        String desPath = FileUtil.getAbsolutePath(name, ".zip", moduleType);
        File zipFile = new File(desPath);
        if (!zipFile.getParentFile().exists()) {
            zipFile.getParentFile().mkdirs();
        }
        ZipOutputStream zipStream = null;
        FileInputStream zipSource = null;
        BufferedInputStream bufferStream = null;
        try {
            // 构造最终压缩包的输出流
            zipStream = new ZipOutputStream(new FileOutputStream(zipFile));
            for (FileStorage fileStorage : fileStorageList) {
                String path = fileStorage.getAbsolutePath();
                File file = new File(path);
                // 将需要压缩的文件格式化为输入流
                zipSource = new FileInputStream(file);
                // 压缩条目不是具体独立的文件，而是压缩包文件列表中的列表项，称为条目，就像索引一样
                ZipEntry zipEntry = new ZipEntry(fileStorage.getOriginalName());
                // 定位该压缩条目位置，开始写入文件到压缩包中
                zipStream.putNextEntry(zipEntry);
                // 输入缓冲流
                bufferStream = new BufferedInputStream(zipSource, 1024 * 10);
                int read = 0;
                // 创建读写缓冲区
                byte[] buf = new byte[1024 * 10];
                while ((read = bufferStream.read(buf, 0, 1024 * 10)) != -1) {
                    zipStream.write(buf, 0, read);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭流
            try {
                if (null != bufferStream) {
                    bufferStream.close();
                }
                if (null != zipStream) {
                    zipStream.close();
                }
                if (null != zipSource) {
                    zipSource.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return zipFile;
    }

    /**
     * 下载文件夹
     *
     * @param res
     * @param file
     */
    public void doDownloadZip(HttpServletResponse res, File file) {
        try {
            if (file.exists()) {
                String fileName = file.getName();
                fileName = new String(fileName.getBytes("UTF-8"));
                String basePath = file.getAbsolutePath();
                InputStream in = new FileInputStream(new File(basePath));
                fileName = URLEncoder.encode(fileName, "UTF-8");

                res.setHeader("content-disposition", "attachment;filename=" + fileName);
                OutputStream out = res.getOutputStream();
                byte[] b = new byte[1024];
                int len = -1;
                while ((len = in.read(b)) != -1) {
                    out.write(b, 0, len);
                }
                // 关闭
                out.close();
                in.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
