package cn.com.ty.lift.business.annualinspection.controller;


import cn.com.ty.lift.business.annualinspection.dto.InspectionCount;
import cn.com.ty.lift.business.annualinspection.dto.InspectionRequest;
import cn.com.ty.lift.business.annualinspection.dto.InspectionResponse;
import cn.com.ty.lift.business.annualinspection.entity.AnnualInspection;
import cn.com.ty.lift.business.annualinspection.service.AnnualInspectionService;
import cn.com.ty.lift.business.library.dao.entity.model.response.LiftAnnualInspectionResponse;
import cn.com.ty.lift.business.library.service.LiftService;
import cn.com.ty.lift.business.project.dao.entity.ProjectLiftRelevance;
import cn.com.ty.lift.business.project.dao.entity.Region;
import cn.com.ty.lift.business.project.service.ProjectLiftRelevanceService;
import cn.com.ty.lift.business.push.service.PushUserService;
import cn.com.ty.lift.common.constants.WebSocketConstants;
import cn.com.ty.lift.common.model.CountPage;
import cn.com.ty.lift.common.model.PushMessage;
import cn.com.ty.lift.common.model.PushUserInfo;
import cn.com.ty.lift.common.utils.DateUtils;
import cn.com.ty.lift.common.utils.SendMessageUtil;
import cn.com.ty.lift.common.utils.ValuePool;
import cn.com.ty.lift.common.verify.Val;
import cn.com.ty.lift.common.verify.Validate;
import cn.com.ty.lift.common.verify.Validation;
import cn.com.xwy.boot.web.dto.RestResponse;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.metadata.IPage;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 年检记录 前端控制器
 * </p>
 *
 * @author wcz
 * @since 2019-12-10
 */
@Slf4j
@AllArgsConstructor
@RestController
@RequestMapping("/annualinspection/annual-inspection")
public class AnnualInspectionController {

    private AnnualInspectionService     annualInspectionService;
    private LiftService                 liftService;
    private ProjectLiftRelevanceService projectLiftRelevanceService;
    private JmsMessagingTemplate        jmsMessagingTemplate;
    private PushUserService             pushUserService;

    private static final Map<String, String>     headerAlias = new LinkedHashMap<>();

    static {
        headerAlias.put("areaName", "区域");
        headerAlias.put("projectName", "项目");
        headerAlias.put("useCompanyCode", "梯号");
        headerAlias.put("registrationCode", "注册代码");
        headerAlias.put("devicePosition", "电梯位置");
        headerAlias.put("directorName", "区域主管");
        headerAlias.put("workerName", "维保工");
        headerAlias.put("planDate", "年检时间");
        headerAlias.put("checkGoverner", "是否检查限速器");
        headerAlias.put("loadInspection", "是否荷载试验");
        headerAlias.put("statusDesc", "状态");
    }

    /**
     * 根据id查询
     *
     * @param request InspectionRequest
     * @return RestResponse
     */
    @PostMapping("findOne")
    @Validation(fields = {"id"})
    public RestResponse findOne(@Val @RequestBody InspectionRequest request) {
        InspectionResponse entity = annualInspectionService.infoById(request);
        return RestResponse.success(entity);
    }

    /**
     * 根据条件查询年检记录
     *
     * @param request InspectionRequest
     * @return RestResponse
     */
    @PostMapping("page")
    @Validation(fields = "mtCompanyId")
    public RestResponse page(@Val @RequestBody InspectionRequest request) {
        //计划与执行: 按年检时间由近及远排序,已完成: 按年检完成时间由近及远排序
        if(Objects.equals(request.getStatus(), ValuePool.INSPECTION_STATUS_TO_DO)){
            request.addAsc("plan_date");
        }
        if(Objects.equals(request.getStatus(), ValuePool.INSPECTION_STATUS_COMPLETE)){
            request.addAsc("finish_time");
        }
        IPage<InspectionResponse> pages = annualInspectionService.pageByCondition(request);
        long count = annualInspectionService.countByCondition(request);
        return RestResponse.success(CountPage.getCountPage(count, pages));
    }

    /**
     * 根据条件查询年检记录
     *
     * @param request InspectionRequest
     * @return RestResponse
     */
    @PostMapping("pageWorker")
    @Validation(fields = {"workerId"})
    public RestResponse pageWorker(@Val @RequestBody InspectionRequest request) {
        //计划与执行: 按年检时间由近及远排序,已完成: 按年检完成时间由近及远排序
        IPage<InspectionResponse> pages = annualInspectionService.pageByCondition(request);
        return RestResponse.success(pages);
    }

    /**
     * app年检数量统计
     *
     * @param request InspectionRequest
     * @return RestResponse
     */
    @PostMapping("count")
    @Validation(fields = {"mtCompanyId", "userId"})
    public RestResponse count(@Val @RequestBody InspectionRequest request) {
        InspectionCount count = annualInspectionService.count(request);
        return RestResponse.success(count);
    }

    /**
     * 待确认年检计划, 根据电梯中的年检时间，提前45天通知
     */
    @PostMapping("toConfirm")
    @Validation(fields = {"mtCompanyId"})
    public RestResponse toConfirm(@Val @RequestBody InspectionRequest request){
        request.addAsc("annual_inspection_date");
        IPage<LiftAnnualInspectionResponse> pages = liftService.toConfirmAnnualInspection(request.getPage(), request);
        return RestResponse.success(pages);
    }

    /**
     * status 状态（0 待完成；1 已完成；2 超期）
     * 1  维保工确认年检计划。停止信息推送
     * stepStatus : 1
     * stepName: 1
     */
    @PostMapping("confirm")
    @Validation(fields = {"id", "liftId","mtCompanyId","planDate","isCheckGoverner","loadInspectionSetting"})
    public RestResponse confirm(@Val @RequestBody AnnualInspection entity){
        AnnualInspection sameConfirm = annualInspectionService.sameConfirm(entity.getLiftId(), entity.getMtCompanyId(), entity.getPlanDate());
        if(Objects.nonNull(sameConfirm)){
            LocalDateTime createDate = sameConfirm.getCreateDate();
            String message = Objects.isNull(createDate) ? "" : "创建于：" + createDate;
            return RestResponse.fail(ValuePool.INSPECTION_EXIST_SAME + message);
        }

        AnnualInspection previousConfirm = annualInspectionService.previousConfirm(entity.getLiftId(), entity.getMtCompanyId());
        if(Objects.nonNull(previousConfirm) && Objects.nonNull(previousConfirm.getPlanDate())){
            LocalDate deadline = previousConfirm.getPlanDate().plusDays(DateUtils.daysOfYear());
            Validate.notTrue(deadline.isBefore(entity.getPlanDate()), ValuePool.inspectionSetPlanDateIllegal(previousConfirm.getPlanDate(), deadline));
        }

        entity.setStatus(ValuePool.INSPECTION_STATUS_TO_DO);
        entity.setStepStatus(ValuePool.INSPECTION_STAGE_CONFIRM);
        entity.setStepName(ValuePool.INSPECTION_STEP_ONE);
        boolean ai = annualInspectionService.save(entity);
        if (ai) {
            return RestResponse.success(entity.getId());
        } else {
            return RestResponse.fail();
        }
    }
    /**
     * 修改年检信息
     * <p>
     * status 状态（0 待完成；1 已完成；2 超期）
     * stepStatus  :年检阶段状态- 第一阶段（自检） 1-2，第二阶段（报检） 3，第三阶段（场检） 4-7，第四阶段（确认） 8-10
     * stepName : 当前能操作的阶段
     * <p>
     * 1  维保工确认年检计划
     * 2  维保工上传自检报告,选择自检时间 或者 文员设置 是否检查限速器和荷载年检设置，
     *      文员也可以上传自检报告或者确认自检报告和自检时间，自检时间以最后设置的为准
     * --------------------------------
     * 3  企业文员确认现场检验时间
     *      录入人员信息，政府质检，企业质检，联系电话
     * --------------------------------
     * 4	维保工上传检验结果, 如果有急修就关闭急修
     * 5	企业文员确认检验结果-合格 --> 不能算年检超期
     * 6	企业文员确认检验结果-整改 --> 回到第二阶段
     * 7	企业文员确认检验结果-不合格 --> 可以算年检超期
     * --------------------------------
     * 8	维保工上传年检报告和合格证
     * 9	企业文员确认年检报告和合格证-合格
     * 10	企业文员确认年检报告和合格证-不合格 -->停用电梯
     *
     * @param entity AnnualInspection
     * @return RestResponse
     */
    @PostMapping("update")
    @Validation(fields = {"id","mtCompanyId","isCheckGoverner","loadInspectionSetting"})
    public RestResponse update(@Val @RequestBody InspectionRequest entity){
        AnnualInspection old = annualInspectionService.findByMtCompanyId(entity.getId(), entity.getMtCompanyId());
        Validate.notNull(old, ValuePool.INSPECTION_NOT_EXIST);
        Integer oldStepName = ValuePool.nullable(old.getStepName(), 1);
        Validate.equals(oldStepName, ValuePool.INSPECTION_STEP_ONE, ValuePool.inspectionOptionOnStageIllegal(ValuePool.INSPECTION_STEP_ONE_DESC));
        old.setIsCheckGoverner(entity.getIsCheckGoverner());
        old.setLoadInspectionSetting(entity.getLoadInspectionSetting());

        old.setStepStatus(ValuePool.INSPECTION_STAGE_CONFIRM);
        old.setStepName(ValuePool.INSPECTION_STEP_ONE);
        boolean ai = annualInspectionService.saveOrUpdate(old);
        return RestResponse.success(ai);
    }

    /**
     * 1 -> 2  维保工上传自检报告,选择自检时间 或者 文员设置 是否检查限速器和荷载年检设置，
     *      文员也可以上传自检报告或者确认自检报告和自检时间，自检时间以最后设置的为准
     */
    @PostMapping("stepOne")
    @Validation(fields = {"id","mtCompanyId","stepStatus","selfcheckReportImg","selfcheckDate"})
    public RestResponse stepOne(@Val @RequestBody InspectionRequest entity){
        AnnualInspection old = annualInspectionService.findByMtCompanyId(entity.getId(), entity.getMtCompanyId());
        Validate.notNull(old, ValuePool.INSPECTION_NOT_EXIST);
        Integer oldStepName = ValuePool.nullable(old.getStepName(), 1);
        Integer oldStepStatus = ValuePool.nullable(old.getStepStatus(), 2);
        Integer stepStatus = entity.getStepStatus();
        Validate.equals(oldStepName, ValuePool.INSPECTION_STEP_ONE, ValuePool.inspectionStepToNextIllegal(ValuePool.INSPECTION_STEP_ZERO_DESC, ValuePool.INSPECTION_STEP_ONE_DESC));
        Validate.between(oldStepStatus, ValuePool.INSPECTION_STAGE_CONFIRM, ValuePool.INSPECTION_STAGE_SELFCHECK, ValuePool.inspectionCurrentStepStatusIllegal( oldStepStatus, ValuePool.INSPECTION_STEP_ONE_DESC));
        Validate.equals(stepStatus, ValuePool.INSPECTION_STAGE_SELFCHECK, ValuePool.inspectionNewStepStatusIllegal(stepStatus, ValuePool.INSPECTION_STEP_ONE_DESC));

        String selfcheckReportImg = entity.getSelfcheckReportImg();
        if (selfcheckReportImg.contains(",")) {
            int count = selfcheckReportImg.length() - selfcheckReportImg.replace(",", "").length();
            Validate.notTrue(count > 3, ValuePool.INSPECTION_SELF_CHECK_IMAGE_COUNT);
        }

        old.setSelfcheckReportImg(selfcheckReportImg);
        old.setSelfcheckDate(entity.getSelfcheckDate());
        old.setStepStatus(entity.getStepStatus());

        old.setStepName(ValuePool.INSPECTION_STEP_TWO);//流转到阶段2

        boolean ai = annualInspectionService.saveOrUpdate(old);
        return RestResponse.success(ai);
    }

    /**
     * 2 -> 3  企业文员确认现场检验时间
     *      录入人员信息，政府质检，企业质检，联系电话
     */
    @PostMapping("stepTwo")
    @Validation(fields = {"id","mtCompanyId","checkDate","inspector","operator","telephone"})
    public RestResponse stepTwo(@Val @RequestBody InspectionRequest entity){
        AnnualInspection old = annualInspectionService.findByMtCompanyId(entity.getId(), entity.getMtCompanyId());
        Validate.notNull(old, ValuePool.INSPECTION_NOT_EXIST);
        Integer oldStepName = ValuePool.nullable(old.getStepName(), 2);
        Integer oldStepStatus = ValuePool.nullable(old.getStepStatus(), 2);
        Validate.between(oldStepName, ValuePool.INSPECTION_STEP_ONE,ValuePool.INSPECTION_STEP_TWO, ValuePool.inspectionStepToNextIllegal(ValuePool.INSPECTION_STEP_ONE_DESC, ValuePool.INSPECTION_STEP_TWO_DESC));
        Validate.between(oldStepStatus, ValuePool.INSPECTION_STAGE_SELFCHECK, ValuePool.INSPECTION_STAGE_CONFIRM_CHECK, ValuePool.inspectionCurrentStepStatusIllegal(oldStepStatus, ValuePool.INSPECTION_STEP_TWO_DESC));

        old.setCheckDate(entity.getCheckDate());
        old.setInspector(entity.getInspector());
        old.setOperator(entity.getOperator());
        old.setTelephone(entity.getTelephone());

        old.setStepStatus(ValuePool.INSPECTION_STAGE_CONFIRM_CHECK);
        old.setStepName(ValuePool.INSPECTION_STEP_THREE);//流转到阶段3

        boolean ai = annualInspectionService.saveOrUpdate(old);
        if(ai){
            Region region = pushUserService.findRegionByAnnualInspection(old.getId(), old.getMtCompanyId());
            InspectionResponse info = annualInspectionService.infoById(entity);
            List<Long> userIds = new ArrayList<>();
            //区域主管
            if (Objects.nonNull(region)) {
                userIds.add(region.getUserId());
            }
            //电梯主要负责人
            ProjectLiftRelevance relevance = projectLiftRelevanceService.getOne(info.getMtCompanyId(), info.getLiftId());
            if (Objects.nonNull(relevance)) {
                userIds.add(relevance.getWorkerId());
            }
            if(!userIds.isEmpty()){
                List<PushUserInfo> pushUserInfos = pushUserService.listByUserIds(old.getMtCompanyId(), userIds);
                PushMessage pushMessage = PushMessage.inspectionConfirmCheckDate(info.getProjectName(),
                        info.getDevicePosition(), info.getRegistrationCode(), info.getCheckDate());
                pushMessage.sendTokenOnPlatform(jmsMessagingTemplate, pushUserInfos);
                //pc端推送消息
                List<Long> pushUserIds = pushUserInfos.stream().map(PushUserInfo::getUserId).collect(Collectors.toList());
                SendMessageUtil.sendMessageToPC(jmsMessagingTemplate, pushUserIds, pushMessage.getContent(),
                        WebSocketConstants.MessageType.INSPECTION_MSG);
            }
        }
        return RestResponse.success(ai);
    }

    /**
     * 3 -> 4	维保工上传检验结果
     * 5	企业文员确认检验结果-合格 --> 不能算年检超期
     * 6	企业文员确认检验结果-整改 --> 回到第二阶段
     *      (3  企业文员确认现场检验时间 录入人员信息，政府质检，企业质检，联系电话)
     * 7	企业文员确认检验结果-不合格 --> 可以算年检超期
     *  设置下次年检时间，是否检查限速器和是否荷载设置
     */
    @PostMapping("stepThree")
    @Validation(fields = {"id","mtCompanyId","stepStatus","checkResultImg","projectId","nextInspectionTime","isCheckGoverner","loadInspectionSetting"})
    public RestResponse stepThree(@Val @RequestBody InspectionRequest entity){
        AnnualInspection old = annualInspectionService.findByMtCompanyId(entity.getId(), entity.getMtCompanyId());
        Validate.notNull(old, ValuePool.INSPECTION_NOT_EXIST);
        Integer oldStepName = ValuePool.nullable(old.getStepName(), 2);
        Integer oldStepStatus = ValuePool.nullable(old.getStepStatus(), 3);
        Integer stepStatus = entity.getStepStatus();
        Validate.between(oldStepName,ValuePool.INSPECTION_STEP_TWO, ValuePool.INSPECTION_STEP_THREE, ValuePool.inspectionStepToNextIllegal(ValuePool.INSPECTION_STEP_TWO_DESC, ValuePool.INSPECTION_STEP_THREE_DESC));
        Validate.between(oldStepStatus, ValuePool.INSPECTION_STAGE_CONFIRM_CHECK, ValuePool.INSPECTION_STAGE_CHECK_UNQUALIFIED, ValuePool.inspectionCurrentStepStatusIllegal(oldStepStatus, ValuePool.INSPECTION_STEP_THREE_DESC));
        Validate.between(stepStatus, ValuePool.INSPECTION_STAGE_UPLOAD_CHECK, ValuePool.INSPECTION_STAGE_CHECK_UNQUALIFIED, ValuePool.inspectionNewStepStatusIllegal(stepStatus, ValuePool.INSPECTION_STEP_THREE_DESC));
        LocalDate oldPlanDate = old.getPlanDate();
        if(Objects.nonNull(oldPlanDate)){
            LocalDate deadline = oldPlanDate.plusDays(DateUtils.daysOfYear());
            Validate.notTrue(deadline.isBefore(entity.getNextInspectionTime()), ValuePool.inspectionSetPlanDateIllegal(oldPlanDate, deadline));
        }

        old.setStepStatus(entity.getStepStatus());
        old.setCheckResultImg(entity.getCheckResultImg());
        old.setNextInspectionTime(entity.getNextInspectionTime());

        //企业文员确认检验结果-整改 --> 回到第二阶段
        if(stepStatus == ValuePool.INSPECTION_STAGE_CHECK_QUALIFIED || stepStatus == ValuePool.INSPECTION_STAGE_CHECK_UNQUALIFIED){
            old.setStepName(ValuePool.INSPECTION_STEP_FOUR);//流转到阶段4
        } else if(stepStatus == ValuePool.INSPECTION_STAGE_CHECK_RECTIFICATION){
            old.setStepStatus(ValuePool.INSPECTION_STAGE_CONFIRM_CHECK);
            old.setStepName(ValuePool.INSPECTION_STEP_TWO);//转回阶段2
            old.setCheckResultImg("");
            old.setNextInspectionTime(ValuePool.INSPECTION_MIN_PLAN_DATE);
        }
        return annualInspectionService.stepThree(old, entity.getProjectId(), entity.getIsCheckGoverner(), entity.getLoadInspectionSetting());
    }

    /**
     * 5,7 -> 8	维保工上传年检报告和合格证
     * 9	企业文员确认年检报告和合格证-合格
     * 10	企业文员确认年检报告和合格证-不合格 -->停用电梯
     */
    @PostMapping("stepFour")
    @Validation(fields = {"id","mtCompanyId","stepStatus","annualInspectionImg","certificateImgUrl"})
    public RestResponse stepFour(@Val @RequestBody InspectionRequest entity){
        AnnualInspection old = annualInspectionService.findByMtCompanyId(entity.getId(), entity.getMtCompanyId());
        Validate.notNull(old, ValuePool.INSPECTION_NOT_EXIST);
        Integer oldStepName = ValuePool.nullable(old.getStepName(), 3);
        Integer oldStepStatus = ValuePool.nullable(old.getStepStatus(), 5);
        Integer stepStatus = entity.getStepStatus();
        Validate.between(oldStepName, ValuePool.INSPECTION_STEP_THREE, ValuePool.INSPECTION_STEP_FOUR, ValuePool.inspectionStepToNextIllegal(ValuePool.INSPECTION_STEP_THREE_DESC, ValuePool.INSPECTION_STEP_FOUR_DESC));
        Validate.between(oldStepStatus, ValuePool.INSPECTION_STAGE_CHECK_QUALIFIED, ValuePool.INSPECTION_STAGE_CERT_REPORT_UNQUALIFIED, ValuePool.inspectionCurrentStepStatusIllegal(oldStepStatus, ValuePool.INSPECTION_STEP_FOUR_DESC));
        Validate.between(stepStatus, ValuePool.INSPECTION_STAGE_UPLOAD_CERT_REPORT, ValuePool.INSPECTION_STAGE_CERT_REPORT_UNQUALIFIED, ValuePool.inspectionNewStepStatusIllegal(stepStatus, ValuePool.INSPECTION_STEP_FOUR_DESC));

        old.setStepStatus(entity.getStepStatus());
        old.setAnnualInspectionImg(entity.getAnnualInspectionImg());
        old.setCertificateImgUrl(entity.getCertificateImgUrl());

        if(stepStatus == ValuePool.INSPECTION_STAGE_CERT_REPORT_QUALIFIED){
            old.setStatus(ValuePool.INSPECTION_STATUS_COMPLETE);//已完成
            old.setFinishTime(LocalDateTime.now());
        } else if(stepStatus == ValuePool.INSPECTION_STAGE_CERT_REPORT_UNQUALIFIED){
            old.setStatus(ValuePool.INSPECTION_STATUS_OVERDUE);//超期
            old.setFinishTime(LocalDateTime.now());
        }
        old.setStepName(ValuePool.INSPECTION_STEP_FOUR);
        return annualInspectionService.stepFour(old);
    }

    /**
     * 其他角色获取自己关联的项目的年检任务
     *
     * @param request InspectionRequest
     * @return RestResponse
     */
    @PostMapping("pageByUser")
    @Validation(fields = {"userId"})
    public RestResponse pageByUser(@Val @RequestBody InspectionRequest request) {
        IPage<InspectionResponse> pages = annualInspectionService.pageByUser(request);
        return RestResponse.success(pages);
    }

    /**
     * 上传自检报告，传递年检id，传递自检报告图片路径
     * stepName = 1
     * @param request InspectionRequest
     * @return RestResponse
     */
    @PostMapping("selfcheck")
    @Validation(fields = {"id", "selfcheckDate", "selfcheckReportImg"})
    public RestResponse selfcheck(@Val @RequestBody InspectionRequest request) {
        AnnualInspection entity = annualInspectionService.getById(request.getId());
        Validate.notNull(entity, ValuePool.INSPECTION_NOT_EXIST);
        //1 判断年检完成状态 0
        Integer status = ValuePool.nullable(entity.getStatus(), 0);
        Validate.equals(status, ValuePool.INSPECTION_STATUS_TO_DO, ValuePool.inspectionCurrentStepStatusIllegal(status, ValuePool.INSPECTION_STEP_ONE_DESC));
        //2 判断年检阶段状态 1
        Integer stepName = ValuePool.nullable(entity.getStepName(), 1);
        Validate.equals(stepName, ValuePool.INSPECTION_STEP_ONE, ValuePool.inspectionCurrentStepStatusIllegal(stepName, ValuePool.INSPECTION_STEP_ONE_DESC));

        String selfcheckReportImg = request.getSelfcheckReportImg();
        if (selfcheckReportImg.contains(",")) {
            int count = selfcheckReportImg.length() - selfcheckReportImg.replace(",", "").length();
            Validate.notTrue(count > 3, ValuePool.INSPECTION_SELF_CHECK_IMAGE_COUNT);
        }

        entity.setSelfcheckDate(request.getSelfcheckDate());
        entity.setSelfcheckReportImg(selfcheckReportImg);
        entity.setStepStatus(ValuePool.INSPECTION_STAGE_SELFCHECK);
        entity.setStepName(ValuePool.INSPECTION_STEP_ONE);

        boolean result = annualInspectionService.updateById(entity);
        return RestResponse.success(result);
    }

    /**
     * 上传检验结果，传递年检id，传递检验报告图片路径
     *  stepName = 3
     * @param request InspectionRequest
     * @return RestResponse
     */
    @PostMapping("check")
    @Validation(fields = {"id", "checkDate", "checkResultImg"})
    public RestResponse check(@Val @RequestBody InspectionRequest request) {
        AnnualInspection entity = annualInspectionService.getById(request.getId());
        Validate.notNull(entity, ValuePool.INSPECTION_NOT_EXIST);
        //1 判断年检完成状态 0
        Integer status = ValuePool.nullable(entity.getStatus(), 0);
        Validate.equals(status, ValuePool.INSPECTION_STATUS_TO_DO, ValuePool.inspectionCurrentStepStatusIllegal(status, ValuePool.INSPECTION_STEP_THREE_DESC));
        //2 判断年检阶段状态 3
        Integer stepName = ValuePool.nullable(entity.getStepName(), 3);
        Validate.equals(stepName, ValuePool.INSPECTION_STEP_THREE, ValuePool.inspectionCurrentStepStatusIllegal(stepName, ValuePool.INSPECTION_STEP_THREE_DESC));

        entity.setCheckDate(request.getCheckDate());
        entity.setCheckResultImg(request.getCheckResultImg());
        entity.setStepStatus(ValuePool.INSPECTION_STAGE_UPLOAD_CHECK);
        entity.setStepName(ValuePool.INSPECTION_STEP_THREE);

        boolean result = annualInspectionService.updateById(entity);
        return RestResponse.success(result);
    }

    /**
     * 上传年检报告和合格证，传递年检id，传递年检报告和合格证图片路径
     *  stepName = 4
     * @param request InspectionRequest
     * @return RestResponse
     */
    @PostMapping("finish")
    @Validation(fields = {"id", "certificateImgUrl", "annualInspectionImg"})
    public RestResponse finish(@Val @RequestBody InspectionRequest request) {
        AnnualInspection entity = annualInspectionService.getById(request.getId());
        Validate.notNull(entity, ValuePool.INSPECTION_NOT_EXIST);
        //1 判断年检完成状态 0
        Integer status = ValuePool.nullable(entity.getStatus(), 0);
        Validate.equals(status, ValuePool.INSPECTION_STATUS_TO_DO, ValuePool.inspectionCurrentStepStatusIllegal(status, ValuePool.INSPECTION_STEP_FOUR_DESC));
        //2 判断年检阶段状态 4
        Integer stepName = ValuePool.nullable(entity.getStepName(), 4);
        Validate.equals(stepName, ValuePool.INSPECTION_STEP_FOUR, ValuePool.inspectionCurrentStepStatusIllegal(stepName, ValuePool.INSPECTION_STEP_FOUR_DESC));

        entity.setCertificateImgUrl(request.getCertificateImgUrl());
        entity.setAnnualInspectionImg(request.getAnnualInspectionImg());
        entity.setStepStatus(ValuePool.INSPECTION_STAGE_UPLOAD_CERT_REPORT);
        entity.setStepName(ValuePool.INSPECTION_STEP_FOUR);

        boolean result = annualInspectionService.updateById(entity);
        return RestResponse.success(result);
    }

    @PostMapping("export")
    @Validation(fields = {"ids"})
    public void export(@Val @RequestBody InspectionRequest request, HttpServletResponse response) {
        log.info("headerAlias: {}", headerAlias);
        //查询数据
        List<InspectionResponse> inspections = annualInspectionService.listByIdList(request);
        Validate.notNull(inspections, ValuePool.INSPECTION_NOT_EXIST);

        //压缩文件夹
        File zipFile = null;
        File baseDir = null;
        try {
            //获取根目录
            String generateCode = DateUtils.generateCode();
            String dir = StrUtil.join(File.separator, ValuePool.SYSTEM_USER_DIR, "inspection", generateCode);
            String zip = dir + ".zip";
            zipFile = new File(zip);
            baseDir = new File(dir);
            log.info("dir: {}", dir);
            log.info("zip: {}", zip);


            //生成excel文件
            String excel = File.separator + dir + File.separator + generateCode + ".xlsx";
            log.info("生成excel: {}", excel);
            File excelFile = new File(excel);
            ExcelWriter writer = ExcelUtil.getBigWriter(excelFile, "年检记录表");
            //设置列别名
            headerAlias.forEach(writer::addHeaderAlias);
            //如果为true，则不设置alias的字段将不被输出，false表示原样输出
            writer.setOnlyAlias(true);
            writer.write(inspections, true);
//            writer.autoSizeColumnAll();
            writer.close();
            FileUtil.touch(excelFile);

            //处理图片类文件
            //windows现在已知的文件名非法字符有 \ / : * ? " < > |
            String illegalChars = "\\/:*?\"<>|";
            for (int i = 0; i < inspections.size(); i++) {
                InspectionResponse ins = inspections.get(i);
                String areaName = ins.getAreaName();
                String projectName = ins.getProjectName();
                String registrationCode = ins.getRegistrationCode();
                areaName = StrUtil.isNotEmpty(areaName) ? areaName.replace(illegalChars,"-") : "[区域]";
                projectName = StrUtil.isNotEmpty(projectName) ? projectName.replace(illegalChars,"-") : "[项目]";
                registrationCode = StrUtil.isNotEmpty(registrationCode) ? registrationCode.replace(illegalChars,"-") : "[电梯注册代码]";
                //图片文件夹 dir/i.AreaName-ProjectName-RegistrationCode/
                String imgDir = StrUtil.format("{}{}{}.{}-{}-{}{}", dir, File.separator, (i + 1), areaName, projectName, registrationCode, File.separator);
                String selfcheckReportImg = ins.getSelfcheckReportImg();
                if (Objects.nonNull(selfcheckReportImg)) {
                    if (selfcheckReportImg.contains(",")) {
                        String[] imgs = selfcheckReportImg.split(",");
                        for (int num = 0; num < imgs.length; num++) {
                            downloadImage(imgs[num], imgDir, "1.自检报告 "+ (num + 1) +".jpg");
                        }
                    } else {
                        downloadImage(selfcheckReportImg, imgDir, "1.自检报告.jpg");
                    }
                }
                downloadImage(ins.getCheckResultImg(), imgDir, "2.检验结果.jpg");
                downloadImage(ins.getCertificateImgUrl(), imgDir, "3.合格证.jpg");
                downloadImage(ins.getAnnualInspectionImg(), imgDir, "4.年检报告.jpg");
            }

            //压缩文件夹
            log.info("生成zipfile: {}", zip);
            ZipUtil.zip(dir, zip);
        } catch (Exception e) {
            FileUtil.del(zipFile);
            FileUtil.del(baseDir);
            log.error("生成年检文件失败", e);
            throw Validate.validateException("生成年检文件失败");
        }
        //下载压缩文件
        if (FileUtil.exist(zipFile)) {
            // 设置强制下载不打开, ZIP的application/x-zip-compressed
            response.setContentType("application/force-download");
            // 设置文件名
            response.addHeader("Content-Disposition", "attachment;fileName=" + zipFile.getName());
            byte[] buffer = new byte[1024];
            try (FileInputStream fis = new FileInputStream(zipFile);
                 BufferedInputStream bis = new BufferedInputStream(fis)) {
                OutputStream os = response.getOutputStream();
                int i;
                while ((i = bis.read(buffer)) != -1) {
                    os.write(buffer, 0, i);
                }
            } catch (Exception e) {
                log.error("下载年检文件失败", e);
                throw Validate.validateException("下载年检文件失败");
            }finally {
                //删除临时根目录和zip文件
                FileUtil.del(zipFile);
                FileUtil.del(baseDir);
            }
        }
    }

    //根据图片URL生成图片文件
    private void downloadImage(String imgUrl, String imgDir, String imgName) {
        if (StrUtil.isNotEmpty(imgUrl)) {
            log.info("imgUrl: {}", imgUrl);
            String filename = imgDir + imgName;
            log.info("{}: {}", imgName, filename);
            HttpUtil.downloadFile(imgUrl, filename);
        }
    }

    @PostMapping("pageByLift")
    @Validation(fields = {"mtCompanyId", "liftId", "projectId"})
    public RestResponse pageByLift(@Val @RequestBody InspectionRequest request){
        IPage<InspectionResponse> pages = annualInspectionService.pageByLift(request);
        return RestResponse.success(pages);
    }
}
