package com.yiboshi.science.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yiboshi.arch.exception.BusinessException;
import com.yiboshi.science.base.BaseServiceImpl;
import com.yiboshi.science.base.Pagination;
import com.yiboshi.science.config.bean.SystemProperties;
import com.yiboshi.science.config.security.SecurityUserHolder;
import com.yiboshi.science.dao.ComProjectDAO;
import com.yiboshi.science.entity.*;
import com.yiboshi.science.enumeration.CommonEnum;
import com.yiboshi.science.param.dto.*;
import com.yiboshi.science.param.query.ComProjectQueryVO;
import com.yiboshi.science.service.*;
import com.yiboshi.science.utils.*;
import lombok.AllArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PathVariable;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 项目表 Service 实现类
 *
 * @author lkl
 * @version 2021-08-26
 */
@Service
@AllArgsConstructor
public class ComProjectServiceImpl extends BaseServiceImpl<ComProjectDAO, ComProjectQueryVO, ComProjectDTO, ComProject> implements ComProjectService {

    @Autowired
    private ComProjectDAO comProjectDAO;
    @Autowired
    private ComProjectMembersService comProjectMembersService;
    @Autowired
    private ComProjectCooperativeUnitsService comProjectCooperativeUnitsService;
    @Autowired
    private ComProjectResultsService comProjectResultsService;
    @Autowired
    private ComProjectBasicService comProjectBasicService;
    @Autowired
    private ComProjectStageGoalService comProjectStageGoalService;
    @Autowired
    private ComProjectFundCompositionService comProjectFundCompositionService;
    @Autowired
    private ComProjectBudgetService comProjectBudgetService;
    @Autowired
    private ComProjectEquipmentService comProjectEquipmentService;
    @Autowired
    private ComProjectManufactureService comProjectManufactureService;

    @Autowired
    private ComProjectResearchService comProjectResearchService;
    @Autowired
    private ComProjectSubService comProjectSubService;
    @Autowired
    private ComProjectManagementRuleService comProjectManagementRuleService;
    @Autowired
    private ComFileService ComFileService;
    @Autowired
    private ComPersonService comPersonService;
    @Autowired
    private ComUnitService comUnitService;
    @Autowired
    private ComProjectAuditService comProjectAuditService;
    @Autowired
    private ComProjectAuditNoteService comProjectAuditNoteService;
    @Autowired
    private ComBatchService comBatchService;
    @Autowired
    private SystemProperties properties;
    @Autowired
    private SystemParameterService systemParameterService;
    @Autowired
    private final ExcelUtils excelUtils;
    @Autowired
    private final HtmlBuilder htmlBuilder;
    @Autowired
    private final ComProjectFundPlanService comProjectFundPlanService;
    @Autowired
    private final ComProjectUnitPaymentService comProjectUnitPaymentService;
    @Autowired
    private ComProjectKpitService comProjectKpitService;
    @Autowired
    private ComProjectKpitDetailService comProjectKpitDetailService;

    @Override
    protected void setCriteriaForQuery(ComProjectQueryVO vo, QueryWrapper<ComProjectQueryVO> criteria) {
        if (Objects.nonNull(vo.getProjName())) {
            criteria.like("proj_name", vo.getProjName());
        }
        if (Objects.nonNull(vo.getProjNo())) {
            criteria.like("proj_no", vo.getProjNo());
        }
        if (Objects.nonNull(vo.getProjClass())) {
            criteria.eq("proj_class", vo.getProjClass());
        }
        if (Objects.nonNull(vo.getAppNo())) {
            criteria.eq("app_no", vo.getAppNo());
        }
        if (Objects.nonNull(vo.getVersionNo())) {
            criteria.eq("version_no", vo.getVersionNo());
        }
        if (Objects.nonNull(vo.getReportYear())) {
            criteria.eq("report_year", vo.getReportYear());
        }
        if (Objects.nonNull(vo.getBatch())) {
            criteria.eq("batch", vo.getBatch());
        }
        if (Objects.nonNull(vo.getProjState())) {
            switch (vo.getProjState()) {
                case 1:
                    criteria.in("proj_state",
                            CommonEnum.projState.draft.getCode(),
                            CommonEnum.projState.waitSubmit.getCode());
                    break;
                case 2:
                    criteria.eq("proj_state", CommonEnum.projState.returnModify.getCode());
                    break;
                case 3:
                    criteria.in("proj_state",
                            CommonEnum.projState.toAudit.getCode(),
                            CommonEnum.projState.failed.getCode(),
                            CommonEnum.projState.pass.getCode(),
                            CommonEnum.projState.report.getCode(),
                            CommonEnum.projState.conclusion.getCode());
                    break;
                case 4:
                    break;
                case 5:
                    criteria.ge("proj_state", CommonEnum.projState.pass.getCode());
                    break;
                case 6:
                    criteria.ge("proj_state", CommonEnum.projState.report.getCode());
                    break;
                default:
                    criteria.eq("proj_state", vo.getProjState());
                    break;
            }
        }
        if (Objects.nonNull(vo.getAppUnitId())) {
            criteria.eq("app_unit_id", vo.getAppUnitId());
        }
        if (Objects.nonNull(vo.getAppPersonId())) {
            criteria.eq("app_person_id", vo.getAppPersonId());
        }
        if (Objects.nonNull(vo.getStartDate())) {
            criteria.eq("start_date", vo.getStartDate());
        }
        if (Objects.nonNull(vo.getEndDate())) {
            criteria.eq("end_date", vo.getEndDate());
        }
        if (Objects.nonNull(vo.getProjContent())) {
            criteria.eq("proj_content", vo.getProjContent());
        }
        if (Objects.nonNull(vo.getResearchProjects())) {
            criteria.eq("research_projects", vo.getResearchProjects());
        }
        if (Objects.nonNull(vo.getKnowledgeId())) {
            criteria.eq("knowledge_id", vo.getKnowledgeId());
        }
        if (Objects.nonNull(vo.getProjKeywords())) {
            criteria.eq("proj_keywords", vo.getProjKeywords());
        }
        if (Objects.nonNull(vo.getProjBasis())) {
            criteria.eq("proj_basis", vo.getProjBasis());
        }
        if (Objects.nonNull(vo.getProjType())) {
            criteria.eq("proj_type", vo.getProjType());
        }
        if (Objects.nonNull(vo.getResearchContent())) {
            criteria.eq("research_content", vo.getResearchContent());
        }
        if (Objects.nonNull(vo.getResearchPlan())) {
            criteria.eq("research_plan", vo.getResearchPlan());
        }

        if (Objects.nonNull(vo.getMainFeatures())) {
            criteria.eq("main_features", vo.getMainFeatures());
        }
        if (Objects.nonNull(vo.getExpectedResults())) {
            criteria.eq("expected_results", vo.getExpectedResults());
        }

        if (Objects.nonNull(vo.getMemResume())) {
            criteria.eq("mem_resume", vo.getMemResume());
        }
        if (Objects.nonNull(vo.getProjDoc())) {
            criteria.eq("proj_doc", vo.getProjDoc());
        }

        if (Objects.nonNull(vo.getRemark())) {
            criteria.eq("remark", vo.getRemark());
        }
        if (Objects.nonNull(vo.getAppUnitName())) {
            criteria.like("unit_name", vo.getAppUnitName());
        }
        if (Objects.nonNull(vo.getAppPersonName())) {
            criteria.like("person_name", vo.getAppPersonName());
        }
    }

    @Override
    public Pagination<ComProjectDTO> getListByPage(ComProjectQueryVO vo) {
        QueryWrapper criteria = new QueryWrapper();
        setCriteriaForQuery(vo, criteria);
        Page<ComProjectQueryVO> page = new Page<>(vo.getPageIndex(), vo.getPageSize());
        List<ComProjectDTO> dtoList = comProjectDAO.getListByPage(page, criteria).getRecords();
        return new Pagination<>(dtoList, page.getTotal(), vo.getPageSize());
    }

    /**
     * 获取新的版本号
     *
     * @param oldVersionNo 原版本号
     * @return
     */
    public String getVersionNo(String oldVersionNo) {
        if (null != oldVersionNo) {
            String lastCode = oldVersionNo.substring(oldVersionNo.length() - 3, oldVersionNo.length());
            String appNo = oldVersionNo.substring(0, oldVersionNo.length() - 3);
            Integer index = Integer.parseInt(lastCode) + 1;
            String code = ("00" + index);
            return appNo + code.substring(code.length() - 3);
        }
        return "";
    }

    /**
     * 根据id获取项目信息
     */
    public ComProjectDTO getNewProject(Integer projType) {
        ComProjectDTO dto = new ComProjectDTO();
        if (Objects.isNull(projType)) {
            projType = CommonEnum.projType.num.getCode();
        }

        dto.setProjType(projType);
        //申报单位
        ComUnitDTO comUnitDTO = comUnitService.getUnitById(SecurityUserHolder.getUnitId());
        if (null != comUnitDTO) {
            dto.setAppUnitName(comUnitDTO.getUnitName());
//
//            dto.setOrganizationCode(comUnitDTO.getOrganizationCode());
//            dto.setRegisteredAddress(comUnitDTO.getRegisteredAddress());
//            dto.setPostCode(comUnitDTO.getPostCode());

            dto.setUnitLinkName(comUnitDTO.getLinkName());
            dto.setUnitLinkMobile(comUnitDTO.getTelephone());
            dto.setUnitLinkEmail(comUnitDTO.getEmail());
            dto.setUnitLinkFax(comUnitDTO.getFax());
            dto.setCompleteStatus("0,0,0,0,0,0");

//            dto.setLegalPerson(comUnitDTO.getLegalPerson());
//            dto.setWorkforce(comUnitDTO.getWorkforce());
//            dto.setSpecializedPersonnel(comUnitDTO.getSpecializedPersonnel());
//            dto.setResearchPersonnel(comUnitDTO.getResearchPersonnel());
//
//            dto.setDepositBank(comUnitDTO.getDepositBank());
//            dto.setBankAccount(comUnitDTO.getBankAccount());
//            dto.setDepositBankAddress(comUnitDTO.getDepositBankAddress());
//            dto.setInterbankNumber(comUnitDTO.getInterbankNumber());

        }

        // 申报人
        ComPersonDTO comPersonDTO = comPersonService.getPersonById(SecurityUserHolder.getPersonId());
        if (null != comPersonDTO) {
            loadPersonInfo(dto, comPersonDTO);
            dto.setAddress(comPersonDTO.getAddress());
            dto.setMainResearchAreas(comPersonDTO.getMainResearchAreas());
        }

        //经费表
        List<ComProjectBudgetDTO> budgetList = comProjectBudgetService.getList(projType);
        dto.setBudget(budgetList);
        //年度用款计划表
        List<ComProjectFundPlanDTO> fundPlanList = comProjectFundPlanService.getList();
        dto.setFundPlan(fundPlanList);
        // 项目绩效指标表
        NewProjectKPIInfo(dto);

        // 附件
        List<ComFileDTO> fileList = configureFileList(projType);
        dto.setFileList(fileList);

        dto.setReportYear(comBatchService.getReportYear(projType));
        dto.setProjState(CommonEnum.projState.draft.getCode());
        dto.setAppPersonId(SecurityUserHolder.getPersonId());
        dto.setAppUnitId(SecurityUserHolder.getUnitId());
        return dto;
    }

    private void NewProjectKPIInfo(ComProjectDTO dto) {
        List<ComProjectKpitDTO> ProjectKPIList = comProjectKpitService.getProjectKpitStatistic();
        ProjectKPIStatisticDTO kpiDTO = new ProjectKPIStatisticDTO();
        kpiDTO.setTotalRowSpan(ProjectKPIList.size() + 2);
        kpiDTO.setThreeLevel(ProjectKPIList);

        dto.setProjectKPI(kpiDTO);
    }

    /**
     * 根据id获取项目信息
     *
     * @param id 查询条件
     */
    public ComProjectDTO getProjectById(String id) {
        ComProjectDTO dto = comProjectDAO.getById(id);
        if (null == dto)
            throw new BusinessException("项目不存在或已删除！");
        // 申报人
        ComPersonDTO comPersonDTO = comPersonService.getPersonById(dto.getAppPersonId());
        if (null != comPersonDTO) {
            loadPersonInfo(dto, comPersonDTO);
        }
        //申报单位
        ComUnitDTO comUnitDTO = comUnitService.getUnitById(dto.getAppUnitId());
        if (null != comUnitDTO) {
            dto.setAppUnitName(comUnitDTO.getUnitName());
        }

        ComProjectMembersDTO comProjectMembersDTO = comProjectMembersService.getMemCountById(id);
        dto.setMemCount(comProjectMembersDTO.getMemCount());
        dto.setMemHighCount(comProjectMembersDTO.getMemHighCount());
        dto.setMemMiddleCount(comProjectMembersDTO.getMemMiddleCount());
        dto.setMemLowCount(comProjectMembersDTO.getMemLowCount());
        dto.setMemBshCount(comProjectMembersDTO.getMemBshCount());
        dto.setMemBsCount(comProjectMembersDTO.getMemBsCount());
        dto.setMemSsCount(comProjectMembersDTO.getMemSsCount());
        dto.setMemXsCount(comProjectMembersDTO.getMemXsCount());
        dto.setWorkCount(comProjectMembersDTO.getWorkCount());

        //获取项目组成员
        List<ComProjectMembersDTO> memList = comProjectMembersService.getListByObjectId(dto.getId());
        dto.setMembers(memList);

        // 项目绩效目标表
        LoadProjectKPIInfo(dto);

//        // 项目合作单位
//        List<ComProjectCooperativeUnitsDTO> cooperativeUnits = comProjectCooperativeUnitsService.getListByObjectId(dto.getId(), 1);
//        dto.setCooperativeUnits(cooperativeUnits);

        // 项目参与单位
        List<ComProjectCooperativeUnitsDTO> participateUnits = comProjectCooperativeUnitsService.getListByObjectId(dto.getId(), 2);
        dto.setParticipateUnits(participateUnits);

        //经费表
        List<ComProjectBudgetDTO> budgetList = comProjectBudgetService.getListByObjectId(dto.getId());
        if (null == budgetList || budgetList.size() == 0)
            budgetList = comProjectBudgetService.getList(dto.getProjType());
        dto.setBudget(budgetList);

        // 年度用款计划
        List<ComProjectFundPlanDTO> fundPlanList = comProjectFundPlanService.getListByObjectId(dto.getId());
        if (null == fundPlanList || fundPlanList.size() == 0)
            fundPlanList = comProjectFundPlanService.getList();
        dto.setFundPlan(fundPlanList);

        // 购置设备预算明细表
        List<ComProjectEquipmentDTO> equipmentList = comProjectEquipmentService.getListByObjectId(dto.getId());
        dto.setDeviceList(equipmentList);

        // 试制设备预算明细表
        List<ComProjectManufactureDTO> manufactureList = comProjectManufactureService.getListByObjectId(dto.getId());
        dto.setManufactureList(manufactureList);

        // 单位支出明细预算
        List<ComProjectUnitPaymentDTO> unitPaymentList = comProjectUnitPaymentService.getListByObjectId(dto.getId());
        dto.setUnitPayment(unitPaymentList);

        // 项目安排及阶段目标
        List<ComProjectStageGoalDTO> stageGoals = comProjectStageGoalService.getListByObjectId(id);
        dto.setStageGoals(stageGoals);

        // 项目课颖设置表
        List<ComProjectSubDTO> projectSubList = comProjectSubService.getListByObjectId(dto.getId());
        dto.setProjectSubList(projectSubList);

//        // 在研或完成基础研究项目情况
//        List<ComProjectResearchDTO> projectResearchList = comProjectResearchService.getListByObjectId(dto.getId());
//        dto.setProjectResearchList(projectResearchList);

//        // 单位科研项目及资金管理制度表
//        List<ComProjectManagementRuleDTO> managementRuleList = comProjectManagementRuleService.getListByObjectId(dto.getId());
//        dto.setManagementRuleList(managementRuleList);

        //附件列表
        List<ComFileDTO> fileList = ComFileService.getListByObjectId(dto.getId(), CommonEnum.fileType.project.getCode());
        if (null == fileList || fileList.size() == 0)
            fileList = configureFileList(dto.getProjType());
        else
            fileList = checkNecessaryAttachmentFile(dto.getProjType(), fileList);
        dto.setFileList(fileList);

        //审核记录列表
        List<ComProjectAuditNoteDTO> auditList = comProjectAuditNoteService.getListByObjectId(dto.getId());
        dto.setAuditList(auditList);
        return dto;
    }

    private void LoadProjectKPIInfo(ComProjectDTO dto) {
        List<ComProjectKpitDTO> ProjectKPIList = comProjectKpitDetailService.getProjectKpitDetailStatistic(dto.getId());
        if (null == ProjectKPIList || ProjectKPIList.size() == 0)
            ProjectKPIList = comProjectKpitService.getProjectKpitStatistic();
        ProjectKPIStatisticDTO kpiDTO = new ProjectKPIStatisticDTO();
        kpiDTO.setTotalRowSpan(ProjectKPIList.size() + 2);
        kpiDTO.setThreeLevel(ProjectKPIList);

        kpiDTO.setReportYear(dto.getReportYear());
        kpiDTO.setProjName(dto.getProjName());
        kpiDTO.setAppUnitName(dto.getAppUnitName());
        kpiDTO.setManagerDept(dto.getManagerDept());
        kpiDTO.setProjAttribute(dto.getProjAttribute());
        kpiDTO.setYearTarget(dto.getYearTarget());
        kpiDTO.setYear1Goal(dto.getYear1Goal());
        kpiDTO.setYear2Goal(dto.getYear2Goal());
        kpiDTO.setYear3Goal(dto.getYear3Goal());
        if (Objects.nonNull(dto.getStartDate()) && Objects.nonNull(dto.getEndDate())) {
            kpiDTO.setStartDate(dto.getStartDate());
            kpiDTO.setEndDate(dto.getEndDate());
            kpiDTO.setProjDeadline(DateUtils.FormatDate(dto.getStartDate()) + "至" + DateUtils.FormatDate(dto.getEndDate()));
        }
        List<ComProjectBudgetDTO> budgetDTO = dto.getBudget();
        if (null != budgetDTO) {
            // 资金总额
            List<ComProjectBudgetDTO> FindList = budgetDTO.stream().filter(e -> e.getBudgetId().equals("3b1f57d3-6aec-4129-aef5-702a1accfe01")).collect(Collectors.toList());
            if (null != FindList)
                kpiDTO.setTotalBudget(FindList.get(0).getTotalBudget());
            // 省级财政资金
            FindList = budgetDTO.stream().filter(e -> e.getBudgetId().equals("3b1f57d3-6aec-4129-aef5-702a1accfe02")).collect(Collectors.toList());
            if (null != FindList)
                kpiDTO.setApplyFunds(FindList.get(0).getTotalBudget());
            // 自筹资金
            FindList = budgetDTO.stream().filter(e -> e.getBudgetId().equals("3b1f57d3-6aec-4129-aef5-702a1accfe03")).collect(Collectors.toList());
            if (null != FindList)
                kpiDTO.setSelfFunds(FindList.get(0).getTotalBudget());
        } else {
            kpiDTO.setTotalBudget(new BigDecimal(0.00));
            kpiDTO.setApplyFunds(new BigDecimal(0.00));
            kpiDTO.setSelfFunds(new BigDecimal(0.00));
        }

        List<ComProjectFundPlanDTO> fundPlanDTO = dto.getFundPlan();
        if (null != fundPlanDTO) {
            List<ComProjectFundPlanDTO> FindList = fundPlanDTO.stream().filter(e -> e.getFundId().equals("6a18820d-ad2b-11ef-b6cb-0c42a1380f01")).collect(Collectors.toList());
            if (null != FindList)
                kpiDTO.setYearTotal(FindList.get(0).getYearValue1());
            FindList = fundPlanDTO.stream().filter(e -> e.getFundId().equals("6a18820d-ad2b-11ef-b6cb-0c42a1380f02")).collect(Collectors.toList());
            if (null != FindList)
                kpiDTO.setYearApply(FindList.get(0).getYearValue1());
            FindList = fundPlanDTO.stream().filter(e -> e.getFundId().equals("6a18820d-ad2b-11ef-b6cb-0c42a1380f03")).collect(Collectors.toList());
            if (null != FindList)
                kpiDTO.setYearSelf(FindList.get(0).getYearValue1());
        } else {
            kpiDTO.setYearTotal(new BigDecimal(0.00));
            kpiDTO.setYearApply(new BigDecimal(0.00));
            kpiDTO.setYearSelf(new BigDecimal(0.00));
        }

        dto.setProjectKPI(kpiDTO);
    }

    private List<ComFileDTO> configureFileList(Integer projType) {
        List<ComFileDTO> fileList = new ArrayList<>();
        List<SystemParameter> parameterList;
        //健康领域科技项目
        if (projType == CommonEnum.projType.num.getCode())
            parameterList = systemParameterService.getListByType(61);
        else//临床科技项目
            parameterList = systemParameterService.getListByType(13);
        parameterList.forEach(e -> {
            fileList.add(configureFile(e.getName(), e.getDisplayOrder(), e.getIsRequired()));
        });
        return fileList;
    }

    private ComFileDTO configureFile(String FileExplain, int showIndex, Boolean isRequired) {
        ComFileDTO file = new ComFileDTO();
        file.setFileType(CommonEnum.fileType.project.getCode());
        file.setFileExplain(FileExplain);
        file.setShowIndex(showIndex);
        file.setRequired(true);
        if (!isRequired.equals(null))
            file.setIsRequired(isRequired);
        else
            file.setIsRequired(false);
        return file;
    }

    public List<ComFileDTO> checkNecessaryAttachmentFile(Integer projType, List<ComFileDTO> fileList) {
        List<SystemParameter> parameterList;
        //健康领域科技项目
        if (projType == CommonEnum.projType.num.getCode())
            parameterList = systemParameterService.getListByType(61);
        else//临床科技项目
            parameterList = systemParameterService.getListByType(13);

        AtomicInteger allCount = new AtomicInteger(parameterList.size() + 1);
        fileList.forEach(e -> {
            AtomicInteger num = new AtomicInteger(1);
            int i = num.get();
            parameterList.forEach(p -> {
                if (null != e.getFileExplain() && e.getFileExplain().equals(p.getName())) {
                    e.setShowIndex(p.getDisplayOrder());
                    e.setRequired(true);
                    num.incrementAndGet();
                }
            });
            if (i == num.get()) {
                e.setShowIndex(allCount.get());
                e.setRequired(false);
                allCount.incrementAndGet();
            }
        });

        parameterList.forEach(p -> {
            List<ComFileDTO> findList = fileList.stream().filter(e -> null != e.getFileExplain() && e.getFileExplain().equals(p.getName())).collect(Collectors.toList());
            if (findList.size() == 0) {
                ComFileDTO fileDTO = configureFile(p.getName(), p.getDisplayOrder(), p.getIsRequired());
                fileList.add(fileDTO);
            }
        });

        fileList.sort(Comparator.comparingInt(ComFileDTO::getShowIndex));

        return fileList;
    }


    private void loadPersonInfo(ComProjectDTO dto, ComPersonDTO comPersonDTO) {
        dto.setAppPersonName(comPersonDTO.getPersonName());
        dto.setSex(comPersonDTO.getSex());
        dto.setBirthday(comPersonDTO.getBirthday());
        dto.setNationName(comPersonDTO.getNationName());
        dto.setDegreeName(comPersonDTO.getDegreeName());
        dto.setTitleName(comPersonDTO.getTitleName());
        dto.setDutyName(comPersonDTO.getDuty());
        dto.setSpecName(comPersonDTO.getSpecName());
        dto.setMobile(comPersonDTO.getMobile());
        dto.setEmail(comPersonDTO.getEmail());
    }

    /**
     * 更新项目状态
     *
     * @return
     */
    public void updateStateOrNo(String id, Integer state, String versionNo) {
        ComProject comProject = new ComProject();
        comProject.setId(id);
        comProject.setProjState(state);
        comProject.setVersionNo(versionNo);
        this.update(comProject);
    }


    public String updateUnit(ComProjectDTO dto) {
        if (Objects.isNull(dto.getAppUnitId()))
            throw new BusinessException("修改失败，请检查!");
        ComProject comProject = new ComProject();
        comProject.setId(dto.getId());
        comProject.setAppUnitId(dto.getAppUnitId());
        return this.update(comProject);
    }

    public void report(ComProjectAudit model, String unitId, String treeCode) {
        ComProject comProject = this.entityById(model.getAuditObjectId());
        if (null == comProject)
            throw new BusinessException("项目不存在或已删除！");
        if (!comProject.getProjState().equals(CommonEnum.projState.waitSubmit.getCode()) && !comProject.getProjState().equals(CommonEnum.projState.returnModify.getCode()))
            throw new BusinessException("项目已上报！");
        comProjectAuditService.report(comProject.getReportYear(), model.getAuditObjectId(), model.getAuditType(), unitId, treeCode);
        String versionNo = "";
        if (null == comProject.getVersionNo())
            versionNo = comProject.getAppNo() + "001";
        else
            versionNo = this.getVersionNo(comProject.getVersionNo());
        // 更新项目状态
        this.updateStateOrNo(model.getAuditObjectId(), CommonEnum.projState.toAudit.getCode(), versionNo);
    }

    @Transactional
    public void audit(ComProjectAudit report, String auditUnitId, String auditTreeCode) {
        if (Objects.isNull(report.getAuditObjectId()))
            throw new BusinessException("参数缺失！");
        ComProject model = this.getById(report.getAuditObjectId());
        if (null == model)
            throw new BusinessException("审核对象不存在！");
        ComUnit appUnit = comUnitService.getById(model.getAppUnitId());
        if (null == appUnit)
            throw new BusinessException("申报单位不存在,或已删除！");
        //  返回上级或下级单位Id, 最高级或个人返回 null
        String unitId = comProjectAuditService.audit(report, appUnit.getTreeCode(), auditTreeCode);

        // 处理项目状态
        Integer projState = null;
        if (report.getAuditResult().equals(CommonEnum.auditResult.pass.getCode())) {
            if (unitId == null)
                projState = CommonEnum.projState.pass.getCode();
        } else if (report.getAuditResult().equals(CommonEnum.auditResult.returnModify.getCode())) {
            if (unitId == null)
                projState = CommonEnum.projState.returnModify.getCode();
        } else {
            projState = CommonEnum.projState.failed.getCode();
        }
        if (null != projState)
            this.updateStateOrNo(report.getAuditObjectId(), projState, null);
    }

    public DataStatisticsDTO getCount(ComProject e) {
        QueryWrapper criteria = new QueryWrapper();
        this.notNullField(e, criteria);
        return comProjectDAO.getCount(criteria);
    }

    @Transactional
    public String delete(String id) {
        ComProject comProject = this.entityById(id);
        if (null == comProject)
            throw new BusinessException("项目不存在");
        if (comProject.getProjState() > CommonEnum.projState.waitSubmit.getCode())
            throw new BusinessException("当前项目状态不能删除");
        // 项目参加人员
        comProjectMembersService.deleteByObjectId(id);
        // 项目绩效指标表
        comProjectKpitDetailService.deleteByObjectId(id);
        // 经费预算
        comProjectBudgetService.deleteByObjectId(id);
        // 年度用款计划表
        comProjectFundPlanService.deleteByObjectId(id);
        // 项目合作单位
        comProjectCooperativeUnitsService.deleteByObjectId(id, 1);
        // 主要参与单位
        comProjectCooperativeUnitsService.deleteByObjectId(id, 2);
        // 购置设备预算明细表
        comProjectEquipmentService.deleteByObjectId(id);
        // 试制设备预算明细表
        comProjectManufactureService.deleteByObjectId(id);
        // 单位支出明细预算表
        comProjectUnitPaymentService.deleteByObjectId(id);
        // 项目安排及阶段目标
        comProjectStageGoalService.deleteByObjectId(id);
        // 项目课颖设置表
        comProjectSubService.deleteByObjectId(id);
        // 附件
        ComFileService.deleteByObjectId(id);
        // 项目信息表
        comProjectBasicService.deleteByProjId(id);
        this.deleteById(id);
        return id;
    }

    public void updateAssignState(String id, Integer assignState, Integer completed, BigDecimal totalScore, BigDecimal averageScore) {
        ComProject comProject = new ComProject();
        comProject.setId(id);
        comProject.setAssignState(assignState);
        comProject.setCompleted(completed);
        comProject.setTotalScore(totalScore);
        comProject.setAverageScore(averageScore);
        this.update(comProject);
    }

    @Transactional
    public String save(ComProjectDTO dto) {
        dto.setFileId(dto.getDownloadId());
        if (Objects.nonNull(dto.getGovFunding())) {
            if (dto.getGovFunding().compareTo(new BigDecimal(50)) > -1) {
                dto.setProjClass(2);
            } else {
                dto.setProjClass(1);
            }
        }
        if (Objects.isNull(dto.getId()))
            dto.setId(projectInsert(dto));
        else {
            ComProject project = this.entityById(dto.getId());
            if (null == project) {
                dto.setId(projectInsert(dto));
            } else
                projectUpdate(dto);
        }
        return dto.getId();
    }

    public String saveByStep(ComProjectDTO dto) {
        String ProjectID = "";
        switch (dto.getStep()) {
            case 0://项目基本信息
                ProjectID = ProjectSaveStep0(dto);
                break;
            case 1://项目组成员及单位
                ProjectID = ProjectSaveStep1(dto);
                break;
            case 2://经费预算及设备明细
                ProjectID = ProjectSaveStep2(dto);
                break;
            case 3://阶段目标及课题设置
                ProjectID = ProjectSaveStep3(dto);
                break;
            case 4://绩效指标
                ProjectID = ProjectSaveStep4(dto);
                break;
            case 5://附件
                ProjectID = ProjectSaveStep5(dto);
                break;
        }

        return ProjectID;
    }

    private String ProjectSaveStep0(ComProjectDTO dto) {
        String ProjectID = "";
        dto.setFileId(dto.getDownloadId());
        if (Objects.isNull(dto.getId()))
            ProjectID = InsertProjectBaseInfo(dto);
        else {
            ComProject project = this.entityById(dto.getId());
            if (null == project) {
                ProjectID = InsertProjectBaseInfo(dto);
            } else
                ProjectID = UpdateProjectBaseInfo(dto);
        }

        return ProjectID;
    }

    @Transactional
    public String ProjectSaveStep1(ComProjectDTO dto) {
        ComProject comProject = convert2Entity(dto);
        this.update(comProject);

        // 项目参加人员
        comProjectMembersService.insertList(dto.getMembers(), dto.getId());
        // 主要参与单位
        comProjectCooperativeUnitsService.insertList(dto.getParticipateUnits(), dto.getId(), 2);

        return dto.getId();
    }

    @Transactional
    public String ProjectSaveStep2(ComProjectDTO dto) {
        if (Objects.nonNull(dto.getGovFunding())) {
            if (dto.getGovFunding().compareTo(new BigDecimal(50)) > -1) {
                dto.setProjClass(2);
            } else {
                dto.setProjClass(1);
            }
        }
        ComProject comProject = convert2Entity(dto);
        this.update(comProject);

        comProjectBasicService.insertOrUpdate(dto);

        // 经费预算
        comProjectBudgetService.insertBudgetList(dto.getBudget(), dto.getId());
        // 年度用款计划表
        comProjectFundPlanService.insertList(dto.getFundPlan(), dto.getId());

        if (null != dto.getDeviceList() && dto.getDeviceList().size() > 0) {
            // 购置设备预算明细表
            comProjectEquipmentService.insertEquipmentList(dto.getDeviceList(), dto.getId());
        }
        if (null != dto.getManufactureList() && dto.getManufactureList().size() > 0) {
            // 试制设备预算明细表
            comProjectManufactureService.insertEquipmentList(dto.getManufactureList(), dto.getId());
        }
        if (null != dto.getUnitPayment() && dto.getUnitPayment().size() > 0) {
            // 单位支出明细预算表
            comProjectUnitPaymentService.insertList(dto.getUnitPayment(), dto.getId());
        }

        return dto.getId();
    }

    @Transactional
    public String ProjectSaveStep3(ComProjectDTO dto) {
        ComProject comProject = convert2Entity(dto);
        this.update(comProject);

        // 项目安排及阶段目标
        comProjectStageGoalService.insertList(dto.getStageGoals(), dto.getId());

        if (null != dto.getProjectSubList() && dto.getProjectSubList().size() > 0) {
            // 项目课颖设置表
            comProjectSubService.insertList(dto.getProjectSubList(), dto.getId());
        }

        return dto.getId();
    }

    @Transactional
    public String ProjectSaveStep4(ComProjectDTO dto) {
        ComProject comProject = new ComProject();
        comProject.setId(dto.getId());
        comProject.setCompleteStatus(dto.getCompleteStatus());
        if (Objects.nonNull(dto.getManagerDept()))
            comProject.setManagerDept(dto.getManagerDept());

        this.update(comProject);

        ComProjectBasic comProjectBasic = new ComProjectBasic();
        comProjectBasic.setProjId(dto.getId());
        if (Objects.nonNull(dto.getProjAttribute()))
            comProjectBasic.setProjAttribute(dto.getProjAttribute());
        else
            comProjectBasic.setProjAttribute("5b9d6509-aece-11ef-b6cb-0c42a1380f01");//新增项目

        if (Objects.nonNull(dto.getYearTarget()))
            comProjectBasic.setYearTarget(dto.getYearTarget());
        if (Objects.nonNull(dto.getYear1Goal()))
            comProjectBasic.setYear1Goal(dto.getYear1Goal());
        if (Objects.nonNull(dto.getYear2Goal()))
            comProjectBasic.setYear2Goal(dto.getYear2Goal());
        if (Objects.nonNull(dto.getYear3Goal()))
            comProjectBasic.setYear3Goal(dto.getYear3Goal());

        comProjectBasicService.insertOrUpdate(dto);

        if (null != dto.getProjectKPI().getKpiList() && dto.getProjectKPI().getKpiList().size() > 0) {
            // 项目绩效指标表
            comProjectKpitDetailService.insertList(dto.getProjectKPI().getKpiList(), dto.getId());
        }

        return dto.getId();
    }

    @Transactional
    public String ProjectSaveStep5(ComProjectDTO dto) {
        ComProject comProject = convert2Entity(dto);
        this.update(comProject);

        // 附件
        ComFileService.insertList(dto.getFileList(), dto.getId(), CommonEnum.fileType.project.getCode());

        return dto.getId();
    }

    private String InsertProjectBaseInfo(ComProjectDTO dto) {
        ComBatchDTO comBatchDTO = comBatchService.getCurrentYearBatchByType(dto.getProjType());
        ComProject comProject = convert2Entity(dto);
        comProject.setAppNo(getAppNo());
        comProject.setReportYear(comBatchDTO.getYear());
        comProject.setBatch(comBatchDTO.getBatch());
        dto.setSubjectScope("生物医药领域");
        comProject.setCompleted(0);
        comProject.setAssignState(0);
        String id = this.insert(comProject);
        dto.setId(id);
        comProjectBasicService.insertOrUpdate(dto);
        return id;
    }

    private String UpdateProjectBaseInfo(ComProjectDTO dto) {
        ComProject project = this.entityById(dto.getId());
        if (null == project)
            throw new BusinessException("项目不存在或已删除");
        if (!StringUtil.isContainsRole(SecurityUserHolder.getRoles(), CommonEnum.systemRole.sys.getCode().toString())
                && !StringUtil.isContainsRole(SecurityUserHolder.getRoles(), CommonEnum.systemRole.topGov.getCode().toString())
                && !project.getProjState().equals(CommonEnum.projState.draft.getCode())
                && !project.getProjState().equals(CommonEnum.projState.waitSubmit.getCode())
                && !project.getProjState().equals(CommonEnum.projState.returnModify.getCode()))
            throw new BusinessException("项目已上报！");
        ComProject comProject = convert2Entity(dto);
        comProjectBasicService.insertOrUpdate(dto);
        return this.update(comProject);
    }


    @Transactional
    //插入
    public String projectInsert(ComProjectDTO dto) {
        ComBatchDTO comBatchDTO = comBatchService.getCurrentYearBatchByType(dto.getProjType());
        ComProject comProject = convert2Entity(dto);
        comProject.setAppNo(getAppNo());
        comProject.setReportYear(comBatchDTO.getYear());
        comProject.setBatch(comBatchDTO.getBatch());
        dto.setSubjectScope("生物医药领域");
        comProject.setCompleted(0);
        comProject.setAssignState(0);
        String id = this.insert(comProject);
        dto.setId(id);
        this.saveList(dto, id);
        comProjectBasicService.insertOrUpdate(dto);
        return id;
    }

    @Transactional
    //更新
    public String projectUpdate(ComProjectDTO dto) {
        ComProject project = this.entityById(dto.getId());
        if (null == project)
            throw new BusinessException("项目不存在或已删除");
        if (!StringUtil.isContainsRole(SecurityUserHolder.getRoles(), CommonEnum.systemRole.sys.getCode().toString())
                && !StringUtil.isContainsRole(SecurityUserHolder.getRoles(), CommonEnum.systemRole.topGov.getCode().toString())
                && !project.getProjState().equals(CommonEnum.projState.draft.getCode())
                && !project.getProjState().equals(CommonEnum.projState.waitSubmit.getCode())
                && !project.getProjState().equals(CommonEnum.projState.returnModify.getCode()))
            throw new BusinessException("项目已上报！");
        ComProject comProject = convert2Entity(dto);
        this.saveList(dto, dto.getId());
        comProjectBasicService.insertOrUpdate(dto);
        return this.update(comProject);
    }

    @Transactional
    public void saveList(ComProjectDTO dto, String id) {
        // 项目参加人员
        comProjectMembersService.insertList(dto.getMembers(), id);
        // 项目绩效指标表
        comProjectKpitDetailService.insertList(dto.getProjectKPI().getKpiList(), id);
        // 经费预算
        comProjectBudgetService.insertBudgetList(dto.getBudget(), id);
        // 年度用款计划表
        comProjectFundPlanService.insertList(dto.getFundPlan(), id);
//        // 项目合作单位
//        comProjectCooperativeUnitsService.insertList(dto.getCooperativeUnits(), id, 1);
        // 主要参与单位
        comProjectCooperativeUnitsService.insertList(dto.getParticipateUnits(), id, 2);
        // 购置设备预算明细表
        comProjectEquipmentService.insertEquipmentList(dto.getDeviceList(), id);
        // 试制设备预算明细表
        comProjectManufactureService.insertEquipmentList(dto.getManufactureList(), id);
        // 单位支出明细预算表
        comProjectUnitPaymentService.insertList(dto.getUnitPayment(), id);
        // 项目安排及阶段目标
        comProjectStageGoalService.insertList(dto.getStageGoals(), id);
        // 项目课颖设置表
        comProjectSubService.insertList(dto.getProjectSubList(), id);
        // 附件
        ComFileService.insertList(dto.getFileList(), id, CommonEnum.fileType.project.getCode());
        // 项目经费构成表
//        comProjectFundCompositionService.insertList(dto.getFundCompositions(), id);
        // 在研或完成基础研究项目情况
//        comProjectResearchService.insertList(dto.getProjectResearchList(), id);
        // 单位科研项目及资金管理制度表
//        comProjectManagementRuleService.insertList(dto.getManagementRuleList(), id);
        // 成果形式
//        comProjectResultsService.insertList(dto.getResults(), id);
    }


    public void export(@PathVariable String id, HttpServletRequest request, HttpServletResponse response) {
        ComProjectDTO p = this.getProjectById(id);
        if (null != p) {
            String strDateFormat = p.getProjType().equals(1) ? "yyyy-MM-dd HH:mm:ss" : "yyyy-MM-dd";
            SimpleDateFormat sdf = new SimpleDateFormat(strDateFormat);
            if (null != p.getStartDate())
                p.setStartDateStr(sdf.format(p.getStartDate()));
            if (null != p.getEndDate())
                p.setEndDateStr(sdf.format(p.getEndDate()));
            p.getMembers().forEach((e) -> {
//              e.setAge(IDCardUtil.getAge(e.getCertId()));
                e.setSex(IDCardUtil.getSex(e.getCertId()));
            });

            final String[] unit = {""};
            p.getCooperativeUnits().forEach(e -> {
                if (Objects.nonNull(e.getUnitName())) {
                    unit[0] = unit[0] + " " + e.getUnitName();
                }
            });

            if (null == p.getCooperativeUnits() || p.getCooperativeUnits().size() < 3) {
                int count = p.getCooperativeUnits() == null ? 0 : p.getCooperativeUnits().size();
                List<ComProjectCooperativeUnitsDTO> item = p.getCooperativeUnits() == null ? new ArrayList<>() : p.getCooperativeUnits();
                for (int i = 1; i <= 3 - count; i++) {
                    item.add(new ComProjectCooperativeUnitsDTO());
                }
                p.setCooperativeUnits(item);
            }

            if (null == p.getMembers() || p.getMembers().size() < 6) {
                int count = p.getMembers() == null ? 0 : p.getMembers().size();
                List<ComProjectMembersDTO> item = p.getMembers() == null ? new ArrayList<>() : p.getMembers();
                for (int i = 1; i <= 6 - count; i++) {
                    item.add(new ComProjectMembersDTO());
                }
                p.setMembers(item);
            }
            if (null == p.getBudget() || p.getBudget().size() < 13) {
                int count = p.getBudget() == null ? 0 : p.getBudget().size();
                List<ComProjectBudgetDTO> item = p.getBudget() == null ? new ArrayList<>() : p.getBudget();
                for (int i = 1; i <= 13 - count; i++) {
                    item.add(new ComProjectBudgetDTO());
                }
                p.setBudget(item);
            }
//            if (null == p.getEquipments() || p.getEquipments().size() < 4) {
//                int count = p.getEquipments() == null ? 0 : p.getEquipments().size();
//                List<ComProjectEquipmentDTO> item = p.getEquipments() == null ? new ArrayList<>() : p.getEquipments();
//                for (int i = 1; i <= 4 - count; i++) {
//                    item.add(new ComProjectEquipmentDTO());
//                }
//                p.setEquipments(item);
//            }
            List<String> str = comProjectResultsService.getNameByObjectId(p.getId());
            if (p.getProjType().equals(1)) {
                WordUtils utl = new WordUtils();
                utl.export(p, response, "word.ftl");
            } else {
                htmlBuilder.exportWord(p, request, response);
            }
        }
    }

    /**
     * 获取项目编号
     *
     * @param year 项目申报年度
     * @param code 学科代码
     * @return
     */
    private String getProjectNo(int year, String code) {
        return year + code + comProjectDAO.getProjectNo(year + code);
    }

    /**
     * 获取申请编号
     *
     * @return
     */
    private String getAppNo() {
        Date nowTime = new Date();
        SimpleDateFormat date = new SimpleDateFormat("yyyyMMddHHmmss");
        return date.format(nowTime);
    }

    public DataStatisticsDTO getProjectReportCountByGov(String treeCode) {
        return comProjectDAO.getProjectReportCountByGov(treeCode);
    }

    public DataStatisticsDTO getProjectReportCountByUnitId(String appUnitId) {
        return comProjectDAO.getProjectReportCountByUnitId(appUnitId);
    }

    public List<ProjectImportDTO> projectImport(List<ProjectImportDTO> list) throws IOException {
//        //职称
//        List<SystemParameter> titleList = systemParameterService.getListByType(7);
//        //专业学科
//        List<SystemParameter> specList = systemParameterService.getListByType(57);
//        //预期成果形式
//        List<SystemParameter> anticipatedList = systemParameterService.getListByType(53);
//        for (ProjectImportDTO e : list) {
//            String error = "";
//            if (Objects.isNull(e.getPersonCode()) || e.getPersonCode().equals("")) {
//                error = error + "；申报人编码为空";
//            }
//            if (Objects.isNull(e.getAppUnitName()) || e.getAppUnitName().equals("")) {
//                error = error + "；申报单位为空";
//            }
//            if (Objects.isNull(e.getPersonName()) || e.getPersonName().equals("")) {
//                error = error + "；申报人姓名为空";
//            }
//            if (Objects.isNull(e.getProjNo()) || e.getProjNo().equals("")) {
//                error = error + "；项目编号为空";
//            }
//            if (Objects.isNull(e.getProjName()) || e.getProjName().equals("")) {
//                error = error + "；项目名称为空";
//            }
//            if (Objects.nonNull(error) && !error.equals("")) {
//                e.setRemark(error);
//                e.setImportState("失败");
//                continue;
//            }
//            try {
//                ComUnit comUnit = comUnitService.isExist(e.getAppUnitName());
//                if (null == comUnit) {
//                    comUnit = new ComUnit();
//                    comUnit.setUnitName(e.getAppUnitName());
//                    comUnit.setTreeCode(comUnitService.getNewCode("00052"));
//                    comUnit.setUnitState(CommonEnum.unitState.normal.getCode());
//                    comUnit.setRemark("导入");
//                    comUnitService.insert(comUnit);
//                }
//                SystemUser systemUser = systemUserService.getByCode(e.getPersonCode());
//                if (null == systemUser) {
//                    ComPerson comPerson = new ComPerson();
//                    comPerson.setPersonName(e.getPersonName());
//                    comPerson.setCertId(String.valueOf(UUID.randomUUID()));
//                    comPerson.setMobile(e.getMobile());
//                    comPerson.setUnitId(comUnit != null ? comUnit.getId() : null);
//                    comPerson.setPersonState(1);
//                    comPerson.setRemark("导入");
//                    String personId = comPersonService.insert(comPerson);
//
//                    ComApplicant comApplicant = new ComApplicant();
//                    comApplicant.setPersonId(personId);
//                    comApplicant.setState(1);
//                    comApplicant.setRemark("导入");
//                    comApplicantService.insert(comApplicant);
//
//                    systemUser = new SystemUser();
//                    systemUser.setPersonId(personId);
//                    systemUser.setPersonCode(e.getPersonCode());
//                    systemUser.setUnit(comUnit != null ? comUnit.getId() : null);
//                    systemUser.setUsername(e.getPersonCode());
//                    systemUser.setPassword("123456");
//                    systemUser.setNoteState(1);
//                    systemUser.setRemark("导入");
//                    systemUserService.insert(systemUser);
//                }
//
//                ComProject comProject = new ComProject();
//                comProject.setCreated(e.getCreated());
//                comProject.setProjNo(e.getProjNo());
//                comProject.setProjName(e.getProjName());
//                comProject.setAppPersonId(systemUser.getPersonId());
//                comProject.setAppUnitId(comUnit.getId());
//                comProject.setAverageScore(e.getAverageScore());
//                if (null != e.getKnowledgeName() && !e.getKnowledgeName().equals("")) {
//                    List<SystemParameter> findList2 = specList.stream().filter(p -> e.getKnowledgeName().equals(p.getName())).collect(Collectors.toList());
//                    if (findList2.size() > 0)
//                        comProject.setKnowledgeId(findList2.stream().findFirst().get().getId());
//                }
//                comProject.setApplyMoney(e.getApplyMoney());
//                if (null != e.getAnticipatedName() && !e.getAnticipatedName().equals("")) {
//                    List<SystemParameter> findList2 = anticipatedList.stream().filter(p -> e.getAnticipatedName().equals(p.getName())).collect(Collectors.toList());
//                    if (findList2.size() > 0)
//                        comProject.setAnticipatedForms(findList2.stream().findFirst().get().getId());
//                }
//                comProject.setProjName(e.getProjName());
//                comProject.setProjKeywords(e.getProjKeywords());
//                comProject.setKeywordsEnglish(e.getKeywordsEnglish());
//                comProject.setProjContent(e.getProjContent());
//                comProject.setStartDate(e.getStartDate());
//                comProject.setEndDate(e.getEndDate());
//
//                comProject.setEnglishName(e.getEnglishName());
//                comProject.setAddress(e.getAppUnitAddress());
//                comProject.setTelephone(e.getTelephone());
//
//                comProject.setReportYear(e.getReportYear());
//
//                comProject.setProjState(50);
//                comProject.setProjType(1);
//                comProject.setAppNo(e.getProjStateName());
//
//                comProject.setBatch(1);
//
//                this.insert(comProject);
//                e.setRemark("导入");
//                e.setImportState("成功");
//            } catch (
//                    Exception x) {
//                e.setImportState("失败");
//                e.setRemark(x.getMessage());
//            }
//        }
//        excelUtils.writeExcel2(list);
        return list;
    }

    public ComProjectDTO getProjectBasicInfoById(String id) {
        ComProjectDTO dto = comProjectDAO.getById(id);
        if (null == dto)
            throw new BusinessException("项目不存在或已删除！");
        // 申报人
        ComPersonDTO comPersonDTO = comPersonService.getPersonById(dto.getAppPersonId());
        if (null != comPersonDTO) {
            loadPersonInfo(dto, comPersonDTO);
        }

        return dto;
    }
}