package cn.com.ty.lift.business.library.service;

import cn.com.ty.lift.business.annualinspection.dto.InspectionRequest;
import cn.com.ty.lift.business.capital.dao.mapper.CommonMapper;
import cn.com.ty.lift.business.capital.service.CapitalRepairLiftRelevanceService;
import cn.com.ty.lift.business.framework.util.MessageUtils;
import cn.com.ty.lift.business.library.dao.entity.Lift;
import cn.com.ty.lift.business.library.dao.entity.LiftHistory;
import cn.com.ty.lift.business.library.dao.entity.PlatformCompanyLiftRelevance;
import cn.com.ty.lift.business.library.dao.entity.model.LiftImportModel;
import cn.com.ty.lift.business.library.dao.entity.model.LiftProjectModel;
import cn.com.ty.lift.business.library.dao.entity.model.request.LiftExtensionRequest;
import cn.com.ty.lift.business.library.dao.entity.model.request.LiftRequest;
import cn.com.ty.lift.business.library.dao.entity.model.response.LiftAnnualInspectionResponse;
import cn.com.ty.lift.business.library.dao.entity.model.response.LiftResponse;
import cn.com.ty.lift.business.library.dao.mapper.LiftMapper;
import cn.com.ty.lift.business.maintenance.dao.entity.MaintenancePlan;
import cn.com.ty.lift.business.maintenance.dao.entity.model.response.LiftPrintResponse;
import cn.com.ty.lift.business.maintenance.service.MaintenancePlanService;
import cn.com.ty.lift.business.maintenance.service.MaintenanceService;
import cn.com.ty.lift.business.project.dao.entity.Project;
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.project.service.ProjectService;
import cn.com.ty.lift.business.push.service.PushUserService;
import cn.com.ty.lift.common.base.ExportRequest;
import cn.com.ty.lift.common.constants.ApiConstants;
import cn.com.ty.lift.common.constants.CommonEnum;
import cn.com.ty.lift.common.constants.WebSocketConstants;
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.verify.Validate;
import cn.com.xwy.boot.web.dto.RestResponse;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author bieao
 * @date 2019/11/27
 * @description 电梯业务层
 */
@Slf4j
@Service
public class LiftService extends ServiceImpl<LiftMapper, Lift> {

    @Resource
    private PlatformCompanyLiftRelevanceService platformService;

    @Resource
    private ProjectLiftRelevanceService projectRelevanceService;

    @Resource
    private CapitalRepairLiftRelevanceService capitalRepairLiftRelevanceService;

    @Resource
    private MaintenanceService maintenanceService;

    @Resource
    private LiftHistoryService liftHistoryService;

    @Resource
    private ProjectService projectService;

    @Resource
    private PushUserService pushUserService;

    @Resource
    private JmsMessagingTemplate jmsMessagingTemplate;

    @Resource
    private CommonMapper commonMapper;

    @Resource
    private MaintenancePlanService maintenancePlanService;

    private Map<String, String> headsMap = new LinkedHashMap<String,String>() {{
        put("liftCode", "电梯号");
        put("registrationCode", "注册代码");
        put("liftBrand", "电梯品牌");
        put("liftType", "电梯类型");
        put("devicePosition", "设备使用地点");
    }};

    /**
     * @param request 电梯列表查询条件
     * @return IPage<LiftResponse> 电梯列表分页结果
     * @description 条件查询电梯档案列表
     * @date 2019/11/27 2:10 PM
     */
    public IPage<LiftResponse> list(LiftRequest request) {
        request.addAsc("project_name");
        return baseMapper.findByCondition(request.getPage(), request);
    }

    /**
     * @param request 电梯列表查询条件
     * @return IPage<LiftResponse> 项目下电梯列表
     * @description 查询项目下电梯列表
     * @date 2019/12/17 11:04 AM
     */
    public IPage<LiftResponse> liftProjectList(LiftRequest request) {
        return baseMapper.findLiftListByProjectId(request.getPage(), request);
    }

    /**
     * @param request 选择电梯列表查询条件
     * @return IPage<LiftResponse> 选择电梯列表
     * @description 选择电梯
     * @date 2019/12/30 10:42 AM
     */
    public IPage<LiftResponse> choose(LiftRequest request) {
        return baseMapper.chooseLiftList(request.getPage(), request);
    }

    /**
     * @param id 电梯id
     * @return Lift 电梯详情
     * @description 查询电梯详情
     * @date 2019/12/6 10:51 AM
     */
    public Object detail(Long id, Long projectId) {
        if (ObjectUtil.isEmpty(projectId)) {
            return getOne(null, id);
        }
        return baseMapper.queryById(id, projectId);
    }


    /**
     * @param mtCompanyId      公司id
     * @param registrationCode 注册代码
     * @return RestResponse 判断结果
     * @description 新增电梯前置判断条件
     * @date 2019/12/20 2:31 PM
     */
    public RestResponse preJudgment(Long mtCompanyId, String registrationCode) {
        //查询电梯表是否有该电梯
        Optional<Lift> lift = getOne(registrationCode, null);
        Long liftId = lift.map(Lift::getId).orElse(null);
        if (ObjectUtil.isNotEmpty(liftId)) {
            Map<String, Object> paramMap = new HashMap<>(2);
            paramMap.put("liftId", liftId);
            paramMap.put("mtCompanyId", mtCompanyId);
            //查询该公司下是否有此电梯
            boolean result = platformService.findCompanyLiftExist(paramMap);
            if (result) {
                return RestResponse.fail(MessageUtils.get("msg.lift.exist"));
            } else {
                Object detail = detail(liftId, null);
                return RestResponse.success(detail, MessageUtils.get("msg.lift.company.exist"));
            }
        } else {
            return RestResponse.success(null, MessageUtils.get("msg.pre.judge"));
        }
    }

    /**
     * @param registrationCode 电梯注册代码
     * @return 电梯id
     * @description 查询电梯是否存在
     * @date 2019/12/20 11:04 AM
     */
    public Optional<Lift> getOne(String registrationCode, Long liftId) {
        QueryWrapper<Lift> queryWrapper = new QueryWrapper<>();
        LambdaQueryWrapper<Lift> lambdaQueryWrapper = queryWrapper.lambda();
        lambdaQueryWrapper.eq(ObjectUtil.isNotEmpty(liftId), Lift::getId, liftId);
        lambdaQueryWrapper.eq(StrUtil.isNotEmpty(registrationCode), Lift::getRegistrationCode, registrationCode);
        return Optional.ofNullable(getOne(lambdaQueryWrapper));
    }

    /**
     * @param liftId      电梯id
     * @param mtCompanyId 公司id
     * @return RestResponse 是否成功
     * @description 保存公司电梯关联数据、平台电梯关联数据
     * @date 2020/1/11 4:18 下午
     */
    public PlatformCompanyLiftRelevance saveCompanyLiftInfo(Long liftId, Long mtCompanyId) {
        //新增企业电梯关联表
        PlatformCompanyLiftRelevance ret = platformService.save(liftId, mtCompanyId);
        if (ObjectUtil.isEmpty(ret)) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return null;
        }
        //新增平台电梯关联表
        PlatformCompanyLiftRelevance liftRelevance = platformService.save(liftId, ApiConstants.PLATFORM_COMPANY_ID);
        if (ObjectUtil.isEmpty(liftRelevance)) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return null;
        }
        return ret;
    }


    /**
     * @param liftId      电梯ID
     * @param mtCompanyId 公司ID
     * @return
     * @description 新增电梯消息推送
     * @date 2020/5/5 9:26 下午
     */
    public void sendAddMessage(Long liftId, Long projectId, Long mtCompanyId) {
        log.info("新增电梯开始消息推送");
        //消息推送
        List<Long> userIds = new ArrayList<>();
        Region region = pushUserService.findRegionByProject(projectId, mtCompanyId);
        if (Objects.nonNull(region)) {
            userIds.addAll(region.members());
        }
        List<PushUserInfo> director = pushUserService.listEnterpriseAdmin(mtCompanyId);
        List<PushUserInfo> pushUserInfos = new ArrayList<>(director);
        if (!userIds.isEmpty()) {
            List<PushUserInfo> userInfos = pushUserService.listByUserIds(mtCompanyId, userIds);
            pushUserInfos.addAll(userInfos);
        }
        log.info("新增电梯推送人员：" + pushUserInfos.toString());
        if (!pushUserInfos.isEmpty()) {
            Optional<Project> project = projectService.getOne(projectId);
            if (project.isPresent()) {
                Project p = project.get();
                String projectName = p.getProjectName();
                Optional<Lift> lift = getOne(null, liftId);
                lift.ifPresent(l -> {
                    String creatorName = commonMapper.queryUserNameById(l.getCreatorId());
                    PushMessage pushMessage = PushMessage.workCreateLift(creatorName, projectName, l.getDevicePosition(), l.getRegistrationCode());
                    pushMessage.sendTokenOnPlatform(jmsMessagingTemplate, pushUserInfos);
                    List<Long> sendToUserIdList = pushUserInfos.stream().map(PushUserInfo::getUserId).collect(Collectors.toList());
                    //推送pc端
                    SendMessageUtil.sendMessageToPC(jmsMessagingTemplate, sendToUserIdList, pushMessage.getContent(),
                            WebSocketConstants.MessageType.WORK_MSG);
                });
                log.info("新增电梯消息推送结束");
            }
        }
    }

    /**
     * @param request 新增电梯数据项
     * @return RestResponse 状态码和返回消息
     * @description 新增电梯
     * @date 2019/11/27 2:22 PM
     */
    @Transactional(rollbackFor = Exception.class)
    public RestResponse add(LiftExtensionRequest request) {
        //电梯id
        Long id;
        //获取新增标记 (0:新增,1:查询后带入)
        String mark = request.getMark();
        //公司id
        Long mtCompanyId = request.getMtCompanyId();
        Lift lift = request.getLift();
        RestResponse response = preJudgment(mtCompanyId, lift.getRegistrationCode());
        if (ApiConstants.RESULT_ERROR.equals(response.getStatusCode())) return response;
        //判断电梯是否需要新增
        Optional<Lift> lifts = getOne(lift.getRegistrationCode(), null);
        Long liftId = lifts.map(Lift::getId).orElse(null);
        if (ObjectUtil.isNotEmpty(liftId)) {
            mark = "1";
        }
        //新增标记 (0:新增,1:查询后带入)
        if ("0".equals(mark)) {
            //按当前日期时间戳自动生成电梯编号
            String liftCode = ApiConstants.STRAIGHT_LADDER + DateUtils.generateCode();
            if (CommonEnum.LiftType.STAIRCASE.getCode().equals(Objects.toString(lift.getLiftType()))) {
                lift.setLiftCode(ApiConstants.STAIRCASE + liftCode);
            }
            LocalDate lastDay = lift.getAnnualInspectionDate().with(TemporalAdjusters.lastDayOfMonth());
            lift.setAnnualInspectionDate(lastDay);
            //新增电梯表
            boolean liftResult = save(lift);
            if (!liftResult)
                return RestResponse.fail(MessageUtils.get("msg.add.fail"));
            id = lift.getId();
        } else {
            id = liftId;
        }
        //新增电梯来源
        String source = request.getSource();
        switch (source) {
            //电梯管理入口
            case "0":
                if (!maintenanceService.judge(mtCompanyId))
                    return RestResponse.fail(MessageUtils.get("msg.limit.num"));
                PlatformCompanyLiftRelevance relevanceResult = saveCompanyLiftInfo(id, mtCompanyId);
                if (Objects.isNull(relevanceResult)) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return RestResponse.fail(MessageUtils.get("msg.add.fail"));
                }
                break;
            //项目管理入口
            case "1":
                Long projectId = request.getProjectId();
                Optional<Project> optional = projectService.getOne(projectId);
                int num = 0;
                if (optional.isPresent()) {
                    Project project = optional.get();
                    num = project.getNum();
                }
                //判断当前项目下实际台量是否大于项目里设置的台量
                int currentNum = projectRelevanceService.countLiftNum(mtCompanyId, projectId);
                if (currentNum >= num) {
                    return RestResponse.fail(MessageUtils.get("msg.project.limit.num"));
                }
                if (!maintenanceService.judge(mtCompanyId))
                    return RestResponse.fail(MessageUtils.get("msg.limit.num"));
                //新增企业电梯关联表
                PlatformCompanyLiftRelevance companyLiftEntry = platformService.save(id, mtCompanyId);
                if (ObjectUtil.isEmpty(companyLiftEntry)) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return RestResponse.fail(MessageUtils.get("msg.add.fail"));
                }
                //新增平台电梯关联表
                PlatformCompanyLiftRelevance relevance = platformService.save(id, ApiConstants.PLATFORM_COMPANY_ID);
                if (ObjectUtil.isEmpty(relevance)) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return RestResponse.fail(MessageUtils.get("msg.add.fail"));
                }
                //新增项目电梯关联表
                ProjectLiftRelevance projectLiftRelevance = projectRelevanceService
                        .save(lift.getId(), request.getProjectId(), companyLiftEntry.getId(), request.getWorkerId(), request.getMtCompanyId());
                if (Objects.isNull(projectLiftRelevance)) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return RestResponse.fail(MessageUtils.get("msg.add.fail"));
                }
                //新增电梯发送消息
                sendAddMessage(id, projectLiftRelevance.getProjectId(), mtCompanyId);
                break;
            //大修管理入口
            case "2":
                //新增大修项目和电梯关联关系
                boolean ret = capitalRepairLiftRelevanceService.save(request, id);
                if (!ret) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return RestResponse.fail(MessageUtils.get("msg.add.fail"));
                }
                break;
            default:
                break;
        }
        return RestResponse.success(null, MessageUtils.get("msg.add.success"));
    }

    /**
     * @param projectId   项目ID
     * @param mtCompanyId 公司ID
     * @return
     * @description 更新电梯位置消息推送
     * @date 2020/5/5 9:26 下午
     */
    public void sendModifyMessage(Long liftId, Long projectId, Long mtCompanyId, String devicePosition, String newDevicePosition) {
        //消息推送
        List<Long> userIds = new ArrayList<>();
        Region region = pushUserService.findRegionByProject(projectId, mtCompanyId);
        if (Objects.nonNull(region)) {
            userIds.addAll(region.members());
        }
        List<PushUserInfo> director = pushUserService.listEnterpriseAdmin(mtCompanyId);
        List<PushUserInfo> pushUserInfos = new ArrayList<>(director);
        if (!userIds.isEmpty()) {
            List<PushUserInfo> userInfos = pushUserService.listByUserIds(mtCompanyId, userIds);
            pushUserInfos.addAll(userInfos);
        }
        if (!pushUserInfos.isEmpty()) {
            Optional<Project> project = projectService.getOne(projectId);
            if (project.isPresent()) {
                Project p = project.get();
                String projectName = p.getProjectName();
                Optional<Lift> lift = getOne(null, liftId);
                lift.ifPresent(l -> {
                    String updateName = commonMapper.queryUserNameById(l.getUpdateId());
                    PushMessage pushMessage = PushMessage.workModifyLiftPosition(updateName, projectName, devicePosition, newDevicePosition, l.getRegistrationCode());
                    pushMessage.sendTokenOnPlatform(jmsMessagingTemplate, pushUserInfos);
                    List<Long> sendToUserIdList = pushUserInfos.stream().map(PushUserInfo::getUserId).collect(Collectors.toList());
                    //推送pc端
                    SendMessageUtil.sendMessageToPC(jmsMessagingTemplate, sendToUserIdList, pushMessage.getContent(),
                            WebSocketConstants.MessageType.WORK_MSG);
                });
            }
        }
    }

    /**
     * @param request 修改电梯数据项
     * @return RestResponse 状态码和返回消息
     * @description 修改电梯
     * @date 2019/11/27 2:22 PM
     */
    @Transactional(rollbackFor = Exception.class)
    public RestResponse modify(LiftRequest request) {
        Lift lift = request.getLift();
        Long newWorkerId = request.getWorkerId();
        Long mtCompanyId = request.getMtCompanyId();
        Optional<Lift> oldLift = getOne(null, lift.getId());
        if (!oldLift.isPresent())
            return RestResponse.fail(MessageUtils.get("msg.lift.not.exist"));
//        String coordinate = lift.getCoordinate();
//        if (Objects.nonNull(coordinate)) {
//            boolean ret = VerifyUtils.preJudgment(coordinate);
//            if (!ret)
//                return RestResponse.fail(MessageUtils.get("msg.longitude.error"));
//        }
        LocalDate lastDay = lift.getAnnualInspectionDate().with(TemporalAdjusters.lastDayOfMonth());
        lift.setAnnualInspectionDate(lastDay);
        boolean result = updateById(lift);
        if (!result)
            return RestResponse.fail(MessageUtils.get("msg.modify.fail"));

        Lift entry = oldLift.get();
        ProjectLiftRelevance liftRelevance = projectRelevanceService.getOne(mtCompanyId, entry.getId());
        Long projectId = null;
        if (Objects.nonNull(liftRelevance)) {
            projectId = liftRelevance.getProjectId();
        }
        String devicePosition = entry.getDevicePosition();
        String newDevicePosition = lift.getDevicePosition();
        if (!Objects.equals(devicePosition, newDevicePosition)) {
            if (Objects.nonNull(projectId))
                //更新电梯定位发送推送消息
                sendModifyMessage(lift.getId(), projectId, mtCompanyId, devicePosition, newDevicePosition);
        }
        //生成电梯操作记录
        LiftHistory history = liftHistoryService.createOperaHistory(entry, lift, mtCompanyId);
        if (Objects.nonNull(history)) {
            //保存电梯操作记录
            boolean historyResult = liftHistoryService.save(history);
            if (!historyResult) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return RestResponse.fail(MessageUtils.get("msg.modify.fail"));
            }
        }
        if (Objects.nonNull(liftRelevance)) {
            liftRelevance.setWorkerId(newWorkerId);
            boolean ret = projectRelevanceService.modify(liftRelevance);
            if (!ret) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return RestResponse.fail(MessageUtils.get("msg.modify.fail"));
            }

            List<Long> liftIdList = new ArrayList<>();
            liftIdList.add(entry.getId());
            List<MaintenancePlan> planList = maintenancePlanService.getPlanList(mtCompanyId, liftIdList);
            if (CollUtil.isNotEmpty(planList)) {
                //修改未完成的维保计划为新的维保负责人
                planList.forEach(plan -> plan.setWorkerId(newWorkerId));
                boolean planResult = maintenancePlanService.updateBatchById(planList);
                if (!planResult) {
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                    return RestResponse.fail(MessageUtils.get("msg.modify.fail"));
                }
            }
        }
        return RestResponse.success(null, MessageUtils.get("msg.modify.success"));
    }

    public List<Map<String,String>> exportList(List<String> ids){
        return baseMapper.exportList(ids);
    }

    /**
     * @param request 导出电梯数据列表
     * @return RestResponse 状态码和返回消息
     * @description 导出电梯
     * @date 2020/5/9 9:08 下午
     */
    public void export(ExportRequest request, HttpServletResponse response) {
        List<String> ids = request.getIds();
        List<Map<String, String>> liftList = exportList(ids);
        ExcelWriter writer = new ExcelWriter(true, "电梯");
        //设置列别名
        headsMap.forEach(writer::addHeaderAlias);
        String fileName = DateUtils.generateCode() + ".xlsx";
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
        response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
        try (ServletOutputStream out = response.getOutputStream()) {
            writer.write(liftList, true);
            writer.autoSizeColumnAll();
            writer.flush(out, true);
            writer.close();
        } catch (IOException e) {
            log.error("电梯数据导出失败", e);
        }
    }

    /**
     * @param liftIdList 电梯id列表
     * @return 电梯列表数据
     * @description 根据电梯id列表查询项目列表数据
     * @date 2020/2/17 4:47 下午
     */
    public List<LiftPrintResponse> queryLiftListByIdList(List<Long> liftIdList) {
        return baseMapper.queryLiftListByIdList(liftIdList);
    }

    private void rollback() {
        //强制手动事务回滚
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    }

    /**
     * 解析excel导入电梯
     *
     * @param liftImportModels 解析表格lift数据
     * @param mtCompanyId      维保公司
     * @param projectId        项目id
     * @return RestResponse
     * @author wcz
     */
    @Transactional(rollbackFor = Exception.class)
    public RestResponse assemble(List<LiftImportModel> liftImportModels, Long mtCompanyId, Long projectId) {
        Validate.notNull(liftImportModels, "没有数据");
        //存放新建的lift
        List<Lift> lifts = new ArrayList<>();
        //存放新建的project-lift关联信息
        List<ProjectLiftRelevance> projectLiftRelevances = new ArrayList<>();
        //存放新建的platform-company-lift关联信息
        List<PlatformCompanyLiftRelevance> platformCompanyLiftRelevances = new ArrayList<>();

        //根据维保公司和项目id查询
        List<LiftProjectModel> liftProjectModelList = baseMapper.listByCompanyAndProject(mtCompanyId, projectId);
        //根据维保公司和项目查询
        List<ProjectLiftRelevance> projectLiftRelevanceList = projectRelevanceService.findLiftList(mtCompanyId, projectId);
        //根据维保公司
        List<PlatformCompanyLiftRelevance> platformCompanyLiftRelevanceList = platformService.listByCompany(mtCompanyId);

        liftImportModels.forEach(item -> {
            Lift lift = new Lift();
            //复制解析model中的值到lift中
            BeanUtil.copyProperties(item, lift, true);
            log.info("复制电梯属性后：{}", lift);

            String registrationCode = item.getRegistrationCode();
            Optional<LiftProjectModel> lpOptional = liftProjectModelList
                    .stream()
                    .filter(lpm -> (StrUtil.equals(registrationCode, lpm.getRegistrationCode())))
                    .distinct().limit(1).findFirst();
            LiftProjectModel liftProjectModel;

            if (lpOptional.isPresent()) {
                liftProjectModel = lpOptional.get();
                //如果已经存在lift，取出id赋值
                lift.setId(liftProjectModel.getLiftId());
            } else {
                //如果不存在,新建id赋值
                lift.setId(IdWorker.getId());
                //加入list中批量插入
                lifts.add(lift);
            }

            Optional<PlatformCompanyLiftRelevance> pclrOptional = platformCompanyLiftRelevanceList
                    .stream()
                    .filter(pclr -> (pclr.getLiftId() == lift.getId()))
                    .distinct().limit(1).findFirst();
            PlatformCompanyLiftRelevance platformCompanyLiftRelevance;
            if (!pclrOptional.isPresent()) {
                //如果不存在就新建
                platformCompanyLiftRelevance = new PlatformCompanyLiftRelevance();
                Long relevanceId = IdWorker.getId();
                //属性赋值
                platformCompanyLiftRelevance.setId(relevanceId);
                platformCompanyLiftRelevance.setMtCompanyId(mtCompanyId);
                platformCompanyLiftRelevance.setLiftId(lift.getId());
                platformCompanyLiftRelevance.setLiftCompanyStatus(CommonEnum.LiftStatus.NORMAL.getCode());
                log.info("新建PlatformCompanyLiftRelevance:{}", platformCompanyLiftRelevance);
                //加入到新建list中批量插入
                platformCompanyLiftRelevances.add(platformCompanyLiftRelevance);
            } else {
                platformCompanyLiftRelevance = pclrOptional.get();
            }

            //fixme:导入电梯时，是否指定项目导入，添加ProjectLiftRelevance关联信息
            Optional<ProjectLiftRelevance> plrOptional = projectLiftRelevanceList
                    .stream()
                    .filter(plr -> (plr.getLiftId() == lift.getId()))
                    .distinct().limit(1).findFirst();
            ProjectLiftRelevance projectLiftRelevance;
            if (!plrOptional.isPresent()) {
                projectLiftRelevance = new ProjectLiftRelevance();
                projectLiftRelevance.setMtCompanyId(mtCompanyId);
                projectLiftRelevance.setLiftId(lift.getId());
                projectLiftRelevance.setProjectId(projectId);
                projectLiftRelevance.setRelevanceId(platformCompanyLiftRelevance.getId());
                log.info("新建ProjectLiftRelevance：{}", projectLiftRelevance);
                projectLiftRelevances.add(projectLiftRelevance);
            }
        });

        //批量插入platform-company-lift关联数据
        if (!platformCompanyLiftRelevances.isEmpty()) {
            boolean plat = platformService.saveOrUpdateBatch(platformCompanyLiftRelevances, platformCompanyLiftRelevances.size());
            if (!plat) {
                //强制手动事务回滚
                rollback();
                return RestResponse.fail("插入平台公司电梯关联信息失败，请稍后重试");
            }
        }
        //批量插入project-lift关联数据
        if (!projectLiftRelevances.isEmpty()) {
            boolean proj = projectRelevanceService.saveOrUpdateBatch(projectLiftRelevances, projectLiftRelevances.size());
            if (!proj) {
                //强制手动事务回滚
                rollback();
                return RestResponse.fail("插入项目电梯关联信息失败，请稍后重试");
            }
        }
        //批量插入lift数据
        if (!lifts.isEmpty()) {
            boolean lift = saveOrUpdateBatch(lifts, lifts.size());
            if (!lift) {
                //强制手动事务回滚
                rollback();
                return RestResponse.fail("插入电梯信息失败，请稍后重试");
            }
        }
        return RestResponse.success("导入成功");
    }

    /**
     * 根据RegistrationCode分组查询存在电梯注册代码相同的重复电梯数据
     *
     * @return List<Lift>
     * @author wcz
     */
    public List<Lift> groupByRegistrationCode() {
        return baseMapper.groupByRegistrationCode();
    }

    /**
     * 待确认年检计划，提前45天提醒
     *
     * @return
     */
    public IPage<LiftAnnualInspectionResponse> toConfirmAnnualInspection(IPage<LiftAnnualInspectionResponse> page, InspectionRequest request) {
        if (Objects.equals(request.getCurrentRoleCode(), CommonEnum.DefaultRole.HIGH_DIRECTOR.getCode())) {
            request.setUserId(0L);
        }
        return baseMapper.toConfirmAnnualInspection(page, request);
    }

    /**
     * 去掉lift中registration_code对应的重复数据，同步其他表中lift_id
     *
     * @return boolean
     * @author wcz
     */
    public boolean clearData() {
        //1 获取同一registration_code对应多个电梯的记录
        //SELECT registration_code FROM lift GROUP BY registration_code HAVING count(*) > 1
        List<Lift> liftCodes = groupByRegistrationCode();
        Validate.notNull(liftCodes, "电梯注册信息为空");
        //按照registration_code 分组
        Map<String, List<Lift>> codesMap = liftCodes.stream().collect(Collectors.groupingBy(Lift::getRegistrationCode));
        //根据存在重复lift的code去查询registration_code <--> id的对应关系
        Map<String, List<Long>> codeIdMap = new HashMap<>();
        //sB201707197996 SB201707197996
        codesMap.forEach((code, liftList) -> {
            codeIdMap.put(code, liftList.stream().map(Lift::getId).collect(Collectors.toList()));
        });
        //从相同registration_code中的lift_id的集合,取出第一个id保留，剩下的删除，并且把删除的id引用update成保留的id
        Map<Long, List<Long>> updateIds = new HashMap<>();
        StringBuffer deleteBuffer = new StringBuffer();

        deleteBuffer.append(StrUtil.format("-- 删除lift中同一个RegistrationCode下多余id的记录 :{}", DateUtil.now())).append("\n\n");
        codeIdMap.entrySet().stream().forEach(entry -> {
            List<Long> entryValue = entry.getValue();
            int size = entryValue.size();
            //sB201707197996 SB201707197996
            if (size > 1) {
                Long first = entryValue.get(0);
                List<Long> other = entryValue.subList(1, size);
                updateIds.put(first, other);
                deleteBuffer.append(StrUtil.format("-- RegCode: {}, ids: {}, 保留id: {}", entry.getKey(), entry.getValue(), first)).append("\n");
                deleteBuffer.append(StrUtil.format("DELETE FROM lift WHERE id IN ({});", StrUtil.join(",", other))).append("\n\n");
            }
        });
        //保存脚本到文件
        String deletesql = "./sql/1.delete_lift.sql";
        FileUtil.writeString(deleteBuffer.toString(), new File(deletesql), "utf-8");
        log.info("生成DELETE操作sql文件：{}", deletesql);

        StringBuffer updateBuffer = new StringBuffer();
        //需要更新lift_id的表
        List<String> updateTables = new ArrayList<>();
        updateTables.add("annual_inspection");
        updateTables.add("emergency_repair");
        updateTables.add("lift_event");
        updateTables.add("lift_fault_report");
        updateTables.add("lift_history");
        updateTables.add("maintenance_plan");
        updateTables.add("maintenance_record");
        updateTables.add("maintenance_dispose");
        updateTables.add("project_lift_relevance");
        updateTables.add("platform_company_lift_relevance");
        updateTables.add("user_lift_record");
        updateTables.add("integral_record");
//        updateTables.add("reward_lift");
        for (int i = 0; i < updateTables.size(); i++) {
            String table = updateTables.get(i);
            updateBuffer.append(StrUtil.format("-- 更新{}中lift_id :{}", table, DateUtil.now())).append("\n\n");
            updateIds.entrySet().forEach(entry -> {
                updateBuffer.append(StrUtil.format("UPDATE {} SET lift_id = {} WHERE lift_id IN ({});", table, entry.getKey(), StrUtil.join(",", entry.getValue()))).append("\n");
            });
            String updatesql = StrUtil.format("./sql/{}.update_{}.sql", (i + 2), table);
            FileUtil.writeString(updateBuffer.toString(), new File(updatesql), "utf-8");
            log.info("生成UPDATE操作sql文件：{}", updatesql);
            //清空buffer
            updateBuffer.setLength(0);
        }
        return true;
    }

}
