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

import cn.com.ty.lift.business.framework.util.MessageUtils;
import cn.com.ty.lift.business.library.service.PlatformCompanyLiftRelevanceService;
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.dao.entity.model.response.MaintenancePlanPrintResponse;
import cn.com.ty.lift.business.maintenance.service.MaintenancePlanService;
import cn.com.ty.lift.business.project.dao.entity.*;
import cn.com.ty.lift.business.project.dao.entity.model.ProjectImportModel;
import cn.com.ty.lift.business.project.dao.entity.model.request.ProjectRequest;
import cn.com.ty.lift.business.project.dao.entity.model.response.ProjectDetailResponse;
import cn.com.ty.lift.business.project.dao.entity.model.response.ProjectResponse;
import cn.com.ty.lift.business.project.dao.entity.model.response.ProjectUserResponse;
import cn.com.ty.lift.business.project.dao.mapper.ProjectMapper;
import cn.com.ty.lift.business.push.service.PushUserService;
import cn.com.ty.lift.common.base.ExportRequest;
import cn.com.ty.lift.common.constants.CommonEnum;
import cn.com.ty.lift.common.constants.CommonEnum.ProjectStatus;
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.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.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
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.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author bieao
 * @date 2019/11/28
 * @description 项目管理业务层
 */
@Slf4j
@Service
public class ProjectService extends ServiceImpl<ProjectMapper, Project> {

    @Resource
    private ProjectLiftRelevanceService projectLiftRelevanceService;
    @Resource
    private PlatformCompanyLiftRelevanceService platformCompanyService;
    @Resource
    private ProjectHistoryService projectHistoryService;
    @Resource
    private PropertyCompanyService propertyCompanyService;
    @Resource
    private PropertyContactService propertyContactService;
    @Resource
    private AreaCodeService areaCodeService;
    @Resource
    private RegionService regionService;
    @Resource
    private ProjectUserService projectUserService;
    @Resource
    private MaintenancePlanService maintenancePlanService;
    @Resource
    private ProjectAppService projectAppService;
    @Resource
    private JmsMessagingTemplate jmsMessagingTemplate;
    @Resource
    private PushUserService pushUserService;

    private Map<String, String> projectHeadsMap = new LinkedHashMap<String, String>() {{
        put("projectCode", "项目编号");
        put("projectName", "项目名称");
        put("province", "省份");
        put("city", "市");
        put("district", "区");
        put("num", "台量");
        put("actualNum", "系统台量");
        put("address", "项目地址");
        put("startDate", "开始时间");
        put("endDate", "结束时间");
    }};

    private Map<String, String> liftHeadsMap = new LinkedHashMap<String, String>() {{
        put("projectName", "项目名称");
        put("registrationCode", "注册代码");
        put("liftType", "电梯类型");
        put("devicePosition", "电梯位置");
        put("liftBrand", "电梯品牌");
        put("workerName", "维保工");
        put("annualInspectionDate", "年检日期");
        put("liftStatus", "电梯状态");
    }};

    /**
     * @return 项目列表
     * @description 查询服务中项目列表
     * @date 2020/2/9 4:02 下午
     */
    public List<Project> queryInServiceProjectList() {
        LambdaQueryWrapper<Project> lambdaQueryWrapper = new QueryWrapper<Project>().lambda();
        lambdaQueryWrapper.lt(Project::getEndDate, LocalDate.now());
        lambdaQueryWrapper.eq(Project::getProjectStatus, ProjectStatus.IN_SERVICE.getCode());
        return list(lambdaQueryWrapper);
    }

    /**
     * @return 项目列表
     * @description 查询尚未开始项目列表
     * @date 2020/6/3 22:32 下午
     */
    public List<Project> queryNotStartProjectList() {
        LambdaQueryWrapper<Project> lambdaQueryWrapper = new QueryWrapper<Project>().lambda();
        lambdaQueryWrapper.eq(Project::getStartDate, LocalDate.now());
        lambdaQueryWrapper.eq(Project::getProjectStatus, ProjectStatus.NOT_START.getCode());
        return list(lambdaQueryWrapper);
    }

    /**
     * @param list 项目列表
     * @description 更新项目状态
     * @date 2020/2/10 4:16 下午
     */
    public void updateBatch(List<Project> list, String projectStatus) {
        list.forEach(project -> project.setProjectStatus(projectStatus));
        updateBatchById(list, list.size());
        log.info("批量更新项目状态" + list.size() + "条");
    }


    /**
     * @param projectId   项目ID
     * @param mtCompanyId 公司ID
     * @return
     * @description 项目逾期消息推送
     * @date 2020/5/5 9:26 下午
     */
    public void sendOverdueMessage(Long projectId, Long mtCompanyId) {
        //消息推送
        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()) {
            ProjectDetailResponse detail = projectAppService.detail(projectId);
            PushMessage pushMessage = PushMessage.workProjectOverdue(detail.getAreaName(), detail.getProjectName());
            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:10 PM
     */
    public IPage<ProjectResponse> list(ProjectRequest request) {
        request.addDesc("project_status");
        return baseMapper.findByCondition(request.getPage(), request);
    }

    /**
     * @param request 项目名称
     * @return 项目列表
     * @description 获取物业端数据接口
     * @date 2020/5/11 10:21 上午
     */
    public IPage<Project> propertyList(ProjectRequest request) {
        String projectName = request.getProjectName();
        IPage<Project> projectPage = new Page<>(request.getPageNum(), request.getPageSize());
        return this.page(projectPage, new QueryWrapper<Project>()
                .select("id", "project_name projectName", "mt_company_id mtCompanyId")
                .like(StringUtils.isNotBlank(projectName), "project_name", projectName)
        );
    }

    /**
     * @param mtCompanyId   公司id
     * @param projectStatus 项目状态
     * @return 项目数量、电梯数量、停保电梯数量
     * @description 查询项目数量、电梯数量、停保电梯数量
     * @date 2020/1/19 11:30 上午
     */
    public Map<String, Object> countAll(Long mtCompanyId, Integer projectStatus) {
        LambdaQueryWrapper<Project> lambdaQueryWrapper = new QueryWrapper<Project>().lambda();
        lambdaQueryWrapper.eq(Project::getMtCompanyId, mtCompanyId);
        List<Project> projects = list(lambdaQueryWrapper);
        Map<String, Long> collect = projects.stream().collect(Collectors.groupingBy(Project::getProjectStatus, Collectors.counting()));
        Map<String, Long> totalMap = new HashMap<>();
        Long notStart = collect.get(ProjectStatus.NOT_START.getCode());
        Long inService = collect.get(ProjectStatus.IN_SERVICE.getCode());
        Long stopService = collect.get(ProjectStatus.STOP_SERVICE.getCode());
        Long overdue = collect.get(ProjectStatus.OVERDUE.getCode());
        totalMap.put("notStart", notStart == null ? 0 : notStart);
        totalMap.put("inService", inService == null ? 0 : inService);
        totalMap.put("stopService", stopService == null ? 0 : stopService);
        totalMap.put("overdue", overdue == null ? 0 : overdue);
        int projectCount = count(mtCompanyId, projectStatus);
        int liftCount = projectLiftRelevanceService.count(mtCompanyId, projectStatus);
        int stopLiftCount = platformCompanyService.count(mtCompanyId, projectStatus);
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("totalCount", totalMap);
        resultMap.put("projectCount", projectCount);
        resultMap.put("liftCount", liftCount);
        resultMap.put("stopLiftCount", stopLiftCount);
        return resultMap;
    }

    /**
     * @param mtCompanyId   公司id
     * @param projectStatus 项目状态
     * @return 符合条件的项目数量
     * @description 根据项目状态和公司id查询项目数量
     * @date 2020/1/19 11:30 上午
     */
    public int count(Long mtCompanyId, Integer projectStatus) {
        LambdaQueryWrapper<Project> lambdaQueryWrapper = new QueryWrapper<Project>().lambda();
        lambdaQueryWrapper.eq(Project::getMtCompanyId, mtCompanyId);
        lambdaQueryWrapper.eq(Project::getProjectStatus, projectStatus);
        return count(lambdaQueryWrapper);
    }

    /**
     * @param request 公司项目查询条件
     * @return IPage<ProjectResponse> 公司项目分页列表结果
     * @description 查询公司项目列表
     * @date 2019/12/9 10:32 AM
     */
    public IPage<ProjectResponse> companyList(ProjectRequest request) {
        return baseMapper.findCompanyListByCondition(request.getPage(), request);
    }

    /**
     * @param request 区域id或维保公司id
     * @return List<ProjectIDResponse> 项目ID和名称列表
     * @description 项目ID和名称列表
     * @date 2019/12/16 4:21 PM
     */
    public List<Map<String, Object>> projectIDList(ProjectRequest request) {
        QueryWrapper<Project> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(ObjectUtil.isNotEmpty(request.getMtCompanyId()), "mt_company_id", request.getMtCompanyId());
        queryWrapper.eq(ObjectUtil.isNotEmpty(request.getRegionId()), "region_id", request.getRegionId());
        queryWrapper.select("id projectId", "project_name projectName");
        return listMaps(queryWrapper);
    }

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

    /**
     * @param plans 项目id列表
     * @return 项目列表
     * @description 获取项目列表
     * @date 2020/1/8 9:06 下午
     */
    public Collection<Project> getProjectList(List<MaintenancePlan> plans) {
        List<Long> projectIdList = plans.stream().map(MaintenancePlan::getProjectId).collect(Collectors.toList());
        return listByIds(projectIdList);
    }

    public Optional<Project> getOne(Long id) {
        QueryWrapper<Project> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", id);
        return Optional.ofNullable(getOne(queryWrapper));
    }

    /**
     * @param id 项目id
     * @return Project 项目详情
     * @description 查询项目详情
     * @date 2019/12/6 10:51 AM
     */
    public Map<String, Object> detail(Long id) {
        Optional<Project> project = getOne(id);
        List<ProjectUserResponse> userList = projectUserService.getUserList(id, null);
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("project", project);
        resultMap.put("userList", userList);
        return resultMap;
    }

    /**
     * @param project 项目信息
     * @return 是否成功
     * @description 保存项目信息
     * @date 2020/1/14 4:12 下午
     */
    public boolean saveProject(Project project) {
        //按当前日期时间戳自动生成项目编号
        String projectCode = DateUtils.generateCode();
        project.setProjectCode("XM" + projectCode);
        LocalDate now = LocalDate.now();
        LocalDate startDate = project.getStartDate();
        LocalDate endDate = project.getEndDate();
        if (startDate.isEqual(now) || startDate.isBefore(now) && endDate.isAfter(now)) {
            project.setProjectStatus("2");
        }
        return save(project);
    }

    /**
     * @param projectId   项目ID
     * @param mtCompanyId 公司ID
     * @return
     * @description 新增项目及项目服务中消息推送
     * @date 2020/5/5 9:26 下午
     */
    public void sendMessage(Long projectId, Long mtCompanyId, String projectStatus) {
        //消息推送
        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()) {
            ProjectDetailResponse detail = projectAppService.detail(projectId);
            PushMessage pushMessage = PushMessage.workAddProject(detail.getAreaName(), detail.getProjectName(), detail.getNum(), detail.getStartDate(), detail.getAreaDirector());
            pushMessage.sendTokenOnPlatform(jmsMessagingTemplate, pushUserInfos);
            if (ProjectStatus.IN_SERVICE.getCode().equals(projectStatus)) {
                PushMessage.workStartProject(detail.getAreaName(), detail.getProjectName()).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 Integer 成功1或失败0
     * @description 新增项目
     * @date 2019/11/27 2:22 PM
     */
    @Transactional(rollbackFor = Exception.class)
    public RestResponse add(ProjectRequest request) {
        Project project = request.getProject();
        boolean ret = saveProject(project);
        if (!ret) return RestResponse.fail(MessageUtils.get("msg.add.fail"));
        //新增项目消息推送
        sendMessage(project.getId(), project.getMtCompanyId(), project.getProjectStatus());
        //批量新增项目成员信息
        List<ProjectUser> users = request.getUserList();
        users.forEach(user -> user.setProjectId(project.getId()));
        boolean result = projectUserService.saveBatch(users, users.size());
        if (!result) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RestResponse.fail(MessageUtils.get("msg.add.fail"));
        }
        return RestResponse.success(null, MessageUtils.get("msg.add.success"));
    }

    /**
     * @param id          项目id
     * @param mtCompanyId 公司id
     * @return 1.成功, 0.失败, 消息描述
     * @description 删除项目，并删除项目组成员，删除项目关联数据
     * @date 2020/5/26 5:21 下午
     */
    @Transactional(rollbackFor = Exception.class)
    public RestResponse remove(Long id, Long mtCompanyId) {
        //删除项目
        boolean projectResult = removeById(id);
        if (!projectResult) return RestResponse.fail(MessageUtils.get("msg.delete.fail"));
        //删除项目关联
        boolean relevanceResult = projectLiftRelevanceService.removeByMap(id, mtCompanyId);
        if (!relevanceResult) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RestResponse.fail(MessageUtils.get("msg.delete.fail"));
        }
        //删除项目组成员
        boolean userResult = projectUserService.removeByMap(id, mtCompanyId);
        if (!userResult) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RestResponse.fail(MessageUtils.get("msg.delete.fail"));
        }
        return RestResponse.success(null, MessageUtils.get("msg.delete.success"));
    }

    /**
     * @param project 修改项目数据项
     * @return 是否成功
     * @description 修改项目
     * @date 2019/11/27 2:22 PM
     */
    @Transactional(rollbackFor = Exception.class)
    public RestResponse modify(Project project) {
        Optional<Project> oldProject = getOne(project.getId());
        if (!oldProject.isPresent())
            return RestResponse.fail(MessageUtils.get("msg.project.not.exist"));
        boolean result = updateById(project);
        if (!result)
            return RestResponse.fail(MessageUtils.get("msg.modify.fail"));
        Project entry = oldProject.get();
        //生成项目操作记录
        ProjectHistory history = projectHistoryService.createOperaHistory(entry, project, project.getMtCompanyId());
        if (Objects.nonNull(history)) {
            //保存项目操作记录
            boolean projectResult = projectHistoryService.save(history);
            if (!projectResult) {
                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);
    }

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

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

    /**
     * @param request projectId 项目id
     * @return RestResponse 状态码和返回消息
     * @description 项目锁定、解锁,锁定该项目下的电梯
     * @date 2019/12/27 5:04 PM
     */
    @Transactional(rollbackFor = Exception.class)
    public RestResponse projectLockOrUnLock(ProjectRequest request) {
        Project project = new Project();
        project.setId(request.getProjectId());
        project.setLocked(request.getLock());
        int ret = baseMapper.updateById(project);
        if (ret < 0) {
            return RestResponse.fail(MessageUtils.get("msg.modify.fail"));
        }
        //根据项目id和公司id查询项目下电梯
        List<ProjectLiftRelevance> relevanceList = projectLiftRelevanceService.findLiftList(request.getMtCompanyId(), request.getProjectId());
        if (CollUtil.isEmpty(relevanceList)) {
            return RestResponse.success(null, MessageUtils.get("msg.project.status.update"));
        }
        relevanceList.forEach(relevance -> relevance.setLiftLocked(request.getLock()));
        boolean response = projectLiftRelevanceService.updateBatchById(relevanceList);
        if (!response) {
            return RestResponse.fail(MessageUtils.get("msg.modify.fail"));
        }
        return RestResponse.success(null, MessageUtils.get("msg.modify.success"));
    }

    /**
     * @param request 公司id，项目id
     * @return List<MaintenancePlanPrintResponse> 项目管理-维保计划打印列表
     * @description 项目管理-维保计划打印列表
     * @date 2020/3/2 4:54 下午
     */
    public MaintenancePlanPrintResponse planPrint(ProjectRequest request) {
        Integer monthDay = request.getBeginTime().lengthOfMonth();
        //根据项目id查询项目详情
        MaintenancePlanPrintResponse project = baseMapper.findProjectByIdAndCompanyId(request);

        //根据项目id和公司id查询项目下电梯列表
        List<ProjectLiftRelevance> liftList = projectLiftRelevanceService.findLiftList(request.getMtCompanyId(), request.getId());

        List<Long> liftIdList = liftList.stream().map(ProjectLiftRelevance::getLiftId).collect(Collectors.toList());
        List<LiftPrintResponse> liftMaintenancePlanList;
        if (CollUtil.isEmpty(liftIdList)) {
            liftMaintenancePlanList = new ArrayList<>();
        } else {
            //根据公司id和电梯id列表查询维保计划列表
            liftMaintenancePlanList = maintenancePlanService.getLiftMaintenancePlanList(request.getMtCompanyId(), liftIdList, request.getBeginTime());
        }
        project.setLiftList(liftMaintenancePlanList);
        project.setNum(liftList.size());
        project.setMonthDay(monthDay);
        return project;
    }

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

    /**
     * 根据表格解析的数据，组装project
     *
     * @param projectImportModels 解析excel得到项目数据
     * @param mtCompanyId         维保公司
     * @return RestResponse
     * @author wcz
     */
    @Transactional(rollbackFor = Exception.class)
    public RestResponse assemble(List<ProjectImportModel> projectImportModels, Long mtCompanyId) {
        //检查列表有效性
        Validate.notNull(projectImportModels, "没有数据");
        //存放新建的project
        List<Project> projects = new ArrayList<>();
        //存放新建的region
        List<Region> regions = new ArrayList<>();

        //存放新建的propertyCompanies
        List<PropertyCompany> propertyCompanies = new ArrayList<>();

        //存放新建的propertyContacts
        List<PropertyContact> propertyContacts = new ArrayList<>();

        //所有的行政划分信息
        List<AreaCode> areaCodeList = areaCodeService.list();
        Map<Integer, List<AreaCode>> areaCodeMap = areaCodeList.stream().collect(Collectors.groupingBy(AreaCode::getLevel));
        //所有的省数据
        List<AreaCode> provinceList = areaCodeMap.get(1);
        //所有的市数据
        List<AreaCode> cityList = areaCodeMap.get(2);
        //所有的区数据
        List<AreaCode> districtList = areaCodeMap.get(3);

        //根据MtCompanyId查询区域
        List<Region> regionList = regionService.listByMtCompanyId(mtCompanyId);
        //根据MtCompanyId查询甲方公司
        List<PropertyCompany> propertyCompanyList = propertyCompanyService.listByMtCompanyId(mtCompanyId);

        //全部甲方联系人
        List<PropertyContact> propertyContactList = propertyContactService.list();
        log.info("甲方联系人总条数: {}", propertyContactList.size());

        for (int i = 0; i < projectImportModels.size(); i++) {
            ProjectImportModel item = projectImportModels.get(i);
            //0 属性表头，1 文字表头，2 记录行
            int rowNum = i + 2;
            Project project = new Project();
            //复制解析model中的值到project中
            BeanUtil.copyProperties(item, project);
            log.info("复制属性后的project: {}", project);
            //查找省
            String provName = item.getProvince();
            Optional<AreaCode> provOptional = provinceList
                    .stream()
                    .filter(areaCode -> (StrUtil.equals(areaCode.getName(), provName)))
                    .distinct().limit(1).findFirst();

            if (!provOptional.isPresent()) {
                log.error("表格数据有误，行数：{}, {}没有匹配省", rowNum, provName);
                return RestResponse.fail(StrUtil.format("表格数据有误，行数：{}, {}没有匹配省", rowNum, provName));
            }
            //项目中设置省
            AreaCode province = provOptional.get();
            project.setProvince(province.getName());
            project.setProvinceCode(province.getCode());
            // 查找市
            String cityName = item.getCity();
            Optional<AreaCode> cityOptional = cityList
                    .stream()
                    .filter(areaCode -> (StrUtil.equals(areaCode.getName(), cityName)))
                    .distinct().limit(1).findFirst();
            if (!cityOptional.isPresent()) {
                log.error("表格数据有误，行数：{}, {}没有匹配市", rowNum, cityName);
                return RestResponse.fail(StrUtil.format("表格数据有误，行数：{}, {}没有匹配市", rowNum, cityName));
            }
            //项目中设置市
            AreaCode city = cityOptional.get();
            project.setCity(city.getName());
            project.setCityCode(city.getCode());
            //查找区
            String distName = item.getDistrict();
            Optional<AreaCode> distOptional = districtList
                    .stream()
                    .filter(areaCode -> (StrUtil.equals(areaCode.getName(), distName)))
                    .distinct().limit(1).findFirst();
            if (!distOptional.isPresent()) {
                log.error("表格数据有误，行数：{}, {}没有匹配区", rowNum, distName);
                return RestResponse.fail(StrUtil.format("表格数据有误，行数：{}, {}没有匹配区", rowNum, distName));
            }
            //项目中设置区
            AreaCode district = distOptional.get();
            project.setDistrict(district.getName());
            project.setDistrictCode(district.getCode());

            //根据省市查找区域
            String areaName = item.getArea();
            Optional<Region> regionOptional = regionList
                    .stream()
                    .filter(r -> (StrUtil.equals(r.getProvinceCode(), province.getCode()) && StrUtil.equals(r.getCityCode(), city.getCode()) && StrUtil.equals(r.getAreaName(), areaName)))
                    .distinct().limit(1).findFirst();
            //根据省市查找区域,如果区域不存在就新增
            if (!regionOptional.isPresent()) {
                log.error("表格数据有误，行数：{}, {}没有匹配区域", rowNum, areaName);
                return RestResponse.fail(StrUtil.format("表格数据有误，行数：{}, {}没有匹配区域", rowNum, areaName));

                //fixme:待确认，如果表格中导入的区域不存在，直接返回还是新增
//                Region region = new Region();
//                Long regionId = IdWorker.getId();
//                log.info("新建区域. id: {}",regionId);
//                region.setId(regionId);
//                region.setMtCompanyId(mtCompanyId);
//                region.setProvinceCode(province.getCode());
//                region.setCityCode(city.getCode());
//                region.setAreaName(areaName);
//                //
//                region.setAreaCode(PinYinUtils.toFirstChar(areaName));
//                region.setUserId(regionId);
//                //新建区域添加到list中批量插入
//                regions.add(region);
            }
            Region region = regionOptional.get();
            //项目中设置区域id
            project.setRegionId(region.getId());

            //根据名称查询甲方公司
            Long ppCompanyId;
            String ppCompanyName = item.getPpCompanyName();
            Optional<PropertyCompany> ppcOptional = propertyCompanyList
                    .stream()
                    .filter(company -> (StrUtil.equals(company.getName(), ppCompanyName)))
                    .distinct().limit(1).findFirst();
            if (ppcOptional.isPresent()) {
                //如果存在就赋值给ppCompanyId
                ppCompanyId = ppcOptional.get().getId();
            } else {
                //如果维保公司不存在，新建，生成id
                PropertyCompany propertyCompany = new PropertyCompany();
                ppCompanyId = IdWorker.getId();
                log.info("新建甲方公司. id: {}", ppCompanyId);
                propertyCompany.setId(ppCompanyId);
                propertyCompany.setMtCompanyId(mtCompanyId);
                //公司名称
                propertyCompany.setName(ppCompanyName);
                //状态 0删除 1正常 2有关联项目
                propertyCompany.setStatus(2);
                propertyCompany.setCreatorId(ppCompanyId);
                propertyCompany.setCreateDate(LocalDateTime.now());
                //新建甲方公司添加list中批量插入
                propertyCompanies.add(propertyCompany);
            }
            //项目中设置甲方公司
            project.setPpCompanyId(ppCompanyId);

            //根据名称查询甲方联系人
            Long ppContactId;
            String ppCompanyContact = item.getPpCompanyContact();
            String ppTelephone = item.getPpCompanyTelephone();
            Optional<PropertyContact> pptOptional = propertyContactList
                    .stream()
                    .filter(contact -> (StrUtil.equals(contact.getName(), ppCompanyContact) && StrUtil.equals(contact.getTelephone(), ppTelephone) && ppCompanyId == contact.getPpCompanyId()))
                    .distinct().limit(1).findFirst();
            if (pptOptional.isPresent()) {
                //如果存在就取id
                ppContactId = pptOptional.get().getId();
            } else {
                //如果不存在就创建，加入到新增list中
                PropertyContact propertyContact = new PropertyContact();
                ppContactId = IdWorker.getId();
                log.info("新增甲方联系人. id: {}", ppContactId);
                propertyContact.setId(ppContactId);
                propertyContact.setName(ppCompanyContact);
                propertyContact.setTelephone(ppTelephone);
                propertyContact.setPpCompanyId(ppCompanyId);
                //0删除 1正常 2有关联项目
                propertyContact.setStatus(2);
                propertyContact.setCreatorId(ppContactId);
                propertyContact.setCreateDate(LocalDateTime.now());
                //新建的甲方联系人添加到list中批量插入
                propertyContacts.add(propertyContact);
            }
            //项目中设置甲方联系人
            project.setPpContactId(ppContactId);

            //设置项目编码
            project.setProjectCode("XM" + DateUtils.generateCode());
            //项目中设置维保公司id
            project.setMtCompanyId(mtCompanyId);
            //新建project添加到list中批量插入
            projects.add(project);
        }
        //批量插入新增区域信息
        if (!regions.isEmpty()) {
            boolean reg = regionService.saveOrUpdateBatch(regions, regions.size());
            if (!reg) {
                //强制手动事务回滚
                rollback();
                return RestResponse.fail("插入区域信息失败，请稍后重试");
            }
        }
        //批量插入新增甲方公司
        if (!propertyCompanies.isEmpty()) {
            boolean ppc = propertyCompanyService.saveOrUpdateBatch(propertyCompanies, propertyCompanies.size());
            if (!ppc) {
                //强制手动事务回滚
                rollback();
                return RestResponse.fail("插入公司信息失败，请稍后重试");
            }
        }
        //批量插入新增甲方联系人
        if (!propertyContacts.isEmpty()) {
            boolean ppt = propertyContactService.saveOrUpdateBatch(propertyContacts, propertyContacts.size());
            if (!ppt) {
                //强制手动事务回滚
                rollback();
                return RestResponse.fail("插入联系人信息失败，请稍后重试");
            }
        }
        //批量插入项目
        if (!projects.isEmpty()) {
            boolean pro = saveBatch(projects, projects.size());
            if (!pro) {
                rollback();
                return RestResponse.fail("插入项目信息失败，请稍后重试");
            }
        }
        return RestResponse.success("导入成功");
    }
}
