package com.ecep.contract.ds.contract.tasker;

import com.ecep.contract.*;
import com.ecep.contract.ds.company.CompanyFileUtils;
import com.ecep.contract.ds.company.model.Company;
import com.ecep.contract.ds.company.model.CompanyExtendInfo;
import com.ecep.contract.ds.company.service.CompanyExtendInfoService;
import com.ecep.contract.ds.contract.model.Contract;
import com.ecep.contract.ds.contract.model.ContractFile;
import com.ecep.contract.ds.contract.service.ExtendVendorInfoService;
import com.ecep.contract.ds.converter.NumberStringConverter;
import com.ecep.contract.ds.customer.model.CompanyCustomer;
import com.ecep.contract.ds.customer.model.CompanyCustomerFile;
import com.ecep.contract.ds.other.service.EmployeeService;
import com.ecep.contract.ds.project.model.Project;
import com.ecep.contract.ds.project.model.ProjectBid;
import com.ecep.contract.ds.project.model.ProjectCost;
import com.ecep.contract.ds.project.model.ProjectQuotation;
import com.ecep.contract.ds.project.service.*;
import com.ecep.contract.ds.vendor.model.ExtendVendorInfo;
import com.ecep.contract.ds.vendor.service.VendorGroupRequireFileTypeService;
import com.ecep.contract.model.*;
import com.ecep.contract.service.tasker.ProjectCostImportItemsFromContractsTasker;
import com.ecep.contract.util.VerifyContext;
import com.ecep.contract.vo.*;
import lombok.Data;
import org.hibernate.Hibernate;
import org.springframework.util.StringUtils;

import java.io.File;
import java.text.NumberFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;

@Data
public class ContractVerifyComm extends VerifyContext {
    private ProjectSaleTypeService getProjectSaleTypeService() {
        return getBean(ProjectSaleTypeService.class);
    }

    ProjectCostService getProjectCostService() {
        return getBean(ProjectCostService.class);
    }

    ProjectQuotationService getProjectQuotationService() {
        return getBean(ProjectQuotationService.class);
    }

    ProjectBidService getProjectBidService() {
        return getBean(ProjectBidService.class);
    }

    private ProjectSaleTypeRequireFileTypeService getSaleTypeRequireFileTypeService() {
        return getBean(ProjectSaleTypeRequireFileTypeService.class);
    }

    private VendorGroupRequireFileTypeService getVendorGroupRequireFileTypeService() {
        return getBean(VendorGroupRequireFileTypeService.class);
    }

    private ExtendVendorInfoService getExtendVendorInfoService() {
        return getBean(ExtendVendorInfoService.class);
    }

    private CompanyExtendInfoService getCompanyExtendInfoService() {
        return getBean(CompanyExtendInfoService.class);
    }

    /**
     *
     */
    private Map<ContractFileType, ContractFileTypeLocalVo> fileTypeLocalMap = null;
    private Contract contract;

    /**
     * 是否验证企业存储目录
     */
    private boolean verifyCompanyPath = true;
    /**
     * 是否验证企业状态
     */
    private boolean verifyCompanyStatus = true;
    /**
     * 是否验证企业文件(资信报告)
     */
    private boolean verifyCompanyCredit = true;
    /**
     * 是否验证客户
     */
    private boolean verifyCustomer = true;
    /**
     * 是否验证客户文件(合同文件)
     */
    private boolean verifyCustomerFiles = true;
    /**
     * 是否验证客户子合同日期
     */
    private boolean verifyCustomerSubContractDate = true;
    /**
     * 是否验证供应商
     */
    private boolean verifyVendor = true;
    /**
     * 是否验证供应商文件(供应商合同)
     */
    private boolean verifyVendorFiles = true;

    /**
     * 合同合规性检测
     *
     * @param contract 要验证的合同对象
     * @param holder   输出
     */
    public boolean verify(Contract contract, MessageHolder holder) {
        boolean passed = true;
        LocalDate setupDate = contract.getSetupDate();
        if (setupDate == null) {
            holder.error("未设置合同提交日期");
            passed = false;
        }

        Company company = contract.getCompany();
        if (company == null) {
            holder.error("未关联企业");
            return false;
        }
        if (!Hibernate.isInitialized(company)) {
            company = getCompanyService().getById(company.getId());
        }
        if (!verify(company, contract, holder)) {
            passed = false;
        }
        return passed;
    }

    public boolean verify(Company company, LocalDate verifyDate, MessageHolder holder) {
        CompanyExtendInfo companyExtendInfo = getCompanyExtendInfoService().findByCompany(company);
        if (companyExtendInfo.isDisableVerify()) {
            holder.debug("公司设定不做校验");
            return true;
        }

        boolean passed = true;
        MessageHolder subHolder = holder.sub(company.getName() + " -> ");
        if (verifyCompanyPath) {
            if (!CompanyFileUtils.exists(company.getPath())) {
                subHolder.error("公司目录未设置");
                passed = false;
            } else {
                File basePath = getCompanyService().getBasePath();
                if (!company.getPath().startsWith(basePath.getAbsolutePath())) {
                    subHolder.warn("公司目录未在规定目录下");
                }
            }
        }

        if (verifyCompanyStatus) {
            if (!getCompanyService().verifyEnterpriseStatus(company, verifyDate, subHolder)) {
                passed = false;
            }
        }

        if (verifyCompanyCredit) {
            if (!getCompanyFileService().verify(company, verifyDate, subHolder)) {
                passed = false;
            }
        }
        return passed;
    }

    /**
     * 验证合同是否合规
     *
     * @param company
     * @param contract
     * @param holder
     * @return
     */
    public boolean verify(Company company, Contract contract, MessageHolder holder) {
        boolean passed = true;
        LocalDate setupDate = contract.getSetupDate();

        Employee employee = contract.getEmployee();
        if (employee == null) {
            holder.error("未关联业务员");
            passed = false;
        }

        if (contract.getAmount() == null || contract.getAmount() <= 0) {
            holder.error("合同金额小于等于0");
            passed = false;
        }

        if (!verify(company, setupDate, holder)) {
            passed = false;
        }

        // 合同类型
        switch (contract.getPayWay()) {
            case RECEIVE -> {
                // 销售合同
                CompanyExtendInfo companyExtendInfo = getCompanyExtendInfoService().findByCompany(company);
                holder.debug("验证销售合同 [" + contract.getCode() + "]...");
                if (!verifyAsCustomer(company, companyExtendInfo, contract, holder.sub("-> "))) {
                    passed = false;
                    holder.error("销售合同合规验证不通过");
                }

                // 销售合同下的采购合同
                List<Contract> list = getContractService().findAllByParent(contract);
                if (list.isEmpty()) {
                    holder.info("没有采购合同");
                } else {
                    holder.info("销售合同下的采购合同：");
                    int count = 1;
                    for (Contract v : list) {
                        if (!Hibernate.isInitialized(v)) {
                            v = getContractService().getById(v.getId());
                        }
                        MessageHolder subHolder = holder.sub(count++ + "/" + list.size() + " -> ");
                        subHolder.debug("验证采购合同 [" + v.getCode() + "]...");
                        if (!verify(v, subHolder)) {
                            passed = false;
                            subHolder.error("采购合同 [" + v.getCode() + "] 合规验证不通过");
                        }
                        if (CompanyFileUtils.exists(v.getPath())) {
                            if (!v.getPath().startsWith(contract.getPath())) {
                                subHolder.error("合同目录未在规定目录下");
                                passed = false;
                            }
                        } else {
                            subHolder.error("合同目录未设置");
                            passed = false;
                        }
                    }

                    DoubleSummaryStatistics statistics = list.stream().mapToDouble(c -> {
                        return Objects.requireNonNullElse(c.getAmount(), 0.0);
                    }).summaryStatistics();
                    NumberFormat numberFormat = NumberFormat.getCurrencyInstance(getLocale());
                    holder.debug(String.format(getLocale(), "采购合同金额合计：%n, 平均值：,最大值：,最小值：", statistics.getSum(), statistics.getAverage(), statistics.getMax(), statistics.getMin()));
                    if (contract.getAmount() != null && statistics.getSum() > contract.getAmount()) {
                        holder.warn("采购合同金额合计大于销售合同金额");
                    }
                }

                break;
            }
            case PAY -> {
                holder.debug("验证采购合同 [" + contract.getCode() + "]...");
                verifyAsVendor(company, contract, holder);
                break;
            }
            case OTHER -> {
                holder.error("合同付款类型：其他");
                break;
            }
            default -> {
                holder.error("合同付款类型：未设置");
            }
        }
        return passed;
    }

    private void verifyAsVendor(Company company, Contract contract, MessageHolder holder) {
        // 供应商，检查评价表
        ExtendVendorInfoVo vendorInfo = getExtendVendorInfoService().findByContract(contract);
        if (vendorInfo == null) {
            ExtendVendorInfo info = getExtendVendorInfoService().newInstanceByContract(contract);
            vendorInfo = getExtendVendorInfoService().save(info).toVo();
            holder.info("创建供应商信息 #" + vendorInfo.getId());
        }
        VendorGroupVo group = getVendorGroupService().findById(vendorInfo.getGroupId());
        boolean assignedProvider = vendorInfo.isAssignedProvider();
        if (assignedProvider) {
            holder.debug("采购信息中设定为指定供应商");
        }

        if (group != null) {
            vendorInfo.setGroupId(group.getId());
        }
        if (verifyCustomerSubContractDate) {
            // 检查子合同日期是否在销售合同之后
            if (!vendorInfo.isPrePurchase()) {
                String parentCode = contract.getParentCode();
                if (StringUtils.hasText(parentCode)) {
                    var parent = getContractService().findByCode(parentCode);
                    if (parent != null) {
                        if (contract.getSetupDate().isBefore(parent.getSetupDate())) {
                            holder.warn("采购合同：" + contract.getCode() + " 提交日期在销售合同之前");
                        }
                    }
                }
            }
        }
        if (verifyVendor) {
            getVendorService().verify(contract, holder);
        }

        if (verifyVendorFiles) {
            holder.debug("核验文件...");
            verifyVendorFile(group, assignedProvider, contract, holder);
        }
    }

    private void verifyVendorFile(VendorGroupVo group, boolean assignedProvider, Contract contract,
                                  MessageHolder holder) {
        if (group == null) {
            return;
        }
        boolean loseFile = false;
        List<ContractFileVo> files = getContractFileService().findAllByContract(contract);
        List<VendorGroupRequireFileTypeVo> list = getVendorGroupRequireFileTypeService().findByGroupId(group.getId());
        if (list != null && !list.isEmpty()) {
            for (VendorGroupRequireFileTypeVo item : list) {
                ContractFileType fileType = item.getFileType();
                if (fileType == null) {
                    continue;
                }
                if (fileType == ContractFileType.QuotationSheet && assignedProvider
                        && group.isRequireQuotationSheetForBid()) {
                    continue;
                }
                if (!hasFileType(files, fileType)) {
                    holder.error("供应商" + getFileTypeLocalValue(fileType) + "未上传");
                    loseFile = true;
                }

            }
        }

        // 供应商比价
        if (group.isPriceComparison()) {
            if (assignedProvider) {
                holder.debug("指定供应商, 跳过供应商比价");
            } else {
                boolean requireQuotation = group.isRequireQuotationSheetForBid();
                List<ContractBidVendorVo> bidVendors = getContractBidVendorService().findByContract(contract);
                if (bidVendors == null || bidVendors.isEmpty()) {
                    holder.error("未上报供应商比价");
                } else {
                    for (ContractBidVendorVo bidVendor : bidVendors) {
                        if (bidVendor.getQuotationSheetFileId() == null) {
                            holder.error("供应商比价：" + getCompanyService().findById(bidVendor.getCompanyId()).getName() + " 未上传报价表");
                            continue;
                        }
                        var fileVo = getContractFileService().findById(bidVendor.getQuotationSheetFileId());
                        if (fileVo == null) {
                            if (requireQuotation && bidVendor.getCompanyId().equals(contract.getCompany().getId())) {
                                holder.debug("供应商类型启用了允许选中供应商不必须要有报价表");
                            } else {
                                var company = getCompanyService().findById(bidVendor.getCompanyId());
                                holder.error("供应商比价：" + company.getName() + " 未上传/关联报价表");
                                loseFile = true;
                            }
                        } else {
                            ContractFileType type = fileVo.getType();
                            if (type != ContractFileType.QuotationSheet) {
                                holder.error("供应商比价：" + fileVo.getFileName() + " 报价表记录异常，类型错误");
                            }
                            File file = new File(contract.getPath(), fileVo.getFileName());
                            if (!file.exists()) {
                                holder.error("供应商比价：" + file.getName() + " 报价表记录异常，文件不存在");
                                loseFile = true;
                            }
                        }
                    }
                }
            }
        }
        if (loseFile && files.isEmpty()) {
            holder.warn("!上传文件空!");
        }
    }

    ContractFileTypeLocalVo getFileTypeLocal(ContractFileType type) {
        if (fileTypeLocalMap == null) {
            fileTypeLocalMap = getContractFileTypeService().findAll(getLocale());
        }
        return fileTypeLocalMap.get(type);
    }

    String getFileTypeLocalValue(ContractFileType type) {
        ContractFileTypeLocalVo fileTypeLocal = getContractFileTypeService().findByTypeAndLang(type, getLocale());
        if (fileTypeLocal == null) {
            return type.name();
        }
        return fileTypeLocal.getValue();
    }

    private boolean hasFileType(List<ContractFileVo> files, ContractFileType fileType) {
        if (files == null || files.isEmpty()) {
            return false;
        }
        for (ContractFileVo file : files) {
            if (file.getType() == fileType) {
                return true;
            }
        }
        return false;
    }

    private boolean verifyAsCustomer(Company company, CompanyExtendInfo companyExtendInfo, Contract contract,
                                     MessageHolder holder) {
        boolean passed = true;
        Project project = contract.getProject();
        if (project == null) {
            holder.debug("未关联项目，测试关联/创建项目...");
            // 收款的合同时，检查是否关联了项目，如果没有则创建
            if (contract.getPayWay() == ContractPayWay.RECEIVE) {
                holder.debug("根据合同号 " + contract.getCode() + ", 未找到相关项目或创建相关项目");
                project = getProjectService().findByCode(contract.getCode());
                if (project == null) {
                    holder.debug("未找到 " + contract.getCode() + " 相关项目, 创建相关项目");
                    try {
                        project = getProjectService().newInstanceByContract(contract);
                        project = getProjectService().save(project);
                        holder.info("创建关联项目成功:" + project.getCode() + " " + project.getName());
                    } catch (Exception e) {
                        holder.error("创建关联项目失败: " + e.getMessage() + ", 编号：" + contract.getCode());
                        return false;
                    }
                }
                contract.setProject(project);
                contract = getContractService().save(contract);
                holder.info("关联项目:" + project.getCode() + " " + project.getName());
            } else {
                holder.warn("未关联项目");
            }
        }

        // fixed no hibernate session
        if (project != null) {
            if (!Hibernate.isInitialized(project)) {
                project = getProjectService().getById(project.getId());
                // fixed
                contract.setProject(project);
            }
        }

        if (project != null) {
            holder.info("核验销售合同关联的项目:" + project.getCode());
            var subHolder = holder.sub(project.getCode() + " - ");
            if (!verifyProject(contract, project, subHolder)) {
                passed = false;
            }

            if (!companyExtendInfo.isDisableVerify()) {
                if (verifyCustomerFiles) {
                    subHolder.info("核验文件...");
                    if (!verifyProjectFileAsCustomer(project, contract, subHolder)) {
                        passed = false;
                    }
                }
            }

            ProjectSaleType saleType = project.getSaleType();
            if (saleType != null) {
                if (CompanyFileUtils.exists(contract.getPath())) {
                    if (!Hibernate.isInitialized(saleType)) {
                        saleType = getProjectSaleTypeService().getById(saleType.getId());
                        project.setSaleType(saleType);
                    }
                    if (!contract.getPath().startsWith(saleType.getPath())) {
                        holder.error("合同目录未在销售类型目录下");
                        passed = false;
                    }
                }
            }
        }

        if (!companyExtendInfo.isDisableVerify()) {
            if (!verifyCustomerContract(contract, holder)) {
                passed = false;
            }
            if (!verifyContractFileAsCustomer(contract, holder)) {
                passed = false;
            }
        }
        return passed;
    }

    /**
     * 客户，检查评估表
     */
    private boolean verifyCustomerContract(Contract contract, MessageHolder holder) {
        if (!verifyCustomer) {
            return false;
        }
        boolean valid = true;
        Company company = contract.getCompany();
        if (company == null) {
            holder.warn("合同未关联公司");
            valid = false;
        }

        CompanyCustomer companyCustomer = getCompanyCustomerService().findByCompany(company);
        if (companyCustomer == null) {
            holder.warn("合同未关联客户");
            valid = false;
        } else {
            if (!StringUtils.hasText(companyCustomer.getPath())) {
                holder.warn("客户未设置文件夹");
                valid = false;
            }
            LocalDate developDate = companyCustomer.getDevelopDate();
            if (developDate == null) {
                holder.warn("客户未设置开发日期");
                valid = false;
            }
            if (!verifyCustomerFileByContract(companyCustomer, contract, holder)) {
                valid = false;
            }
        }
        return valid;
    }

    private boolean verifyCustomerFileByContract(CompanyCustomer companyCustomer, Contract contract,
                                                 MessageHolder holder) {
        List<LocalDate> verifyDates = new ArrayList<>();
        LocalDate minDate = LocalDate.of(2022, 1, 1);
        LocalDate developDate = companyCustomer.getDevelopDate();
        if (developDate != null) {
            if (developDate.isAfter(minDate)) {
                minDate = developDate;
            }
        }
        if (contract.getSetupDate() != null) {
            LocalDate setupDate = contract.getSetupDate();
            if (setupDate.isBefore(developDate)) {
                holder.error("合同提交日期 " + setupDate + " 早于客户开发日期 " + developDate + ".");
                return false;
            }
            if (setupDate.isBefore(minDate)) {
                holder.debug("合同提交日期 " + setupDate + " 早于 " + minDate + ", 跳过");
            } else {
                verifyDates.add(setupDate);
            }
        }
        if (contract.getStartDate() != null) {
            LocalDate startDate = contract.getStartDate();
            if (startDate.isBefore(developDate)) {
                holder.warn("合同起始日期 " + startDate + " 早于客户开发日期 " + developDate + ".");
            }

            if (startDate.isBefore(minDate)) {
                holder.debug("合同起始日期 " + startDate + " 早于 " + minDate + ", 跳过");
            } else {
                verifyDates.add(startDate);
            }
        }
        if (contract.getOrderDate() != null) {
            LocalDate orderDate = contract.getOrderDate();
            if (orderDate.isBefore(developDate)) {
                holder.error("合同签订日期 " + orderDate + " 早于客户开发日期 " + developDate + ".");
                return false;
            }
            if (orderDate.isBefore(minDate)) {
                holder.debug("合同签订日期 " + orderDate + " 早于 " + minDate + ", 跳过");
            } else {
                verifyDates.add(orderDate);
            }
        }

        if (verifyDates.isEmpty()) {
            holder.warn("合同没有符合可核验的日期");
            return false;
        }

        // 客户
        List<CompanyCustomerFile> files = getCompanyCustomerFileService().findAllByCustomer(companyCustomer);
        if (files == null || files.isEmpty()) {
            holder.warn("未见客户评估表");
            return false;
        }

        for (LocalDate verifyDate : verifyDates) {
            CompanyCustomerFile customerFile = files.stream()
                    .filter(v -> v.getSignDate() != null && v.isValid())
                    .filter(v -> v.getType() == CustomerFileType.EvaluationForm)
                    .filter(v -> MyDateTimeUtils.dateValidFilter(verifyDate, v.getSignDate(),
                            v.getSignDate().plusYears(1), 7))
                    .findFirst().orElse(null);
            if (customerFile != null) {
                return true;
            }
        }

        CompanyCustomerFile latestFile = files.stream()
                .filter(v -> v.getSignDate() != null && v.isValid())
                .filter(v -> v.getType() == CustomerFileType.EvaluationForm)
                .max(Comparator.comparing(CompanyCustomerFile::getSignDate))
                .orElse(null);

        if (latestFile == null) {
            holder.error("未匹配的客户评估");
            return false;
        }

        holder.error("客户评估已过期，最后一个客户评估报告日期：" + latestFile.getSignDate() + ", 检测日期："
                + verifyDates.stream().map(LocalDate::toString).collect(Collectors.joining(", ")));
        return false;
    }

    /**
     * 核查合同对应的项目是否合规
     */
    private boolean verifyProject(Contract contract, Project project, MessageHolder holder) {
        boolean passed = true;
        ProjectSaleType saleType = project.getSaleType();
        if (saleType == null) {
            String code = contract.getCode();
            if (code != null && code.length() > 5) {
                ProjectSaleTypeVo saleTypeVo = getProjectSaleTypeService().findByCode(code.substring(0, 1));
                if (saleTypeVo != null) {
                    saleType = getProjectSaleTypeService().getById(saleTypeVo.getId());
                }
            }
        }

        if (saleType == null) {
            holder.warn("销售类型未设置");
        }
        if (project.getAmount() == null || project.getAmount() <= 0) {
            holder.error("金额小于等于0");
            passed = false;
        }

        //
        boolean needImport = false;

        List<ProjectCost> projectCosts = getProjectCostService().findByProject(project);
        ProjectCost autoCost = null;
        for (ProjectCost cost : projectCosts) {
            if (cost.getVersion() == 0) {
                autoCost = cost;
                break;
            }
        }

        if (autoCost == null) {
            // 创建 V0 项目成本
            ProjectCost cost = new ProjectCost();
            cost.setProject(project);
            cost.setVersion(0);
            cost.setStampTax(0.03f);
            cost.setTaxAndSurcharges(11f);
            cost.setApplicant(getEmployeeService().getById(EmployeeService.DEFAULT_SYSTEM_EMPLOYEE_ID));
            cost.setApplyTime(LocalDateTime.now());
            cost.setDescription("自动导入");
            autoCost = getProjectCostService().save(cost);
            needImport = true;
        } else {
            // 检查 V0 项目成本
            if (autoCost.getGrossProfitMargin() <= 0) {
                NumberFormat instance = NumberFormat.getNumberInstance(getLocale());
                instance.setMaximumFractionDigits(2);
                NumberStringConverter converter = new NumberStringConverter(instance);
                holder.warn("V0项目成本毛利率异常：" + converter.toString(autoCost.getGrossProfitMargin()) + "<=0%");
                needImport = true;
            }
        }

        if (needImport && !autoCost.isImportLock()) {
            ProjectCostImportItemsFromContractsTasker tasker = new ProjectCostImportItemsFromContractsTasker();
            tasker.setCost(autoCost);

            // 在类中添加以下依赖，假设使用 Spring Security 来获取当前登录用户
            // 以下代码替换原有的获取当前用户逻辑，假设用户名即为员工 ID
            // 需根据实际业务调整 UserDetails 中的信息获取方式
            // 使用系统员工作为当前用户，实际项目中可能需要修改这里的逻辑
            tasker.setCurrentUser(() -> {
                return getEmployeeService().getById(EmployeeService.DEFAULT_SYSTEM_EMPLOYEE_ID);
            });

            autoCost.setApplyTime(LocalDateTime.now());
            holder.debug("更新V0项目成本");
            SpringApp.getTaskMonitorCenter().registerAndStartTask(tasker);
        }

        // 检查最新的项目成本，默认 V1
        ProjectCost latestCost = null;
        if (!projectCosts.isEmpty()) {
            int maxVersion = -1;
            for (ProjectCost cost : projectCosts) {
                if (cost.getVersion() > maxVersion) {
                    maxVersion = cost.getVersion();
                    latestCost = cost;
                }
            }
        }

        if (latestCost == null) {
            ProjectCost cost = new ProjectCost();
            cost.setProject(project);
            cost.setVersion(1);
            cost.setStampTax(0.03f);
            cost.setTaxAndSurcharges(11f);
            Employee applicant = project.getApplicant();
            if (applicant == null) {
                applicant = contract.getEmployee();
            }
            cost.setApplicant(applicant);
            cost.setApplyTime(project.getCreated().atTime(LocalTime.now()));
            latestCost = getProjectCostService().save(cost);
        } else {
            //
            if (latestCost.getGrossProfitMargin() <= 0) {
                NumberFormat instance = NumberFormat.getNumberInstance(getLocale());
                instance.setMaximumFractionDigits(2);
                NumberStringConverter converter = new NumberStringConverter(instance);
                holder.warn("V" + latestCost.getVersion() + "项目成本毛利率异常："
                        + converter.toString(latestCost.getGrossProfitMargin()) + "<=0%");
            } else if (latestCost.getGrossProfitMargin() >= 50) {
                NumberFormat instance = NumberFormat.getNumberInstance(getLocale());
                instance.setMaximumFractionDigits(2);
                NumberStringConverter converter = new NumberStringConverter(instance);
                holder.warn("V" + latestCost.getVersion() + "项目成本毛利率异常："
                        + converter.toString(latestCost.getGrossProfitMargin()) + ">=50%");
            }
        }

        if (project.isUseBid()) {
            List<ProjectBid> bids = getProjectBidService().findAllByProject(project);
            if (bids.isEmpty()) {
                holder.warn("投标未创建");
            }
        }
        if (project.isUseOffer()) {
            List<ProjectQuotation> quotations = getProjectQuotationService().findAllByProject(project);
            if (quotations.isEmpty()) {
                holder.warn("报价未创建");
            }
        }
        return passed;
    }

    private boolean verifyContractFileAsCustomer(Contract contract, MessageHolder holder) {
        boolean loseFile = false;
        var fileService = getContractFileService();
        var fileTypeService = getContractFileTypeService();
        return !loseFile;
    }

    private boolean verifyProjectFileAsCustomer(Project project, Contract contract, MessageHolder holder) {
        boolean passed = true;
        var fileService = getContractFileService();
        var fileTypeService = getContractFileTypeService();
        List<ContractFileVo> files = fileService.findAllByContract(contract);
        // 投标
        if (project.isUseBid()) {
            // 投标审批表
            if (!hasFileType(files, ContractFileType.BidApprovalForm)) {
                holder.error(fileTypeService.findByTypeAndLang(ContractFileType.BidApprovalForm, getLocale()).getValue() + "未上传");
                passed = false;
            }
            // 中标通知书
            if (!hasFileType(files, ContractFileType.BidAcceptanceLetter)) {
                holder.error(fileTypeService.findByTypeAndLang(ContractFileType.BidAcceptanceLetter, getLocale()).getValue() + "未上传");
                passed = false;
            }
        }
        // 报价
        if (project.isUseOffer()) {
            if (!hasFileType(files, ContractFileType.QuotationApprovalForm)) {
                holder.error(fileTypeService.findByTypeAndLang(ContractFileType.QuotationApprovalForm, getLocale()).getValue() + "未上传");
                passed = false;
            }
        }

        ProjectSaleType saleType = project.getSaleType();
        if (saleType != null) {
            List<ProjectSaleTypeRequireFileTypeVo> list = getSaleTypeRequireFileTypeService()
                    .findBySaleType(saleType);
            for (ProjectSaleTypeRequireFileTypeVo item : list) {
                ContractFileType fileType = item.getFileType();
                if (fileType != null) {
                    if (!hasFileType(files, fileType)) {
                        holder.error(fileTypeService.findByTypeAndLang(fileType, getLocale()).getValue() + "未上传");
                        passed = false;
                    }
                }
            }
            if (!Hibernate.isInitialized(saleType)) {
                saleType = getProjectSaleTypeService().getById(saleType.getId());
            }
            if (saleType.isCriticalProjectDecision()) {
                if (contract.getAmount() != null && contract.getAmount() >= saleType.getCriticalProjectLimit()) {
                    holder.debug("合同金额 " + contract.getAmount() + " 超过 " + saleType.getCriticalProjectLimit());
                    if (!hasFileType(files, ContractFileType.CriticalProjectDecisionRecord)) {
                        holder.error(fileTypeService.findByTypeAndLang(ContractFileType.CriticalProjectDecisionRecord, getLocale()).getValue() + "未上传");
                        passed = false;
                    }
                }
            }
        }
        return passed;
    }
}
