package com.jeeplus.assess.projectRecords.controller;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.jeeplus.aop.demo.annotation.DemoMode;
import com.jeeplus.assess.projectRecords.Utils.EasyPoiUtil;
import com.jeeplus.common.TokenProvider;
import com.jeeplus.common.excel.ExcelOptions;
import com.jeeplus.common.excel.ExportMode;
import com.jeeplus.core.query.QueryWrapperGenerator;
import com.jeeplus.logging.annotation.ApiLog;
import com.jeeplus.sys.domain.WorkAttachmentInfo;
import com.jeeplus.sys.feign.IUserApi;
import com.jeeplus.sys.feign.IWorkAttachmentApi;
import com.jeeplus.sys.service.dto.RoleDTO;
import com.jeeplus.sys.service.dto.UserDTO;
import com.jeeplus.sys.service.dto.WorkAttachmentInfoDTO;
//import com.jeeplus.sys.utils.UserUtils;
//import com.jeeplus.pubmodules.oss.service.OssService;
import com.jeeplus.assess.projectRecords.constant.enums.ProjectStatusEnum;
import com.jeeplus.assess.projectRecords.constant.enums.ProjectTypeEnum;
import com.jeeplus.assess.projectRecords.constant.enums.YesOrNoEnum;
import com.jeeplus.assess.projectRecords.domain.Project;
import com.jeeplus.assess.projectRecords.service.ProjectService;
//import com.jeeplus.sys.service.UserService;
import com.jeeplus.assess.projectRecords.service.dto.FileUploadListDTO;
import com.jeeplus.assess.projectRecords.service.dto.ProjectDTO;
import com.jeeplus.assess.projectRecords.service.mapstruct.ProjectWrapper;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;


/**
 * 项目Controller
 *
 * @author lizhenhao
 * @version 2022-08-02
 */
@Api("项目管理")
@RestController
@RequestMapping(value = "/sys/project")
public class ProjectController {

    @Autowired
    private ProjectService projectService;

//    @Autowired
//    private UserService userService;

//    @Resource
//    private OssService ossService;

    private int successNum;

    @ApiLog("查询项目列表")
    @PreAuthorize("hasAuthority('sys:project:list')")
    @GetMapping("list")
    public ResponseEntity<IPage<Project>> data(Project project, Page<Project> page) throws Exception {
        QueryWrapper<Project> queryWrapper = QueryWrapperGenerator.buildQueryCondition ( project, Project.class );
        IPage<Project> result = projectService.selectPage (page,queryWrapper);
        UserDTO currentUserDTO = SpringUtil.getBean ( IUserApi.class ).getByToken(TokenProvider.getCurrentToken());
        Boolean bmzrRoleFlag = false;
        if(null != currentUserDTO.getRoleDTOList() && currentUserDTO.getRoleDTOList().size()>0){
            for (RoleDTO roleDTO : currentUserDTO.getRoleDTOList()) {
                if("bmzr".equals(roleDTO.getEnName())){
                    bmzrRoleFlag = true;
                    break;
                }
            }
        }
        List<Project> list = result.getRecords();
        for (Project info: list) {
            info = changeBigDecimalEntity(info);
            if((StringUtils.isNotBlank(info.getProjectHeadId()) && info.getProjectHeadId().equals(currentUserDTO.getId()))
                    || bmzrRoleFlag){
                info.setPermissionFlag(true);
            }else{
                info.setPermissionFlag(false);
            }
        }
        return ResponseEntity.ok (result);
    }

    /**
     * 查询项目数据
     * @param id
     * @return
     */
    @ApiLog("查询项目详情")
    @PreAuthorize ("hasAnyAuthority('sys:project:view','sys:project:add','sys:project:edit')")
    @GetMapping("queryById")
    public ResponseEntity queryById(@RequestParam("id") String id) {
        Project userProject = projectService.selectByProjectId ( id );
        userProject = changeBigDecimalEntity(userProject);
        return ResponseEntity.ok (userProject);
    }

    /**
     * 保存项目信息
     * @param projectDTO
     * @return
     */
    @ApiLog("保存项目")
    @PreAuthorize ("hasAnyAuthority('sys:project:add','sys:project:edit')")
    @PostMapping("save")
    public ResponseEntity save(@Valid @RequestBody ProjectDTO projectDTO){
        //新增或编辑表单保存
        Project project = ProjectWrapper.INSTANCE.toEntity (projectDTO);
        Project pro = projectService.projectDtoToDate(project,projectDTO);
        pro.setItemType(projectDTO.getItemType());
        if(StringUtils.isNotBlank(projectDTO.getProjectHead())){
            UserDTO projectHead = SpringUtil.getBean ( IUserApi.class ).getById(projectDTO.getProjectHead());
            if(null == projectHead || StringUtils.isBlank(projectHead.getId())){
                return ResponseEntity.badRequest().body("项目负责人不存在，请重新输入");
            }
            pro.setProjectHead(projectHead.getId());
        }

        /*if(StringUtils.isNotBlank(projectDTO.getEvaluationPersonOne())){

            UserDTO evaluationPersonOne = userService.get(projectDTO.getEvaluationPersonOne());
            if(null == evaluationPersonOne || StringUtils.isBlank(evaluationPersonOne.getId())){
                return ResponseEntity.badRequest().body("签字评估师1不存在，请重新输入");
            }
            pro.setEvaluationPersonOne(evaluationPersonOne.getId());
        }*/

        /*if(StringUtils.isNotBlank(projectDTO.getEvaluationPersonTwo())){

            UserDTO evaluationPersonTwo = userService.get(projectDTO.getEvaluationPersonTwo());
            if(null == evaluationPersonTwo || StringUtils.isBlank(evaluationPersonTwo.getId())){
                return ResponseEntity.badRequest().body("签字评估师2不存在，请重新输入");
            }
            pro.setEvaluationPersonTwo(evaluationPersonTwo.getId());
        }*/

        if(StringUtils.isBlank(projectDTO.getId())){

            //判断一下文号是否存在
            if(StringUtils.isNotBlank(projectDTO.getDocumentNum())){
                if(ObjectUtil.isNotEmpty(projectService.selectByDocumentNum(projectDTO))){
                    return ResponseEntity.badRequest().body("不可使用已存在的文号");
                }
            }
            //文件状态
            if (CollectionUtil.isNotEmpty(projectDTO.getWorkAttachments())) {
                pro.setFileUploadType("1");
            } else {
                pro.setFileUploadType("0");
            }

            projectService.save(pro);//新增
        }else{

            //判断一下文号是否存在
            if(StringUtils.isNotBlank(projectDTO.getDocumentNum())){
                Project userProjects = projectService.selectByDocumentNum(projectDTO);
                if(ObjectUtil.isNotEmpty(userProjects)){
                    if(!projectDTO.getId().equals(userProjects.getId())){
                        return ResponseEntity.badRequest().body("不可使用已存在的文号");
                    }
                }
            }
            LambdaUpdateWrapper<Project> wrapper = projectService.getLambdaUpdateWrapper(projectDTO);
            if (CollectionUtil.isNotEmpty(projectDTO.getWorkAttachments())) {
                wrapper.set(Project::getFileUploadType, "1");
            } else {
                wrapper.set(Project::getFileUploadType, "0");
            }
            projectService.update (pro,wrapper);//修改
        }
        //项目id处理
        List<WorkAttachmentInfoDTO> workAttachmentDtos = new ArrayList<>();
        List<WorkAttachmentInfo> workAttachments = projectDTO.getWorkAttachments();
        workAttachments.stream().forEach(ite -> {
            WorkAttachmentInfoDTO w = new WorkAttachmentInfoDTO();
            w.setBy(ite.getCreateById());
            w.setName(ite.getAttachmentName());
            String fileSize = ite.getFileSize();
            String[] split = fileSize.split("\\.");
            w.setSize(split[0]);
            w.setUrl(ite.getUrl());
            workAttachmentDtos.add(w);
        });
        Map<String,String> map = new HashMap<>();
        String fileList = JSON.toJSONString((workAttachmentDtos));
        String attachmentId = pro.getId();
        String attachmentFlag = "projectRecords";
        map.put("fileList",fileList);
        map.put("attachmentId",attachmentId);
        map.put("attachmentFlag",attachmentFlag);
        map.put("currentToken", TokenProvider.getCurrentToken ( ));
        SpringUtil.getBean ( IWorkAttachmentApi.class ).saveOrUpdateFileList(map);
        return ResponseEntity.ok ("保存项目成功");
    }

    /**
     * 删除项目
     * @param ids
     * @return
     */
    @ApiLog("删除项目")
    @PreAuthorize ("hasAuthority('sys:project:del')")
    @DeleteMapping("delete")
    public ResponseEntity delete(String ids) {
        String idArray[] =ids.split(",");
        projectService.removeByIds (Lists.newArrayList (idArray));
        return ResponseEntity.ok ("删除项目成功");
    }

    /**
     * 导入项目数据
     *
     * @return
     */
    @DemoMode
    @PreAuthorize("hasAnyAuthority('sys:project:import')")
    @PostMapping("import")
    @ApiOperation(value = "导入项目数据excel")
    public ResponseEntity importFile(MultipartFile file) throws IOException{
        //用来计数的，计算导入了多少条数据
        this.successNum = 0;

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        ArrayList<Project> arrayList = new ArrayList<>();
        HashMap<String,String> hashMap = new HashMap<>();

        //这里通过WorkbookFactory.create的方式来创建workBook，并没有用HSSFWorkbook和XSSFWorkbook，因为这两个局限性太大了，只能通过后缀来进行判断excel的版本
        //workBook在这里我主要用来判断是否存在“项目明细表”或“咨询报告”的sheet页，不存在会向用户抛提示
        Workbook workBook = WorkbookFactory.create(file.getInputStream());

        List<ProjectDTO> listA = new ArrayList<>();
        List<ProjectDTO> listB = new ArrayList<>();
        //判断是否存在“项目明细表”sheet页
        int sheetIndexAs = workBook.getSheetIndex("项目明细表");
        if(sheetIndexAs != -1){
            //获取评估项目sheet
            listA = EasyPoiUtil.importSheetExcel(file, 1, 1, sheetIndexAs,1, ProjectDTO.class);
            //去除excel中的空行
            listA = getExcelList(listA);
            //导入前检测数据
            String resultA = importDecide(listA, sdf, arrayList, hashMap, successNum, ProjectTypeEnum.ASSESS.getValue());
            if(StringUtils.isNotBlank(resultA)){
                //有返回值，说明导入的数据不正确。向用户抛提示
                return ResponseEntity.badRequest().body  (resultA);
            }
        }
        //判断是否存在“咨询报告”sheet页
        int sheetIndexCo = workBook.getSheetIndex("咨询报告");
        if(sheetIndexCo != -1){
            //咨询项目sheet
            listB = EasyPoiUtil.importSheetExcel(file, 1, 1, sheetIndexCo,1, ProjectDTO.class);
            //去除excel中的空行
            listB = getExcelList(listB);
            //导入前检测数据
            String resultB = importDecide(listB, sdf, arrayList, hashMap, successNum, ProjectTypeEnum.CONSULTATION.getValue());
            if(StringUtils.isNotBlank(resultB)){
                //有返回值，说明导入的数据不正确。向用户抛提示
                return ResponseEntity.badRequest().body  (resultB);
            }
        }
        //如果两个sheet页都不存在，说明这个导入的文件不符合要求
        if(sheetIndexAs == -1 && sheetIndexCo == -1){
            return ResponseEntity.badRequest().body  ("导入文件格式不正确，建议根据模板来进行数据的导入");
        }
        //判断文件中是否有重复的文号
        /*if(hashMap.size() != listA.size() + listB.size()){
            return ResponseEntity.badRequest().body  ("文件中存在重复的文号或者多个空文号");
        }*/
        //导入数据
        projectService.saveBatch(arrayList);

        return ResponseEntity.ok("已成功导入 " + successNum + " 条数据");
    }
    public String importDecide(List<ProjectDTO> list, SimpleDateFormat sdf, ArrayList<Project> arrayList, HashMap<String,String> hashMap, int successNum, String itemType){

        for (ProjectDTO project : list) {
            if(ObjectUtil.isEmpty(project)){
                continue;
            }
            try {
                if(StringUtils.isNotBlank(project.getEvaluationReportDateUi())){
                    //EvaluationReportDateUi字段接到的数据符合"yyyy/MM/dd"时间格式的话，正常执行。
                    //不符合的话，就会有异常，进到catch
                    String format = sdf.format(DateUtils.parseDate(project.getEvaluationReportDateUi(), new String[]{"yyyy/MM/dd"}));
                    //符合要求的时间格式，则会将数据转换为时间格式存到EvaluationReportDate字段中，并且将项目状态设置为”已完成“
                    project.setEvaluationReportDate(sdf.parse(format));
                    project.setStatus(ProjectStatusEnum.FINISH.getValue());
                }
            }catch (Exception e){
                if(StringUtils.isNotBlank(project.getEvaluationReportDateUi())){
                    if(project.getEvaluationReportDateUi().contains("报告已作废")){
                        //当EvaluationReportDateUi字段接收到的值包含”报告已作废“时，项目状态为”作废“，并且将值放到AssessReportMessage字段中
                        project.setStatus(ProjectStatusEnum.INVALID.getValue());
                        project.setAssessReportMessage(project.getEvaluationReportDateUi());
                    }else{
                        //当EvaluationReportDateUi字段接收到的值不包含”报告已作废“时，项目状态为”暂存“，并且将值放到AssessReportMessage字段中
                        project.setStatus(ProjectStatusEnum.STAGING.getValue());
                        project.setAssessReportMessage(project.getEvaluationReportDateUi());
                    }
                }else{
                    //当EvaluationReportDateUi字段接收到的值为空时，项目状态为”暂存“
                    project.setStatus(ProjectStatusEnum.STAGING.getValue());
                }
            }

            try {
                if(StringUtils.isNotBlank(project.getEvaluationBaseDateUi())){
                    String format = sdf.format(DateUtils.parseDate(project.getEvaluationBaseDateUi(), new String[]{"yyyy/MM/dd"}));
                    project.setEvaluationBaseDate(sdf.parse(format));
                }
            }catch (Exception e){
                if(StringUtils.isNotBlank(project.getEvaluationBaseDateUi())){
                    project.setAssessBaseMessage(project.getEvaluationBaseDateUi());
                }

            }

            try {
                if(StringUtils.isNotBlank(project.getInvoiceDateUi())){
                    String format = sdf.format(DateUtils.parseDate(project.getInvoiceDateUi(), new String[]{"yyyy/MM/dd"}));
                    project.setInvoiceDate(sdf.parse(format));
                }
            }catch (Exception e){
                if(StringUtils.isNotBlank(project.getInvoiceDateUi())){
                    project.setInvoiceMessage(project.getInvoiceDateUi());
                }

            }

            try {
                if(StringUtils.isNotBlank(project.getReimbursementDateUi())){
                    String format = sdf.format(DateUtils.parseDate(project.getReimbursementDateUi(), new String[]{"yyyy/MM/dd"}));
                    project.setReimbursementDate(sdf.parse(format));
                }
            }catch (Exception e){
                e.printStackTrace();
            }

            //项目负责人、签字评估师1、签字评估师2 关联user表的id
            if(StringUtils.isNotBlank(project.getProjectHead())){
                String id = SpringUtil.getBean ( IUserApi.class ).getUserIdByName(project.getProjectHead());
                if(StringUtils.isNotBlank(id)){
                    project.setProjectHead(id);
                }else{
                    return "文件中有项目负责人无法找到，请修改为在档人员，或者不填写";
                }
            }else{
                return "文件中有项目负责人为空，请重新填写";
            }

            /*if(StringUtils.isNotBlank(project.getEvaluationPersonOne())){
                String id = userService.getUserIdByName(project.getEvaluationPersonOne());
                if(ObjectUtil.isNotEmpty(id)){
                    project.setEvaluationPersonOne(id);
                }else{
                    return "文件中有签字评估师无法找到，请修改为在档人员，或者不填写";
                }
            }*/

            /*if(StringUtils.isNotBlank(project.getEvaluationPersonTwo())){
                String id = userService.getUserIdByName(project.getEvaluationPersonTwo());
                if(ObjectUtil.isNotEmpty(id)){
                    project.setEvaluationPersonTwo(id);
                }else{
                    return "文件中有签字评估师无法找到，请修改为在档人员，或者不填写";
                }
            }*/

            //文号的问题
            if(StringUtils.isNotBlank(project.getDocumentNum())) {
                Project userProject = projectService.selectByDocumentNum(project);
                if(ObjectUtil.isNotEmpty(userProject)){
                    return "文件中存在已在档的文号";
                }
            }/*else{
                return "文件中存在空的文号，文号不允许为空";
            }*/

            //当前处理人
            if(StringUtils.isNotBlank(project.getCurrentDisposePerson())){
                String id = SpringUtil.getBean ( IUserApi.class ).getUserIdByName(project.getCurrentDisposePerson());
                if(StringUtils.isNotBlank(id)){
                    project.setCurrentDisposePerson(id);
                }else{
                    return "文件中有当前处理人无法找到，请修改为在档人员，或者不填写";
                }
            }

            //年份的问题
            if(StringUtils.isBlank(project.getYear())) {
                return "文件中存在空年份，请填写年份信息";
            }

            //是否开票
            if(YesOrNoEnum.YES.getLabel().equals(project.getIsInvoice())){
                project.setIsInvoice(YesOrNoEnum.YES.getValue());
            }else if(YesOrNoEnum.NO.getLabel().equals(project.getIsInvoice())){
                project.setIsInvoice(YesOrNoEnum.NO.getValue());
            }

            //合同是否存档
            if(YesOrNoEnum.YES.getLabel().equals(project.getIsContractArchive())){
                project.setIsContractArchive(YesOrNoEnum.YES.getValue());
            }else if(YesOrNoEnum.NO.getLabel().equals(project.getIsContractArchive())){
                project.setIsContractArchive(YesOrNoEnum.NO.getValue());
            }

            //底稿是否完好
            if(YesOrNoEnum.YES.getLabel().equals(project.getIsPapersIntact())){
                project.setIsPapersIntact(YesOrNoEnum.YES.getValue());
            }else if(YesOrNoEnum.NO.getLabel().equals(project.getIsPapersIntact())){
                project.setIsPapersIntact(YesOrNoEnum.NO.getValue());
            }

            //底稿是否归档
            if(YesOrNoEnum.YES.getLabel().equals(project.getIsPapersArchive())){
                project.setIsPapersArchive(YesOrNoEnum.YES.getValue());
            }else if(YesOrNoEnum.NO.getLabel().equals(project.getIsPapersArchive())){
                project.setIsPapersArchive(YesOrNoEnum.NO.getValue());
            }

            //外勤是否已经报销
            if(YesOrNoEnum.YES.getLabel().equals(project.getIsOpsReimbursement())){
                project.setIsOpsReimbursement(YesOrNoEnum.YES.getValue());
            }else if(YesOrNoEnum.NO.getLabel().equals(project.getIsOpsReimbursement())){
                project.setIsOpsReimbursement(YesOrNoEnum.NO.getValue());
            }

            //是否已经报销提成
            if(YesOrNoEnum.YES.getLabel().equals(project.getIsCommissionReimbursement())){
                project.setIsCommissionReimbursement(YesOrNoEnum.YES.getValue());
            }else if(YesOrNoEnum.NO.getLabel().equals(project.getIsCommissionReimbursement())){
                project.setIsCommissionReimbursement(YesOrNoEnum.NO.getValue());
            }

            hashMap.put(project.getDocumentNum(),null);

            //金额字段保留两位小数  四舍五入
            project = changeBigDecimal(project);

            Project userProject = ProjectWrapper.INSTANCE.toEntity(project);
            //项目类型 1.评估项目  2.咨询项目
            userProject.setItemType(itemType);
            arrayList.add(userProject);
            this.successNum++;
        }

        return null;
    }

    /**
     * 金额字段保留两位小数  四舍五入
     * @param project
     * @return
     */
    public ProjectDTO changeBigDecimal(ProjectDTO project) {
        //未报销金额
        if(StringUtils.isNotBlank(project.getUnreimbursedAmount())){
            try{
            BigDecimal b = new BigDecimal(project.getUnreimbursedAmount()).setScale(2, BigDecimal.ROUND_HALF_UP);
            project.setUnreimbursedAmount(b.toString());
            }catch (Exception e) {
                project.setUnreimbursedAmount("");
            }
        }
        //已报销金额
        if(StringUtils.isNotBlank(project.getReimbursementAmount())){
            try{
            BigDecimal b = new BigDecimal(project.getReimbursementAmount()).setScale(2, BigDecimal.ROUND_HALF_UP);
            project.setReimbursementAmount(b.toString());
            }catch (Exception e) {
                project.setReimbursementAmount("");
            }
        }
        //预估/实际收费(万元）
        if(StringUtils.isNotBlank(project.getActualCharges())){
            try{
            BigDecimal b = new BigDecimal(project.getActualCharges()).setScale(2, BigDecimal.ROUND_HALF_UP);
            project.setActualCharges(b.toString());
            }catch (Exception e) {
                project.setActualCharges("");
            }
        }
        //报告收费（元）
        if(StringUtils.isNotBlank(project.getReportCharges())){
            try{
            BigDecimal b = new BigDecimal(project.getReportCharges()).setScale(2, BigDecimal.ROUND_HALF_UP);
            project.setReportCharges(b.toString());
            }catch (Exception e) {
                project.setReportCharges("");
            }
        }
        //租金评估（万/年）
        if(StringUtils.isNotBlank(project.getRentEvaluation())){
            try{
            BigDecimal b = new BigDecimal(project.getRentEvaluation()).setScale(2, BigDecimal.ROUND_HALF_UP);
            project.setRentEvaluation(b.toString());
            }catch (Exception e) {
                project.setRentEvaluation("");
            }
        }
        //净资产评估
        if(StringUtils.isNotBlank(project.getNetAssetsEvaluation())){
            try{
            BigDecimal b = new BigDecimal(project.getNetAssetsEvaluation()).setScale(2, BigDecimal.ROUND_HALF_UP);
            project.setNetAssetsEvaluation(b.toString());
            }catch (Exception e) {
                project.setNetAssetsEvaluation("");
            }
        }
        //固定资产评估（万元）
        if(StringUtils.isNotBlank(project.getFixedAssetsEvaluation())){
            try{
                BigDecimal b = new BigDecimal(project.getFixedAssetsEvaluation()).setScale(2, BigDecimal.ROUND_HALF_UP);
                project.setFixedAssetsEvaluation(b.toString());
            }catch (Exception e) {
                project.setFixedAssetsEvaluation("");
            }
        }
        //废旧物资评估（万元）
        if(StringUtils.isNotBlank(project.getWaystEvaluation())){
            try{
            BigDecimal b = new BigDecimal(project.getWaystEvaluation()).setScale(2, BigDecimal.ROUND_HALF_UP);
            project.setWaystEvaluation(b.toString());
            }catch (Exception e) {
                project.setWaystEvaluation("");
            }
        }
        return project;
    }

    /**
     * 金额字段保留两位小数  四舍五入
     * 实体类domain用
     * @param project
     * @return
     */
    public Project changeBigDecimalEntity(Project project) {
        //未报销金额
        try{
            if(StringUtils.isNotBlank(project.getUnreimbursedAmount())){
                BigDecimal b = new BigDecimal(project.getUnreimbursedAmount()).setScale(2, BigDecimal.ROUND_HALF_UP);
                project.setUnreimbursedAmount(b.toString());
            }
        }catch (Exception e) {
            e.printStackTrace();
        }

        //已报销金额
        try{
            if(StringUtils.isNotBlank(project.getReimbursementAmount())){
                BigDecimal b = new BigDecimal(project.getReimbursementAmount()).setScale(2, BigDecimal.ROUND_HALF_UP);
                project.setReimbursementAmount(b.toString());
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
        //预估/实际收费(万元）
        try{
            if(StringUtils.isNotBlank(project.getActualCharges())){
                BigDecimal b = new BigDecimal(project.getActualCharges()).setScale(2, BigDecimal.ROUND_HALF_UP);
                project.setActualCharges(b.toString());
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
        //报告收费（元）
        try{
            if(StringUtils.isNotBlank(project.getReportCharges())){
                BigDecimal b = new BigDecimal(project.getReportCharges()).setScale(2, BigDecimal.ROUND_HALF_UP);
                project.setReportCharges(b.toString());
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
        //租金评估（万/年）
        try{
            if(StringUtils.isNotBlank(project.getRentEvaluation())){
                BigDecimal b = new BigDecimal(project.getRentEvaluation()).setScale(2, BigDecimal.ROUND_HALF_UP);
                project.setRentEvaluation(b.toString());
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
        //净资产评估
        try{
            if(StringUtils.isNotBlank(project.getNetAssetsEvaluation())){
                BigDecimal b = new BigDecimal(project.getNetAssetsEvaluation()).setScale(2, BigDecimal.ROUND_HALF_UP);
                project.setNetAssetsEvaluation(b.toString());
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
        //固定资产评估（万元）
        try{
            if(StringUtils.isNotBlank(project.getFixedAssetsEvaluation())){
                BigDecimal b = new BigDecimal(project.getFixedAssetsEvaluation()).setScale(2, BigDecimal.ROUND_HALF_UP);
                project.setFixedAssetsEvaluation(b.toString());
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
        //废旧物资评估（万元）
        try{
            if(StringUtils.isNotBlank(project.getWaystEvaluation())){
                BigDecimal b = new BigDecimal(project.getWaystEvaluation()).setScale(2, BigDecimal.ROUND_HALF_UP);
                project.setWaystEvaluation(b.toString());
            }
        }catch (Exception e) {
            e.printStackTrace();
        }
        return project;
    }

    /**
     * 下载项目导入模板
     *
     * @param response
     * @return
     */
    @GetMapping("import/template")
    @PreAuthorize("hasAnyAuthority('sys:project:export')")
    @ApiOperation(value = "下载模板")
    public void importFileTemplate(HttpServletResponse response, HttpServletRequest request) {
        try {
            InputStream inputStream = this.getClass().getResourceAsStream("/dot/项目导入模板.xlsx");
            //强制下载不打开
            response.setContentType("application/force-download");
            OutputStream out = response.getOutputStream();
            //使用URLEncoder来防止文件名乱码或者读取错误
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode("project_template.xlsx", "UTF-8"));
            int b = 0;
            byte[] buffer = new byte[1000000];
            while (b != -1) {
                b = inputStream.read(buffer);
                if (b != -1) out.write(buffer, 0, b);
            }
            inputStream.close();
            out.close();
            out.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 导出项目数据
     *
     * @param userProjectDTO
     * @param page
     * @param response
     * @throws Exception
     */
    @ApiLog("导出项目数据")
    @PreAuthorize("hasAnyAuthority('sys:project:export')")
    @GetMapping("export")
    @ApiOperation(value = "导出项目excel")
    public void exportFile(ProjectDTO userProjectDTO, Page <ProjectDTO> page, ExcelOptions options, HttpServletResponse response) throws Exception {
        String fileName = options.getFilename ( );
        Project project = ProjectWrapper.INSTANCE.toEntity (userProjectDTO);
        QueryWrapper<Project> queryWrapper = QueryWrapperGenerator.buildQueryCondition ( project, Project.class );
        Page <Project> userProjectPage = pageAToPageB(page);
        List <Project> result = new ArrayList<>();
        List <ProjectDTO> userProjectDTOList = new ArrayList<>();
        if ( ExportMode.current.equals ( options.getMode ( ) ) ) {
            result = projectService.selectPage ( userProjectPage, queryWrapper ).getRecords ( );
        } else if ( ExportMode.selected.equals ( options.getMode ( ) ) ) {
            result = projectService.selectPage ( userProjectPage, queryWrapper ).getRecords().stream ( ).filter ( reimbursement ->
                    options.getSelectIds ( ).contains ( reimbursement.getId ( ) )
            ).collect ( Collectors.toList ( ) );
        } else {
            userProjectPage.setSize ( -1 );
            userProjectPage.setCurrent ( 0 );
            result = projectService.selectPage ( userProjectPage, queryWrapper ).getRecords ( );
        }
        result.stream().forEach(item->{
            ProjectDTO projectDTO = ProjectWrapper.INSTANCE.toDTO(item);
            userProjectDTOList.add(projectDTO);
        });

        SimpleDateFormat formatter=new SimpleDateFormat("yyyy/MM/dd");
        List <ProjectDTO> collect = userProjectDTOList.stream().map(item -> {
            return isChange(item,formatter);
        }).collect(Collectors.toList());
        if(ProjectTypeEnum.ASSESS.getValue().equals(userProjectDTO.getItemType())){
            EasyPoiUtil.exportExcel ( collect, "2021年资产评估项目备查登记表",  "项目明细表", ProjectDTO.class, fileName, response );
        }
        if(ProjectTypeEnum.CONSULTATION.getValue().equals(userProjectDTO.getItemType())){
            EasyPoiUtil.exportExcel ( collect, "2021年资产评估项目备查登记表",  "咨询报告", ProjectDTO.class, fileName, response );
        }
    }

    public Page<Project> pageAToPageB(Page<ProjectDTO> page){

        Page<Project> pageB = new Page<>();
        pageB.setCurrent(page.getCurrent());
        pageB.setSize(page.getSize());
        pageB.setOrders(page.getOrders());

        return pageB;
    }

    public ProjectDTO isChange(ProjectDTO userProjectDTO, SimpleDateFormat formatter){

        if(StringUtils.isNotBlank(userProjectDTO.getIsInvoice())){
            //是否开票
            if(YesOrNoEnum.YES.getValue().equals(userProjectDTO.getIsInvoice())){
                userProjectDTO.setIsInvoice(YesOrNoEnum.YES.getLabel());
            }else if(YesOrNoEnum.NO.getValue().equals(userProjectDTO.getIsInvoice())){
                userProjectDTO.setIsInvoice(YesOrNoEnum.NO.getLabel());
            }
        }


        if(StringUtils.isNotBlank(userProjectDTO.getIsContractArchive())) {
            //合同是否存档
            if (YesOrNoEnum.YES.getValue().equals(userProjectDTO.getIsContractArchive())) {
                userProjectDTO.setIsContractArchive(YesOrNoEnum.YES.getLabel());
            } else if (YesOrNoEnum.NO.getValue().equals(userProjectDTO.getIsContractArchive())) {
                userProjectDTO.setIsContractArchive(YesOrNoEnum.NO.getLabel());
            }
        }

        if(StringUtils.isNotBlank(userProjectDTO.getIsPapersIntact())) {
            //底稿是否完好
            if (YesOrNoEnum.YES.getValue().equals(userProjectDTO.getIsPapersIntact())) {
                userProjectDTO.setIsPapersIntact(YesOrNoEnum.YES.getLabel());
            } else if (YesOrNoEnum.NO.getValue().equals(userProjectDTO.getIsPapersIntact())) {
                userProjectDTO.setIsPapersIntact(YesOrNoEnum.NO.getLabel());
            }
        }

        if(StringUtils.isNotBlank(userProjectDTO.getIsPapersArchive())) {
            //底稿是否归档
            if (YesOrNoEnum.YES.getValue().equals(userProjectDTO.getIsPapersArchive())) {
                userProjectDTO.setIsPapersArchive(YesOrNoEnum.YES.getLabel());
            } else if (YesOrNoEnum.NO.getValue().equals(userProjectDTO.getIsPapersArchive())) {
                userProjectDTO.setIsPapersArchive(YesOrNoEnum.NO.getLabel());
            }
        }

        if(StringUtils.isNotBlank(userProjectDTO.getIsOpsReimbursement())) {
            //外勤是否已经报销
            if (YesOrNoEnum.YES.getValue().equals(userProjectDTO.getIsOpsReimbursement())) {
                userProjectDTO.setIsOpsReimbursement(YesOrNoEnum.YES.getLabel());
            } else if (YesOrNoEnum.NO.getValue().equals(userProjectDTO.getIsOpsReimbursement())) {
                userProjectDTO.setIsOpsReimbursement(YesOrNoEnum.NO.getLabel());
            }
        }

        if(StringUtils.isNotBlank(userProjectDTO.getIsCommissionReimbursement())) {
            //是否已经报销提成
            if (YesOrNoEnum.YES.getValue().equals(userProjectDTO.getIsCommissionReimbursement())) {
                userProjectDTO.setIsCommissionReimbursement(YesOrNoEnum.YES.getLabel());
            } else if (YesOrNoEnum.NO.getValue().equals(userProjectDTO.getIsCommissionReimbursement())) {
                userProjectDTO.setIsCommissionReimbursement(YesOrNoEnum.NO.getLabel());
            }
        }


        //评估报告日
        if(ObjectUtil.isNotEmpty(userProjectDTO.getEvaluationReportDate())){
            String time=formatter.format(userProjectDTO.getEvaluationReportDate());
            userProjectDTO.setEvaluationReportDateUi(time);
        }else{
            if(StringUtils.isNotBlank(userProjectDTO.getAssessReportMessage())){
                userProjectDTO.setEvaluationReportDateUi(userProjectDTO.getAssessReportMessage());
            }
        }
        //评估基准日
        if(ObjectUtil.isNotEmpty(userProjectDTO.getEvaluationBaseDate())){
            String time=formatter.format(userProjectDTO.getEvaluationBaseDate());
            userProjectDTO.setEvaluationBaseDateUi(time);
        }else{
            if(StringUtils.isNotBlank(userProjectDTO.getAssessBaseMessage())){
                userProjectDTO.setEvaluationBaseDateUi(userProjectDTO.getAssessBaseMessage());
            }
        }
        //开票日期
        if(ObjectUtil.isNotEmpty(userProjectDTO.getInvoiceDate())){
            String time=formatter.format(userProjectDTO.getInvoiceDate());
            userProjectDTO.setInvoiceDateUi(time);
        }else{
            if(StringUtils.isNotBlank(userProjectDTO.getInvoiceMessage())){
                userProjectDTO.setInvoiceDateUi(userProjectDTO.getInvoiceMessage());
            }
        }
        //报销日期
        if(ObjectUtil.isNotEmpty(userProjectDTO.getReimbursementDate())){
            String time=formatter.format(userProjectDTO.getReimbursementDate());
            userProjectDTO.setReimbursementDateUi(time);
        }
        return userProjectDTO;
    }

    public ArrayList<ProjectDTO> getExcelList(List<ProjectDTO> list){

        ArrayList<ProjectDTO> projectDTOS = new ArrayList<>();

        list.stream().forEach(item->{
            if(!objectCheckIsNull(item)){
                projectDTOS.add(item);
            }
        });

        return projectDTOS;
    }

    /**
     * 检查一个对象的所有属性值是否都是null
     * @param object
     * @return
     */
    public boolean objectCheckIsNull(Object object) {
        boolean flag = true; //定义返回结果，默认为true

        if (Objects.isNull(object)) {
            flag = true;
        } else {
            Class clazz = (Class) object.getClass(); // 得到类对象
            Field fields[] = clazz.getDeclaredFields(); // 得到所有属性
            for (Field field : fields) {
                if("serialVersionUID".equals(field.getName())){
                    continue;
                }
                field.setAccessible(true);
                Object fieldValue = null;
                try {
                    fieldValue = field.get(object); //得到属性值
                    Type fieldType = field.getGenericType();//得到属性类型
                    String fieldName = field.getName(); // 得到属性名
                } catch (Exception e){}
                if (fieldValue != null) {  //只要有一个属性值不为null 就返回false 表示对象不为null
                    flag = false;
                    break;
                }
            }
        }

        return flag;
    }

    @GetMapping("proportion")
    @ApiOperation(value = "项目完成比例")
    public String proportion(Project project) throws Exception{
        QueryWrapper<Project> queryWrapper = QueryWrapperGenerator.buildQueryCondition(project, Project.class);
        return projectService.proportion(queryWrapper);
    }

    /**
     * 导出项目数据
     *
     * @param projectDTO
     * @param response
     * @throws Exception
     */
    @GetMapping("exportFileUploadList")
    @ApiOperation(value = "导出项目文件上传比例excel")
    public void exportFileUploadList(ProjectDTO projectDTO, HttpServletResponse response) throws Exception {
        Project project = ProjectWrapper.INSTANCE.toEntity (projectDTO);
        QueryWrapper<Project> queryWrapper = QueryWrapperGenerator.buildQueryCondition( project, Project.class );
        List<FileUploadListDTO> list = projectService.exportFileUploadList(projectDTO);
        //完成比例导出文档添加汇总列
        AtomicReference<Integer> totalNum = new AtomicReference<>(0);
        AtomicReference<Integer> endNum = new AtomicReference<>(0);
        list.stream().forEach(item->{
            totalNum.updateAndGet(v -> v + item.getAllNum());
            endNum.updateAndGet(v -> v + item.getNum());
        });
        DecimalFormat df = new DecimalFormat("0.00");
        String s = df.format((float) endNum.get() * 100 / (float) totalNum.get());
        FileUploadListDTO fileUploadListDTO = new FileUploadListDTO();
        fileUploadListDTO.setName("汇总");
        fileUploadListDTO.setAllNum(totalNum.get());
        fileUploadListDTO.setNum(endNum.get());
        fileUploadListDTO.setProportion(s+"%");
        list.add(fileUploadListDTO);

        if(ProjectTypeEnum.ASSESS.getValue().equals(projectDTO.getItemType())){
            if(StringUtils.isNotBlank(projectDTO.getYear())){
                EasyPoiUtil.exportExcel(list, projectDTO.getYear() + "年评估项目上传比例报告",  "评估项目上传比例报告", FileUploadListDTO.class, "", response );
            }else{
                EasyPoiUtil.exportExcel(list, "评估项目上传比例报告",  "评估项目上传比例报告", FileUploadListDTO.class, "", response );
            }
        }
        if(ProjectTypeEnum.CONSULTATION.getValue().equals(projectDTO.getItemType())){
            if(StringUtils.isNotBlank(projectDTO.getYear())){
                EasyPoiUtil.exportExcel(list, projectDTO.getYear() + "年咨询项目上传比例报告",  "咨询项目上传比例报告", FileUploadListDTO.class, "", response );
            }else{
                EasyPoiUtil.exportExcel(list, "咨询项目上传比例报告",  "咨询项目上传比例报告", FileUploadListDTO.class, "", response );
            }
        }
    }
}
