package com.yeejoin.amos.maintenance.business.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.Sequence;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.yeejoin.amos.feign.privilege.model.AgencyUserModel;
import com.yeejoin.amos.maintenance.business.constants.XJConstant;
import com.yeejoin.amos.maintenance.business.dao.mapper.InputItemMapper;
import com.yeejoin.amos.maintenance.business.dao.mapper.PointMapper;
import com.yeejoin.amos.maintenance.business.dao.mapper.RouteMapper;
import com.yeejoin.amos.maintenance.business.dao.repository.*;
import com.yeejoin.amos.maintenance.business.dto.PointDto;
import com.yeejoin.amos.maintenance.business.entity.mybatis.CheckPtListBo;
import com.yeejoin.amos.maintenance.business.feign.EquipFeignClient;
import com.yeejoin.amos.maintenance.business.param.*;
import com.yeejoin.amos.maintenance.business.service.intfc.IPointService;
import com.yeejoin.amos.maintenance.business.util.DaoCriteria;
import com.yeejoin.amos.maintenance.business.vo.*;
import com.yeejoin.amos.maintenance.common.enums.PointStatusEnum;
import com.yeejoin.amos.maintenance.core.common.request.CommonPageable;
import com.yeejoin.amos.maintenance.core.common.response.PointResponse;
import com.yeejoin.amos.maintenance.core.util.StringUtil;
import com.yeejoin.amos.maintenance.core.util.query.BaseQuerySpecification;
import com.yeejoin.amos.maintenance.dao.entity.*;
import com.yeejoin.amos.maintenance.exception.YeeException;
import com.yeejoin.amos.maintenance.feign.RemoteSecurityService;
import com.yeejoin.amos.safety.common.cache.PointStatusCache;
import org.apache.commons.lang.StringUtils;
import org.assertj.core.util.Sets;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.typroject.tyboot.core.foundation.utils.Bean;

import javax.annotation.Resource;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.math.BigInteger;
import java.util.*;
import java.util.stream.Collectors;

@Service("pointService")
public class PointServiceImpl implements IPointService {

    @Autowired
    private IPointDao iPointDao;

    @Autowired
    private IPointClassifyDao iPointClassifyDao;

    @Autowired
    private IPointInputItemDao iPointInputItemDao;

    @Autowired
    private IPointPhotoDao iPointPhotoDao;

    @Autowired
    private IRoutePointDao iRoutePointDao;

    @Autowired
    private IPlanTaskDetailDao iPlanTaskDetailDao;

    @Autowired
    private IRoutePointItemDao iRoutePointItemDao;

    @Resource
    private PointMapper pointMapper;

    @Resource
    private RouteMapper routeMapper;

    @Autowired
    private ICatalogTreeDao catalogTreeDao;
    @Autowired
    private InputItemMapper inputItemMapper;

    @Resource
    IPlanTaskDao planTaskDao;
    @Autowired
    private RemoteSecurityService remoteSecurityService;
    @Autowired
    private EquipFeignClient equipFeign;

    @Autowired
    Sequence sequence;

    @Override
    @Transactional
    public Point addPoint(PointParam pointParam) {
        // 保存点基本信息
        Point point = pointParam.getPoint();
        point.setIsDelete(false);
        iPointDao.saveAndFlush(point);
        addClassifyAndInputItem(pointParam, point);
        return point;
    }

    @Override
    public void addMovePoint(MovePointParam param) {
        Point point = new Point();
        BeanUtils.copyProperties(param, point);
        point.setIsFixed("0");
        iPointDao.saveAndFlush(point);
        List<PointInputItem> pointInputItems = new ArrayList<>();
        if (!ObjectUtils.isEmpty(param.getInputItems())) {
            String[] ids = param.getInputItems().split(",");
            int index = 0;
            for (String id : ids) {
                PointInputItem item = new PointInputItem();
                item.setInputItemId(Integer.parseInt(id));
                item.setOrderNo(index++);
                item.setPointId(point.getId());
                item.setCreateDate(new Date());
                pointInputItems.add(item);
            }
            iPointInputItemDao.saveAll(pointInputItems);
        }
    }

    @Override
    public List<Long> addImportPoint(List<PointImportParam> list, String orgCode, String userId) {
        List<Long> ids = new ArrayList<>();

        String structListString = equipFeign.getStructureNameAll();
        JSONObject jsonObject = JSONObject.parseObject(structListString);
        JSONArray structList = jsonObject.getJSONArray("result");
        for (PointImportParam param : list) {
            Point point = new Point();
            // BeanUtils.copyProperties(param, point);
            int count = iPointDao.findByPointNo(param.getPointNo(), orgCode);
            // 该单位已存在该编号的点
            if (count > 0) {
                continue;
            }
            point.setAddress(param.getAddress());
            point.setCatalogId(param.getCatalogId() == null ? 0 : param.getCatalogId());
            point.setChargePersonId(param.getChargePersonId());
            // point.setDistance(param.getDistance() == null ? 0 :
            // param.getDistance());
            // point.setExtendJson(param.getExtendJson());
            point.setFixedShot(param.getFixedShot() == null ? 0 : param.getFixedShot());
            point.setIsFixed(param.getIsFixed());
            point.setIsScore(param.getIsScore());
            // point.setLatitude(param.getLatitude());
            // point.setLongitude(param.getLongitude());
            point.setLevel(param.getLevel());
            point.setName(param.getName());
            point.setOffline(param.getOffline().equals("1") ? true : false);
            point.setPointNo(param.getPointNo());
            point.setRemark(param.getRemark());
            // point.setRouteId(param.getRouteId());
            // point.setRouteName(param.getRouteName());
            // point.setSaveGps(param.getSaveGps());
            point.setShotMaxNumber(param.getShotMaxNumber() == null ? 0 : param.getShotMaxNumber());
            point.setShotMinNumber(param.getShotMinNumber() == null ? 0 : param.getShotMinNumber());
            // point.setUsuallyShot(param.getUsuallyShot());
            point.setCoordinates(param.getCoordinates());
            point.setFloor(param.getFloor());
            point.setIsDelete(false);
            point.setOrgCode(orgCode);
            point.setCreateDate(new Date());
            point.setCreatorId(userId);
            point.setIsIndoor(param.getIsIndoor().equals("1") ? true : false);
            CatalogTree catalog = catalogTreeDao.findOneByNameAndOrgCode(param.getCatalogName(),
                    orgCode);

            point.setCatalogId(catalog.getId());
            if (!org.springframework.util.StringUtils.isEmpty(param.getAddress())) {
                for (int i = 0; i < structList.size(); i++) {
                    if (structList.getJSONObject(i).get("name").equals(param.getAddress())) {
                        point.setRiskSourceId(structList.getJSONObject(i).get("id").toString());
                    }
                }
            }
            iPointDao.saveAndFlush(point);
            ids.add(point.getId());
            String inputItems = param.getInputItems();
            if (!ObjectUtils.isEmpty(inputItems)) {
                String[] itemNos = inputItems.replaceAll(" ", "").split(",");

                List<InputItemVo> inputItemList = inputItemMapper.getInputItemListByitemNos(itemNos);
                int orderNo = 0;
                for (InputItemVo inputItem : inputItemList) {
                    PointInputItem pointInputItem = new PointInputItem();
                    pointInputItem.setPointId(point.getId());
                    pointInputItem.setInputItemId(inputItem.getId());
                    // pointInputItem.setClassifyIds(0);
                    pointInputItem.setId(0);
                    pointInputItem.setOrderNo(orderNo++);
                    iPointInputItemDao.save(pointInputItem);
                }
            }
        }
        return ids;
    }

    /**
     * 增加点的分类和项
     *
     * @param pointParam 页面参数
     * @param point      点基本信息
     */
    private void addClassifyAndInputItem(PointParam pointParam, Point point) {
        long pointId = point.getId();
        // 1.保存点的巡检项信息
        List<PointInputItemVo> pointInputItemVoList = pointParam.getInputItemVoInfo();
        List<PointInputItem> pointInputItems = new ArrayList<>();
        for (PointInputItemVo pointInputItemVo : pointInputItemVoList) {
            PointInputItem pointInputItem = new PointInputItem();
            pointInputItem.setPointId(pointId);
            pointInputItem.setInputItemId(pointInputItemVo.getInputItemId());
            pointInputItem.setId(0);
            pointInputItem.setOrderNo(pointInputItemVo.getpOrderNo());
            pointInputItem.setClassifyIds("");
            pointInputItems.add(pointInputItem);
        }
        if (!pointInputItems.isEmpty()) {
            iPointInputItemDao.saveAll(pointInputItems);
        }
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<Long> delPointById(Long[] ids) {
        List<Long> idList = new ArrayList<Long>();
        idList.addAll(Arrays.asList(ids));
        List<PointInputItem> pointInputItem = iPointInputItemDao.findAllById(idList);
        List<Long> pointInputItemIds = Lists.transform(pointInputItem, PointInputItem::getId);
        // 物理删除p_point_inputitem表对应行
        iPointInputItemDao.deleteByPointId(idList);
        // 物理删除p_route_point、p_route_point_item中相关行
        List<BigInteger> routePointIdList = iRoutePointDao.queryRoutePointByPointId(idList);
        for (BigInteger routePointId : routePointIdList) {
            iRoutePointItemDao.delRoutePointItem(routePointId.longValue());
            iRoutePointDao.deleteById(Long.parseLong(routePointId.toString()));
        }
        for (long pointId : idList) {
            List<PlanTaskDetail> planDetailList = iPlanTaskDetailDao.findALLByPointId(pointId);
            for (PlanTaskDetail planTaskDetail : planDetailList) {
                PlanTask planTask = planTaskDao.findById(planTaskDetail.getTaskNo()).get();
                if (planTask.getFinishStatus() > 1) {
                    continue;
                }
                if (1 == planTaskDetail.getIsFinish()) {
                    planTask.setFinishNum(planTask.getFinishNum() - 1);
                    planTask.setPointNum(planTask.getPointNum() - 1);
                    planTaskDao.save(planTask);
                } else {
                    planTask.setPointNum(planTask.getPointNum() - 1);
                    planTaskDao.save(planTask);
                }
            }
        }
        // 删除p_plan_task_detail相关行
        iPlanTaskDetailDao.deletePlanTaskDetailByPointId(idList);
        // 删除p_point相关行
        iPointDao.delPointById(idList);
        return idList;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Point updatePoint(PointParam pointParam) {
        //1.更新点
        long pointId = pointParam.getPoint().getId();
        Point newPoint = iPointDao.findById(pointId).orElseThrow(()->new RuntimeException("找不到原始数据"));
        Bean.copyExistPropertis(pointParam.getPoint(), newPoint);
        newPoint.setLastUpdateTime(new Date());
        iPointDao.save(newPoint);
        //2.删除点项关系，路线点项关系
        //2.1计算交集
        List<PointInputItemVo> oldInputItemList = queryOldPointInputItem(pointId);
        Set<Long> sOldItemIds = oldInputItemList.stream().map(PointInputItemVo::getPointItemId).collect(Collectors.toSet());
        List<PointInputItemVo> newInputItemList = pointParam.getInputItemVoInfo();
        Set<Long> sNewItemIds = newInputItemList.stream().map(PointInputItemVo::getId).collect(Collectors.toSet());
        //旧id和新id(页面提交回来的)差集删除
        List<Long> deletePointItemIds = sOldItemIds.stream().filter(o -> !sNewItemIds.contains(o)).collect(Collectors.toList());
        if (deletePointItemIds.size() > 0) {
            iPointInputItemDao.delPointInputItemById(deletePointItemIds);
            iRoutePointItemDao.delRoutePointItemByItemId(deletePointItemIds);
        }
        //3.重新建立点项关系
        List<PointInputItem> pointInputItems = new ArrayList<>();
        newInputItemList.forEach(item -> {
            PointInputItem pointInputItem = new PointInputItem();
            pointInputItem.setId(item.getPointItemId());
            pointInputItem.setInputItemId(item.getInputItemId());
            pointInputItem.setPointId(pointId);
            pointInputItem.setClassifyIds("");
            pointInputItem.setOrderNo(item.getpOrderNo());
            pointInputItem.setCreateDate(new Date());
            pointInputItems.add(pointInputItem);
        });
        iPointInputItemDao.saveAll(pointInputItems);
        return newPoint;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveAs(Long[] pointIds) {
        // 保存点所有巡检项、点图片信息、点的扩展分类信息
        for (Long pointId : pointIds) {
            Point point = iPointDao.findById(pointId).get();
            List<PointInputItemVo> inputItemList = queryPointInputItem(pointId);
            inputItemList.forEach(i -> {
                i.setInputItemId(i.getId());
            });
            Point newPoint = new Point();
            BeanUtils.copyProperties(point, newPoint);
            newPoint.setName(point.getName() + "复制");
            newPoint.setPointNo(point.getPointNo() + "_copy");
            newPoint.setId(0);
            newPoint.setStatus(PointStatusEnum.UNPLAN.getCode());
            PointParam pointParam = new PointParam();
            pointParam.setPoint(newPoint);
            pointParam.setInputItemVoInfo(inputItemList);
            addPoint(pointParam);
        }
    }

    @Override
    public Point queryPointById(Long id) {
        return iPointDao.findById(id).get();
    }


    @Override
    public Page<PointVo> queryPointInfo(List<DaoCriteria> criterias, CommonPageable commonPageable, String loginOrgCode) {
        BaseQuerySpecification<Point> spec = new BaseQuerySpecification<>(criterias);
        Order idOrder = new Order(Direction.DESC, "id");
        List<Order> orders = new ArrayList<Order>();
        orders.add(idOrder);
        Sort sort = Sort.by(orders);
        commonPageable.setSort(sort);
        Page<Point> pointPage = iPointDao.findAll(spec, commonPageable);
        List<PointInputItem> pointInputItems = iPointInputItemDao.findAll();
        List<PointVo> pointVoList = new ArrayList<>();
        for (Point point : pointPage) {
            PointVo pointVo = new PointVo();
            BeanUtils.copyProperties(point, pointVo);
            pointVo.setInputItemNum(pointInputItems.stream().filter(i -> i.getPointId() == point.getId()).count());
            String buildingName = StringUtil.isNotEmpty(point.getBuildingName()) ? point.getBuildingName() : "";
            String address = StringUtil.isNotEmpty(point.getAddress()) ? point.getAddress() : "";
            pointVo.setPosition(buildingName + address);
            pointVoList.add(pointVo);
        }
        Pageable pageable = new CommonPageable(pointPage.getNumber(), pointPage.getSize(), pointPage.getSort());
        return new PageImpl<>(pointVoList, pageable, pointPage.getTotalElements());
    }

    @Override
    public List<PointVo> queryAllPoint(List<DaoCriteria> criterias) {
        BaseQuerySpecification<Point> spec = new BaseQuerySpecification<>(criterias);
        Order idOrder = new Order(Direction.DESC, "id");
        List<Order> orders = new ArrayList<Order>();
        orders.add(idOrder);
        Sort sort = Sort.by(orders);
        List<PointVo> returnList = new ArrayList<>();
        List<Point> list = iPointDao.findAll(spec, sort);
        if (!CollectionUtils.isEmpty(list)) {
            for (Point point : list) {
                PointVo pointVo = new PointVo();
                BeanUtils.copyProperties(point, pointVo);
                returnList.add(pointVo);
            }
        }
        return returnList;
    }

    @Override
    public List<PointInputItemVo> queryPointInputItem(Long pointId) {
        return pointMapper.getPointInputItemById1(pointId, null);
    }

    @Override
    public List<PointPhoto> queryPointPhoto(Long pointId) {
        return null;
    }

    @Override
    public List<PointClassify> queryPointClassify(Long pointId) {
        return iPointClassifyDao.getPointClassifyByPointId(pointId);
    }

    @Override
    public List<PointInputItemVo> queryPointInputItemByClassify(Long pointId, Long classifyId) {
        return pointMapper.getPointInputItemById(pointId, classifyId);
    }

    @Override
    public List<Point> queryPointList(List<String> ids, List<String> names, String orgCode) {
        return iPointDao.findAll(getPointSpecification(ids, names, orgCode));
    }

    private Specification getPointSpecification(List<String> ids, List<String> names, String orgCode) {
        return new Specification<Point>() { // 构建查询条件
            @Override
            public Predicate toPredicate(Root<Point> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> predicate = new ArrayList<>();
                if (!ObjectUtils.isEmpty(orgCode)) {
                    predicate.add(cb.equal(root.get("orgCode").as(String.class), orgCode));
                }
                if (!ObjectUtils.isEmpty(names)) {
                    List<Predicate> namePredicate = new ArrayList<>();
                    for (String name : names) {
                        namePredicate.add(cb.like(root.get("name").as(String.class), "%" + name + "%"));
                    }
                    Predicate[] pre = new Predicate[namePredicate.size()];
                    predicate.add(cb.or(namePredicate.toArray(pre)));
                }
                if (!ObjectUtils.isEmpty(ids)) {
                    List<Predicate> noPredicate = new ArrayList<>();
                    for (String id : ids) {
                        noPredicate.add(cb.like(root.get("pointNo").as(String.class), "%" + id + "%"));
                    }
                    Predicate[] pre = new Predicate[noPredicate.size()];
                    predicate.add(cb.or(noPredicate.toArray(pre)));
                }

                Predicate[] pre = new Predicate[predicate.size()];
                return query.where(predicate.toArray(pre)).getRestriction();
            }
        };
    }

    @Override
    public Point queryPointByPointNo(HashMap<String, Object> params) {

        return iPointDao.findOne(new Specification<Point>() {

            @Override
            public Predicate toPredicate(Root<Point> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
                List<Predicate> predicate = new ArrayList<>();
                if (!ObjectUtils.isEmpty(params.get("pointNo"))) {
                    predicate.add(cb.equal(root.get("pointNo").as(String.class), params.get("pointNo")));
                }
                if (!ObjectUtils.isEmpty(params.get("orgCode"))) {
                    predicate.add(cb.equal(root.get("orgCode").as(String.class), params.get("orgCode").toString()));
                }
                Predicate[] pre = new Predicate[predicate.size()];
                return query.where(predicate.toArray(pre)).getRestriction();
            }
        }).get();
    }

    @Override
    public Point setPatrolMode(Long pointId, Boolean isOffine) {
        if (iPointDao.existsById(pointId)) {
            Point point = iPointDao.findById(pointId).get();
            point.setOffline(isOffine);
            return iPointDao.save(point);
        }
        return null;
    }

    @Override
    public Page<PointVo> queryPointByPage(HashMap<String, Object> param, CommonPageable commonPageable) {
        int count = pointMapper.getPointCountByCondition(param);
        param.put("offset", commonPageable.getPageNumber() * commonPageable.getPageSize());
        param.put("pageSize", commonPageable.getPageSize());
        List<PointVo> list = pointMapper.getPointByCondition(param);
        Page<PointVo> pointVoPage = new PageImpl<>(list, commonPageable, count);
        return pointVoPage;
    }

    @Override
    public Map queryPointDetailById(Long id) {
        Map<String, Object> resp = new HashMap<String, Object>();
        Map<String, Object> point = pointMapper.getPointById(id);

        List<Map<String, Object>> inputItem = pointMapper.getPointInputItem(id);
        List<Map<String, Object>> routes = pointMapper.getPointRoute(id);
        List<Map<String, Object>> classify = pointMapper.getPointClassify(id);

        resp.put("point", point);
        resp.put("inputItems", inputItem);
        resp.put("routes", routes);
        resp.put("classify", classify);
        return resp;
    }

    @Override
    public Map queryPointDetailById1(String toke, String product, String appKey, Long id) {
        Map<String, Object> resp = new HashMap<String, Object>();
        Map<String, Object> point = pointMapper.getPointById(id);

        if (StringUtil.isNotEmpty(point.get("depid"))) {
            List<LinkedHashMap> departmentBos = remoteSecurityService.listDepartmentByDeptIds(toke, product, appKey, point.get("depid") + "");
            if (departmentBos != null && departmentBos.size() > 0) {
                for (int i = 0; i < departmentBos.size(); i++) {
                    point.put("departmentName", departmentBos.get(i).get("departmentName"));


                }
            }

        }

        // deptName = checkPointBo.getExecuteDeptId();
        if (StringUtil.isNotEmpty(point.get("userName"))) {
            List<AgencyUserModel> userModels = remoteSecurityService.listUserByUserIds(toke, product, appKey, point.get("userName") + "");
            String userName = "";
            if (userModels != null && userModels.size() > 0) {
                for (int i = 0; i < userModels.size(); i++) {
                    if (i == userModels.size() - 1) {
                        userName = userName + userModels.get(i).getRealName();
                    } else {
                        userName = userName + userModels.get(i).getRealName() + ",";
                    }

                }
                point.put("userName", userName);
            }


        }


        List<Map<String, Object>> routes = pointMapper.getPointRoute(id);
        List<HashMap<String, Object>> classify = pointMapper.getPointInputClassifyInfo(id);
        Map<String, List<HashMap<String, Object>>> inputItems = new HashMap<String, List<HashMap<String, Object>>>();
        if (!classify.isEmpty()) {
            classify.forEach(action -> {
                if (StringUtil.isNotEmpty(action.get("classifyName"))) {
                    if (inputItems.containsKey(action.get("classifyName").toString())) {
                        List<HashMap<String, Object>> list = inputItems.get(action.get("classifyName").toString());
                        list.add(action);
                    } else {
                        List<HashMap<String, Object>> list = new ArrayList<HashMap<String, Object>>();
                        list.add(action);
                        inputItems.put(action.get("classifyName").toString(), list);
                    }
                } else {
                    if (inputItems.containsKey("其他")) {
                        List<HashMap<String, Object>> list = inputItems.get("其他");
                        list.add(action);
                    } else {
                        List<HashMap<String, Object>> list = new ArrayList<HashMap<String, Object>>();
                        list.add(action);
                        inputItems.put("其他", list);
                    }
                }
            });
        }
        resp.put("point", point);
        resp.put("inputItems", inputItems);
        resp.put("routes", routes);
        return resp;

    }

    @Override
    public Map queryPointDetailByIdInVersion2(Long id) {
        Map<String, Object> resp = new HashMap<>();
        Map<String, Object> point = pointMapper.getPointById(id);
        List<Map<String, Object>> routes = pointMapper.getPointRoute(id);
        resp.put("point", point);
        resp.put("inputItems", getClassifyRiskDescMap(id));
        resp.put("routes", routes);
        return resp;
    }

    @Override
    public JSONObject getClassifyRiskDescMap(Long id) {
//        List<HashMap<String, Object>> classify = pointMapper.getPointInputClassifyInfo(id);
        List<PointInputItemVo> pointInputItemVo = queryPointClassInputItem(id);
        return getClassifyRiskDescMap(pointInputItemVo);
    }

    @Override
    public JSONObject getClassifyRiskDescMap(List<PointInputItemVo> pointInputItemVo) {
        JSONObject inputItems = new JSONObject();
        if (!pointInputItemVo.isEmpty()) {
            pointInputItemVo.forEach(action -> {
                String classifyName = "其他";
                if (StringUtil.isNotEmpty(action.getClassifyNames())) {
                    classifyName = action.getClassifyNames();
                }
                String riskDesc = XJConstant.DEFAULT_RISKDESC;
                if (StringUtil.isNotEmpty(action.getRiskDesc())) {
                    riskDesc = action.getRiskDesc();
                }
                JSONObject classifyJson;
                if (inputItems.containsKey(classifyName)) {
                    classifyJson = inputItems.getJSONObject(classifyName);
                } else {
                    classifyJson = new JSONObject();
                }
                JSONArray riskDescArr;
                if (classifyJson.containsKey(riskDesc)) {
                    riskDescArr = classifyJson.getJSONArray(riskDesc);
                } else {
                    riskDescArr = new JSONArray();
                }
                if (StringUtils.isEmpty(action.getRiskDesc())) {
                    action.setRiskDesc(riskDesc);
                }
                riskDescArr.add(action);
                classifyJson.put(riskDesc, riskDescArr);
                inputItems.put(classifyName, classifyJson);
            });
        }
        return inputItems;
    }

    @Override
    public Map<String, PointClassifyVo> queryPointClassifyWithInputItemVo(Long pointId) {
        List<PointClassify> pointClassifyList = iPointClassifyDao.getPointClassifyByPointId(pointId); // 点分类列表
        List<PointInputItemVo> classifiedInputItemList = new ArrayList<>(); // 所有已分类项的列表
        Map<String, PointClassifyVo> classifyInputItemMap = new HashMap<>();
        for (PointClassify pointClassify : pointClassifyList) {
            List<PointInputItemVo> inputItemList = pointMapper.getPointInputItemById(pointId, pointClassify.getId());
            PointClassifyVo pointClassifyVo = new PointClassifyVo();
            BeanUtils.copyProperties(pointClassify, pointClassifyVo);
            pointClassifyVo.setPointInputItemVo(inputItemList);
            classifyInputItemMap.put(pointClassify.getName() + "*" + pointClassify.getOrderNo(), pointClassifyVo);
            for (int i = 0; i < inputItemList.size(); i++) {
                if (!classifiedInputItemList.contains(inputItemList.get(i))) {
                    classifiedInputItemList.add(inputItemList.get(i));
                }
            }
        }

        return classifyInputItemMap;
    }

    @Override
    public List<PointVo> queryPointInfoList(List<DaoCriteria> criterias) {
        BaseQuerySpecification<Point> spec = new BaseQuerySpecification<>(criterias);
        List<Point> pointList = iPointDao.findAll(spec);
        List<PointVo> pointVoList = new ArrayList<>();
        for (Point point : pointList) {
            PointVo pointVo = new PointVo();
            BeanUtils.copyProperties(point, pointVo);
            pointVo.setShotNumber(point.getShotMinNumber() + "-" + point.getShotMaxNumber());
            CatalogTree cataTree = catalogTreeDao.findById(point.getCatalogId()).get();
            String catalogName = cataTree != null ? cataTree.getName() : "";
            pointVo.setCatalogName(catalogName);
            List<String> routeNameList = routeMapper.getRouteNameByPointId(point.getId());
            String routeNames = StringUtils.join(routeNameList.toArray(), ",");
            pointVo.setRouteName(routeNames);
            List<String> inputItemNameList = new ArrayList<>();
            for (InputItem inputItem : queryPointInputItem(point.getId())) {
                inputItemNameList.add(inputItem.getName());
            }
            String inputItemName = StringUtils.join(inputItemNameList.toArray(), ",");
            ;
            pointVo.setInputItemName(inputItemName);
            pointVoList.add(pointVo);
        }
        return pointVoList;
    }

    @Override
    public List<PointVo> queryPointInfoListByIds(PointImportQueryParam pointImportQueryParam) {
        return pointMapper.getPointVoByIds(pointImportQueryParam);
    }

    @Override
    public List<HashMap<String, Object>> getSumPtByRole(HashMap<String, Object> paramMap) {
        List<HashMap<String, Object>> content = null;
        if (XJConstant.ADMIN_FLAG.equals(paramMap.get("roleFlag"))) {
            content = pointMapper
                    .getSumPtForAdmin(paramMap.get("orgCode") == null ? null : paramMap.get("orgCode").toString());
        } else if (XJConstant.DEPART_FLAG.equals(paramMap.get("roleFlag"))) {
            content = pointMapper
                    .getSumPtForDept(paramMap.get("orgCode") == null ? null : paramMap.get("orgCode").toString());
        } else if (XJConstant.PERSON_FLAG.equals(paramMap.get("roleFlag"))) {

        }
        List<Map<String, String>> statusEnums = PointStatusEnum.getEnumList();
        List<HashMap<String, Object>> rContent = new ArrayList<>();
        for (Map<String, String> statusEnum : statusEnums) {
            String code = statusEnum.get("value");
            boolean isCreate = true;
            for (HashMap<String, Object> c : content) {
                if (code.equals(c.get("status"))) {
                    isCreate = false;
                    rContent.add(c);
                    break;
                }
            }
            if (isCreate) {
                HashMap<String, Object> temp = new HashMap<>();
                temp.put("name", statusEnum.get("name"));
                temp.put("status", code);
                temp.put("value", 0);
                rContent.add(temp);
            }
        }
        return rContent;
    }

    @Override
    public Page<CheckPtListBo> getCheckPtList(String toke, String product, String appKey, CheckPtListPageParam param) {
        long total = pointMapper.getCheckPointCount(param);
        List<CheckPtListBo> content = pointMapper.getCheckPointList(param);

        //查询用户名称和部门名称

        if (!CollectionUtils.isEmpty(content)) {
            Set<String> userIds = Sets.newHashSet(Lists.transform(content, CheckPtListBo::getRealName));
            userIds.remove(null);
            userIds.remove("");
            Set<String> deptIds = Sets.newHashSet(Lists.transform(content, CheckPtListBo::getGroupName));
            deptIds.remove("");
            deptIds.remove(null);
            List<AgencyUserModel> userModels = remoteSecurityService.listUserByUserIds(toke, product, appKey, Joiner.on(",").join(userIds));
            Map<String, String> deptMap = new HashMap<String, String>();
            if (!CollectionUtils.isEmpty(deptIds)) {
                List<LinkedHashMap> deptList = remoteSecurityService.listDepartmentByDeptIds(toke, product, appKey, Joiner.on(",").join(deptIds));
                //deptMap = deptList.stream().collect(Collectors.toMap(DepartmentModel::getSequenceNbr, DepartmentModel::getDepartmentName));

                for (int i = 0; i < deptList.size(); i++) {
                    deptMap.put(deptList.get(i).get("sequenceNbr").toString(), deptList.get(i).get("departmentName").toString());
                }


            }
            Map<String, String> userModelMap = userModels.stream().collect(Collectors.toMap(AgencyUserModel::getUserId, AgencyUserModel::getRealName, (k1, k2) -> k2));
            Map<String, String> deptMapNew = deptMap;
            List<String> userNames = new ArrayList<>();

            content.forEach(e -> {
                userNames.clear();
                if (e.getRealName() != null) {
                    List<String> userIds1 = Arrays.asList(e.getRealName().split(","));
                    for (String userId : userIds1) {
                        userNames.add(userModelMap.get(userId));
                    }
                    userNames.remove(null);
                    e.setRealName(Joiner.on(",").join(userNames));
                    e.setGroupName(deptMapNew.get(e.getGroupName()));
                }
            });
        }


        Page<CheckPtListBo> result = new PageImpl<CheckPtListBo>(content, param, total);
        return result;
    }

    @Override
    public CheckPtListBo qryPointByID(int pointID) {
        CheckPtListBo point = pointMapper.getCheckPointById(pointID);
        return point;
    }

    @Override
    public List<PointClassify> queryClassByIds(List<Long> ids) {
        return iPointClassifyDao.findAllById(ids);
    }

    @Override
    public void initPointStatus() {
        // TODO Auto-generated method stub
        List<Point> pointList = iPointDao.findAll();
        pointList.forEach(point -> {
            PointStatusCache.getInstance().putPointStatus(point.getId(), point.getStatus());
            ;
        });
    }

    @Override
    public HashMap<String, Object> queryPointPie(HashMap<String, Object> params) {
        return pointMapper.queryPointPie(params);
    }

    @Override
    public List<String> qryPointNoList(List<DaoCriteria> criterias, Long pointId) {
        BaseQuerySpecification<Point> spec = new BaseQuerySpecification<>(criterias);
        List<Point> pointList = iPointDao.findAll(spec);
        List<String> pointNoList = new ArrayList<>();
        for (Point point : pointList) {
            if (point.getId() != pointId) {
                pointNoList.add(point.getPointNo());
            }
        }
        return pointNoList;
    }

    @Override
    public List<HashMap<String, Object>> queryPointHistogram(HashMap<String, Object> params) {
        return pointMapper.queryPointHistogram(params);
    }

    @Override
    public long getPointCountByOrgCode(String loginOrgCode) {
        return pointMapper.getPointCountByOrgCode(loginOrgCode);
    }

    @Override
    public List<LeavelMovePointVo> queryLeavelPoint(String toke, String product, String appKey, String orgCode, String startTime) {
        List<LeavelMovePointVo> content = pointMapper.queryLeavelPoint(orgCode, startTime);
        String userIds = "";
        String deptIds = "";
        Set<String> set = new HashSet<>();
        Set<String> deptIdSet = new HashSet<>();
        content.forEach(s -> {
            if (s.getChargePerson() != null && !"".equals(s.getChargePerson())) {
                set.add(s.getChargePerson());
            }
            if (s.getDepartmentName() != null && !"".equals(s.getDepartmentName())) {
                deptIdSet.add(s.getDepartmentName());
            }
        });

        List<String> userList = new ArrayList<>(set);
        List<String> deptList = new ArrayList<>(deptIdSet);

        Map<String, String> LoginName = new HashMap<>();
        Map<String, String> userMap = new HashMap<>();
        Map<String, String> deptMap = new HashMap<String, String>();
        if (!CollectionUtils.isEmpty(userList)) {
            userIds = String.join(",", userList);

            List<AgencyUserModel> userModelList = remoteSecurityService.listUserByUserIds(toke, product, appKey, userIds);
            userMap = userModelList.stream().collect(Collectors.toMap(AgencyUserModel::getUserId, AgencyUserModel::getRealName, (k1, k2) -> k2));
            for (AgencyUserModel agencyUserModel : userModelList) {
                LoginName.put(agencyUserModel.getUserId(), agencyUserModel.getMobile() != null ? agencyUserModel.getMobile() : agencyUserModel.getLandlinePhone());
            }

        }
        if (!CollectionUtils.isEmpty(deptList)) {
            List<LinkedHashMap> deptList1 = remoteSecurityService.listDepartmentByDeptIds(toke, product, appKey, Joiner.on(",").join(deptList));
            //deptMap = deptList.stream().collect(Collectors.toMap(DepartmentModel::getSequenceNbr, DepartmentModel::getDepartmentName));

            for (int i = 0; i < deptList1.size(); i++) {
                deptMap.put(deptList1.get(i).get("sequenceNbr").toString(), deptList1.get(i).get("departmentName").toString());
            }


        }
        Map<String, String> deptMapNew = deptMap;


        List<String> userNames = new ArrayList<>();
        Map<String, String> finalUserMap = userMap;
        Map<String, String> finalDeptMap = LoginName;
        content.forEach(c -> {
            userNames.clear();
            if (c.getChargePerson() != null && !"".equals(c.getChargePerson())) {
                List<String> userIdsList = Arrays.asList(c.getChargePerson().split(","));
                for (String userId : userIdsList) {
                    userNames.add(finalUserMap.get(userId));
                }
                userNames.remove(null);
                c.setChargePerson(Joiner.on(",").join(userNames));
            }
            if (c.getDepartmentName() != null && !"".equals(c.getDepartmentName())) {
                c.setDepartmentName(deptMapNew.get(c.getDepartmentName()));
            }


        });
        return content;
    }

    @Override
    public List<Map<String, Object>> getPoints() {
        // TODO Auto-generated method stub
        return pointMapper.getPoints();
    }

    @Override
    public List<Map<String, Object>> queryPointClassifyByRouteIdAndPointId(Long routeId, Long pointId) {
        // TODO Auto-generated method stub
        return pointMapper.queryPointClassifyByRouteIdAndPointId(routeId, pointId);
    }

    @Override
    public List<PointInputItemVo> queryOldPointInputItem(Long pointId) {
        return pointMapper.getPointInputItemById1(pointId, null);
    }

    @Override
    public List<PointResponse> getPointConfigDom() {
        // TODO Auto-generated method stub
        return pointMapper.getPointConfigDom();
    }

    // @Override
    // public PointInfoSyn3DRespone pushPointTo3D(long pointId) {
    // List<Map<String,Object>> result = pointMapper.getPointInfoById(pointId);
    // PointInfoSyn3DRespone pointInfoResponse = new PointInfoSyn3DRespone();
    // List<PointUserSyn3DRespone> users = new
    // ArrayList<PointUserSyn3DRespone>();
    // if(!result.isEmpty()){
    // result.forEach(action->{
    // pointInfoResponse.setPointId(getValue(action.get("pointId")));
    // pointInfoResponse.setPointName(getValue(action.get("pointName")));
    // pointInfoResponse.setPointLevel(getValue(action.get("pointLevel")));
    // pointInfoResponse.setStatus(getValue(action.get("status")));
    // pointInfoResponse.setCoordinates(getValue(action.get("coordinates")));
    // pointInfoResponse.setAddress(getValue(action.get("address")));
    // PointUserSyn3DRespone pointUserSyn3DRespone = new
    // PointUserSyn3DRespone();
    // pointUserSyn3DRespone.setUserId(getValue(action.get("userId")));
    // pointUserSyn3DRespone.setUserName(getValue(action.get("userName")));
    // pointUserSyn3DRespone.setOrgCode(getValue(action.get("orgCode")));
    // pointUserSyn3DRespone.setGroupName(getValue(action.get("groupName")));
    // users.add(pointUserSyn3DRespone);
    // });
    // pointInfoResponse.setUsers(users);
    // }
    // List<PointInfoSyn3DRespone> list = new ArrayList<>();
    // list.add(pointInfoResponse);
    // remoteServer.pointInfoPush(list);
    // return pointInfoResponse;
    // }
    //
    // private String getValue(Object value){
    // if(value == null){
    // return "";
    // }
    // return value.toString();
    // }


    @Override
    public List<HashMap<String, Object>> findPointList(String code, String name, String orgCode) {
        // TODO Auto-generated method stub
        return pointMapper.findPointList(orgCode, name, code);
    }

    @Override
    public List<Point> queryPointInfoByParms(List<DaoCriteria> criterias) {
        // TODO Auto-generated method stub
        BaseQuerySpecification<Point> spec = new BaseQuerySpecification<>(criterias);
        List<Point> point = iPointDao.findAll(spec);
        return point;
    }

    @Override
    public List<PointInputItemVo> queryPointClassInputItem(Long pointId) {
        // TODO Auto-generated method stub
        return pointMapper.getPointClassInputItemById(pointId);
    }

    @Override
    public List<Map<String, Object>> queryAllPointConfig(String loginOrgCode) {
        return pointMapper.queryAllPointConfig(loginOrgCode);
    }

    @Override
    public List<Map<String, Object>> queryEquipPointInputItem(Long pointId) {
        List<Map<String, Object>> content = pointMapper.queryEquipPointInputItem(pointId);
        content.forEach(e -> {
            if (e.get("equipmentId") != null && !StringUtils.isBlank(e.get("equipmentId").toString())) {
                List<PointInputItemVo> inputItems = inputItemMapper.queryCustomInputItemByPointId(pointId, e.get("equipmentId").toString());
                e.put("equipIputDetailData", inputItems);
            }
        });
        return content;
    }

//	@Override
//	public PointInfoSyn3DRespone pushPointTo3D(long pointId) {
//		List<Map<String,Object>> result = pointMapper.getPointInfoById(pointId);
//		PointInfoSyn3DRespone pointInfoResponse = new PointInfoSyn3DRespone();
//		List<PointUserSyn3DRespone> users = new ArrayList<PointUserSyn3DRespone>();
//		if(!result.isEmpty()){
//			result.forEach(action->{
//				pointInfoResponse.setPointId(getValue(action.get("pointId")));
//				pointInfoResponse.setPointName(getValue(action.get("pointName")));
//				pointInfoResponse.setPointLevel(getValue(action.get("pointLevel")));
//				pointInfoResponse.setStatus(getValue(action.get("status")));
//				pointInfoResponse.setCoordinates(getValue(action.get("coordinates")));
//				pointInfoResponse.setAddress(getValue(action.get("address")));
//				PointUserSyn3DRespone pointUserSyn3DRespone = new PointUserSyn3DRespone();
//				pointUserSyn3DRespone.setUserId(getValue(action.get("userId")));
//				pointUserSyn3DRespone.setUserName(getValue(action.get("userName")));
//				pointUserSyn3DRespone.setOrgCode(getValue(action.get("orgCode")));
//				pointUserSyn3DRespone.setGroupName(getValue(action.get("groupName")));
//				users.add(pointUserSyn3DRespone);
//			});
//			pointInfoResponse.setUsers(users);
//		}
//		List<PointInfoSyn3DRespone> list = new ArrayList<>();
//		list.add(pointInfoResponse);
//		remoteServer.pointInfoPush(list);
//		return pointInfoResponse;
//	}
//
//	private String getValue(Object value){
//		if(value == null){
//			return "";
//		}
//		return value.toString();
//	}

    @Override
    public Page queryPointList4Route(Long riskSourceId, String pointNo, String name, int current, int size) {
        if (current < 1 || size < 0) {
            throw new RuntimeException("查询条件有误");
        }
        List<Long> structureIdList = null;
        List<Map<String, Object>> list = Collections.EMPTY_LIST;
        // 传入riskSourceId为-2请求的是巡检点区域为空
        if (riskSourceId != null && riskSourceId != -2) {
            LinkedHashMap<String, Object> o = equipFeign.getBuildingTree();
            if (o == null || !"200".equals(o.get("status").toString())) {
                throw new YeeException("获取建筑树出错");
            }
            List<Map<String, Object>> buildingTree = (List<Map<String, Object>>) o.get("result");
            Map<String, Object> node = getAllNodes(buildingTree).stream().filter(map -> riskSourceId.toString().equals(map.get("id"))).findFirst().orElse(null);
            if (node != null) {
                structureIdList = findBuildChildrenIds(node);
            }
        }

        boolean nullRiskSourceId = false;
        if (riskSourceId != null && riskSourceId == -2) {
            nullRiskSourceId = true;
        }

        int total = pointMapper.queryPointCount4Route(structureIdList, pointNo, name, nullRiskSourceId);
        int offset = (current - 1) * size;
        if (total > offset) {
            list = pointMapper.queryPointList4Route(structureIdList, pointNo, name, offset, size, nullRiskSourceId);
        }
        return new PageImpl(list, PageRequest.of(current - 1, size), total);
    }

    private List<Map<String, Object>> getAllNodes(List<Map<String, Object>> buildingTree) {
        List<Map<String, Object>> res = new LinkedList<>();
        if (buildingTree != null && !buildingTree.isEmpty()) {
            res.addAll(buildingTree);
            buildingTree.forEach(building -> {
                List<Map<String, Object>> childrenTree = (List<Map<String, Object>>) building.get("children");
                res.addAll(getAllNodes(childrenTree));
            });
        }
        return res;
    }

    private List<Long> findBuildChildrenIds(Map<String, Object> building) {
        List<Map<String, Object>> buildingTree = getAllNodes(Collections.singletonList(building));
        return buildingTree.stream().map(building123 -> Long.valueOf(building123.get("id").toString())).collect(Collectors.toList());
    }

    @Override
    public List queryPointListByRouteId(Long routeId) {
        if (routeId == null) {
            throw new RuntimeException("查询条件有误");
        }
        List<Map<String, Object>> resList = pointMapper.queryPointListByRouteId(routeId);
        resList.forEach(map -> {
            map.put("routePointItem", Collections.EMPTY_LIST);
        });
        return resList;
    }


    @Override
    public List queryEquipListByPointId(Long pointId) {
        if (pointId == null) {
            throw new RuntimeException("查询条件有误");
        }
        List<Map<String, Object>> resList = pointMapper.queryEquipListByPointId(pointId);
        return resList;
    }

    @Override
    public List queryItemList4RoutePoint(Long pointId, Long classifyId) {
        if (pointId == null || classifyId == null) {
            throw new RuntimeException("查询条件有误");
        }
        List<Map<String, Object>> resList = pointMapper.queryItemList4RoutePoint(pointId, classifyId);
        return resList;
    }

    @Override
    public LinkedHashMap<String, Object> getRegionTress() {
        return equipFeign.getRegionTress();
    }


    @Override
    @Async
    public void syncSavePoint(List<MaintenanceResourceData> list, String orgCode, String userId) {
        List<Point> points = new ArrayList<>();
        List<PointInputItem> inputItems = new ArrayList<>();
        List<Long> ids = new ArrayList<>();
        //1.删除已有数据
        for (MaintenanceResourceData x : list) {
            String pointNo = x.getFireFacilityCode();
            String originalId = String.valueOf(x.getFireFacilityId());
            Long id = iPointDao.findPointByEquipmentIdAndFireFacilityId(pointNo, originalId);
            if (null != id) {
                ids.add(id);
            }
        }
        if (!ids.isEmpty()) {
            Long[] idsArray = ids.toArray(new Long[0]);
            delPointById(idsArray);
        }
        //2.创建
        for (MaintenanceResourceData x : list) {
            Point point = new Point();
            String pointNo = StringUtil.isNotEmpty(x.getFireFacilityCode()) ? x.getFireFacilityCode() : String.valueOf(sequence.nextId());
            String originalId = String.valueOf(x.getFireFacilityId());
            point.setOriginalId(originalId);
            point.setName(x.getFireFacilityName());
            point.setPointNo(pointNo);
            point.setEquipmentId(x.getClassifyId() == null ? "" : x.getClassifyId().toString());
            point.setEquipmentName(x.getClassifyName());
            point.setBelongSystemId(x.getFireFightSysId() == null ? "" : x.getFireFightSysId().toString());
            point.setBelongSystemName(x.getFireFightSysName());
            point.setOwnerId(String.valueOf(x.getOwnerUnitId()));
            point.setOwnerName(x.getOwnerUnitName());
            point.setBuildingId(x.getBuildingId() != null ? x.getBuildingId().toString() : "");
            point.setBuildingName(x.getBuildingName());
            point.setAddress(x.getArea());
            point.setLevel("");
            point.setCreatorId(userId);
            point.setOrgCode(orgCode);
            points.add(point);
            iPointDao.save(point);
            List<InputItem> inputItemVos = inputItemMapper.getInputItemByEquipmentName(x.getClassifyName(), orgCode);
            if (0 < inputItemVos.size()) {
                inputItemVos.forEach(y -> {
                    PointInputItem inputItem = new PointInputItem();
                    inputItem.setPointId(point.getId());
                    inputItem.setOrderNo(y.getOrderNo());
                    inputItem.setInputItemId(y.getId());
                    inputItems.add(inputItem);
                });
            }
        }
        iPointInputItemDao.saveAll(inputItems);
    }

    @Override
    public Page<PointDto> queryPointInfoWithItem(List<DaoCriteria> criterias, CommonPageable cPageable, Long ownerId) {
        BaseQuerySpecification<Point> spec = new BaseQuerySpecification<>(criterias);
        Order idOrder = new Order(Direction.DESC, "id");
        List<Order> orders = new ArrayList<Order>();
        orders.add(idOrder);
        Sort sort = Sort.by(orders);
        cPageable.setSort(sort);
        Page<Point> pointPage = iPointDao.findAll(spec, cPageable);
        List<PointInputItem> pointInputItems = iPointInputItemDao.findAll();
        List<PointDto> pointDtos = new ArrayList<>();
        for (Point point : pointPage) {
            PointDto pointDto = new PointDto();
            BeanUtils.copyProperties(point, pointDto);
            pointDto.setPointInputItems(pointInputItems.stream().filter(i -> i.getPointId() == point.getId()).collect(Collectors.toList()));
            String buildingName = StringUtil.isNotEmpty(point.getBuildingName()) ? point.getBuildingName() : "";
            String address = StringUtil.isNotEmpty(point.getAddress()) ? point.getAddress() : "";
            pointDto.setPosition(buildingName + address);
            pointDtos.add(pointDto);
        }
        Pageable pageable = new CommonPageable(pointPage.getNumber(), pointPage.getSize(), pointPage.getSort());
        return new PageImpl<>(pointDtos, pageable, pointPage.getTotalElements());
    }
}
