package com.yeejoin.equipmanage.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.yeejoin.equipmanage.common.dto.MaintenanceResourceDto;
import com.yeejoin.equipmanage.common.dto.WaterResourceDto;
import com.yeejoin.equipmanage.common.dto.WaterResourceTypeDto;
import com.yeejoin.equipmanage.common.entity.MaintenanceResource;
import com.yeejoin.equipmanage.common.entity.MaintenanceResourceData;
import com.yeejoin.equipmanage.common.enums.MaintenanceResourceEnum;
import com.yeejoin.equipmanage.common.utils.TreeNodeUtil;
import com.yeejoin.equipmanage.common.vo.MaintenanceResourceDataVo;
import com.yeejoin.equipmanage.common.vo.MaintenanceResourceVo;
import com.yeejoin.equipmanage.fegin.JcsFeign;
import com.yeejoin.equipmanage.mapper.EquipmentSpecificMapper;
import com.yeejoin.equipmanage.mapper.MaintenanceResourceDataMapper;
import com.yeejoin.equipmanage.mapper.MaintenanceResourceMapper;
import com.yeejoin.equipmanage.service.IMaintenanceResourceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.typroject.tyboot.core.restful.utils.ResponseModel;

import java.util.*;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.minBy;

/**
 * 维保设施资源树Service业务层处理
 *
 * @author gaojianqiang
 * @date 2021-07-16
 */
@Service
public class MaintenanceResourceServiceImpl extends ServiceImpl<MaintenanceResourceMapper, MaintenanceResource> implements IMaintenanceResourceService {
    @Autowired
    private MaintenanceResourceMapper maintenanceResourceMapper;

    @Autowired
    private MaintenanceResourceDataMapper maintenanceResourceDataMapper;

    @Autowired
    private EquipmentSpecificMapper equipmentSpecificMapper;

    @Autowired
    private JcsFeign jcsFeign;

    /**
     * 查询维保设施资源树
     *
     * @param id 维保设施资源树ID
     * @return 维保设施资源树
     */
    @Override
    public MaintenanceResource selectMaintenanceResourceById(Long id) {
        return maintenanceResourceMapper.selectMaintenanceResourceById(id);
    }

    /**
     * 查询维保设施资源树列表
     *
     * @param maintenanceResource 维保设施资源树
     * @return 维保设施资源树
     */
    @Override
    public List<MaintenanceResource> selectMaintenanceResourceList(MaintenanceResource maintenanceResource) {
        return maintenanceResourceMapper.selectMaintenanceResourceList(maintenanceResource);
    }

    /**
     * 新增维保设施资源树
     *
     * @param maintenanceResource 维保设施资源树
     * @return 结果
     */
    @Override
    public int insertMaintenanceResource(MaintenanceResource maintenanceResource) {
        return maintenanceResourceMapper.insertMaintenanceResource(maintenanceResource);
    }

    /**
     * 修改维保设施资源树
     *
     * @param maintenanceResource 维保设施资源树
     * @return 结果
     */
    @Override
    public int updateMaintenanceResource(MaintenanceResource maintenanceResource) {
        return maintenanceResourceMapper.updateMaintenanceResource(maintenanceResource);
    }

    /**
     * 批量删除维保设施资源树
     *
     * @param ids 需要删除的维保设施资源树ID
     * @return 结果
     */
    @Override
    public int deleteMaintenanceResourceByIds(Long[] ids) {
        return maintenanceResourceMapper.deleteMaintenanceResourceByIds(ids);
    }

    /**
     * 删除维保设施资源树信息
     *
     * @param id 维保设施资源树ID
     * @return 结果
     */
    @Override
    public int deleteMaintenanceResourceById(Long id) {
        return maintenanceResourceMapper.deleteMaintenanceResourceById(id);
    }

    @Override
    public List<MaintenanceResourceDto> getMaintenanceResourceTree(String appKey, String product, String token) {
        List<MaintenanceResourceDto> list = this.selectAll();
        if (!CollectionUtils.isEmpty(list)) {
            List<MaintenanceResourceDto> companyTree = getCompanyList(appKey, product, token);
            if (!CollectionUtils.isEmpty(companyTree)) {
                List<MaintenanceResourceDto> dataList = new ArrayList<>();
                list.addAll(companyTree);
                Map<String, Optional<MaintenanceResourceDto>> collect = list.stream().collect(groupingBy(MaintenanceResourceDto::getId, minBy(Comparator.comparing(MaintenanceResourceDto::getParentId))));
                collect.entrySet().forEach(entry -> {
                    entry.getValue().ifPresent(v -> {
                        dataList.add(v);
                    });
                });
                return TreeNodeUtil.assembleTree(dataList);
            }
            return TreeNodeUtil.assembleTree(list);
        } else {
            return getCompanyTree(appKey, product, token);
        }
    }

    private List<MaintenanceResourceDto> getCompanyTree(String appKey, String product, String token) {
        ResponseModel<List<Map<String, Object>>> companyList = jcsFeign.selectCompanyList(appKey, product, token);
        List<Map<String, Object>> result = companyList.getResult();
        if (!CollectionUtils.isEmpty(result)) {
            List<MaintenanceResourceDto> resourceDtoList = new ArrayList<>();
            result.stream().forEach(x -> {
                MaintenanceResourceDto dto = JSONObject.parseObject(JSONObject.toJSONString(x), MaintenanceResourceDto.class);
                resourceDtoList.add(dto);
            });
            return TreeNodeUtil.assembleTree(resourceDtoList);
        }
        return Lists.newArrayList();
    }

    private List<MaintenanceResourceDto> getCompanyList(String appKey, String product, String token) {
        ResponseModel<List<Map<String, Object>>> companyList = jcsFeign.selectCompanyList(appKey, product, token);
        List<Map<String, Object>> result = companyList.getResult();
        if (!CollectionUtils.isEmpty(result)) {
            List<MaintenanceResourceDto> resourceDtoList = new ArrayList<>();
            result.stream().forEach(x -> {
                MaintenanceResourceDto dto = JSONObject.parseObject(JSONObject.toJSONString(x), MaintenanceResourceDto.class);
                resourceDtoList.add(dto);
            });
            return resourceDtoList;
        }
        return Lists.newArrayList();
    }

    @Override
    public List<MaintenanceResourceDto> selectAll() {
        List<MaintenanceResourceDto> list = maintenanceResourceMapper.selectAll();
        if (!CollectionUtils.isEmpty(list)) {
            return list;
        }
        return Lists.newArrayList();
    }

    @Override
    public List<MaintenanceResourceDto> findTreeById(Long id) {
        List<MaintenanceResourceDto> list = maintenanceResourceMapper.findTreeById(id);
        Set<MaintenanceResourceDto> set = new HashSet<MaintenanceResourceDto>();
        set.addAll(list);
        list.clear();
        list.addAll(set);
        if (!CollectionUtils.isEmpty(list)) {
            List<MaintenanceResourceDto> dtoList = TreeNodeUtil.assembleTreeNotFilter(list);//&& x.getId().equals(Long.toString(id)) 这一段用于生成树之后并没有把树子节点数据从list列表删除造成的脏数据的问题 by chenhao 2022-01-12
            List<MaintenanceResourceDto> collect = dtoList.stream().filter(x -> !MaintenanceResourceEnum.CLASSIFY.getValue().equals(x.getType()) && x.getId().equals(Long.toString(id))).collect(Collectors.toList());
            return collect;
        }
        return Lists.newArrayList();
    }

    @Override
    public List<MaintenanceResourceDto> combineTree(String appKey, String product, String token) {
        List<MaintenanceResourceDto> resourceList = new ArrayList<>();
        ResponseModel<List<WaterResourceTypeDto>> resourceTypeList = jcsFeign.selectResourceTypeList(appKey, product, token);
        List<WaterResourceTypeDto> result = resourceTypeList.getResult();
        if (!CollectionUtils.isEmpty(result)) {
            List<WaterResourceTypeDto> distinctList = result.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getBelongFightingSystemId() + ";" + o.getResourceType()))), ArrayList::new));
            distinctList.stream().forEach(x -> {
                String fightingSystemId = String.valueOf(x.getBelongFightingSystemId());
                MaintenanceResourceDto resource1 = new MaintenanceResourceDto();
                resource1.setId(fightingSystemId);
                resource1.setName(x.getBelongFightingSystem());
                resource1.setParentId("-1");
                resource1.setType(MaintenanceResourceEnum.FIREFIGHT_SYS.getValue());
                resourceList.add(resource1);
                MaintenanceResourceDto resource2 = new MaintenanceResourceDto();
                resource2.setId(x.getResourceType());
                resource2.setName(x.getResourceTypeName());
                resource2.setParentId(fightingSystemId);
                resource2.setType(MaintenanceResourceEnum.CLASSIFY.getValue());
                resourceList.add(resource2);
            });
        }

        List<MaintenanceResourceDataVo> list = equipmentSpecificMapper.getSysEquipClassifyList();
        if (!CollectionUtils.isEmpty(list)) {
            List<MaintenanceResourceDataVo> distinctList = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getFireFightSysId() + ";" + o.getClassifyId()))), ArrayList::new));
            distinctList.stream().forEach(x -> {
                MaintenanceResourceDto resource1 = new MaintenanceResourceDto();
                resource1.setId(String.valueOf(x.getFireFightSysId()));
                resource1.setCode(x.getFireFightSysCode());
                resource1.setName(x.getFireFightSysName());
                resource1.setParentId("-1");
                resource1.setType(MaintenanceResourceEnum.FIREFIGHT_SYS.getValue());
                resourceList.add(resource1);
            });
            Map<Long, List<MaintenanceResourceDataVo>> map = list.stream().collect(Collectors.groupingBy(MaintenanceResourceDataVo::getFireFightSysId));
            map.forEach((k, v) -> {
                String parentId = String.valueOf(k);
                v.stream().forEach(x -> {
                    MaintenanceResourceDto resource2 = new MaintenanceResourceDto();
                    resource2.setId(String.valueOf(x.getClassifyId()));
                    resource2.setCode(x.getClassifyCode());
                    resource2.setName(x.getClassifyName());
                    resource2.setParentId(parentId);
                    resource2.setType(MaintenanceResourceEnum.CLASSIFY.getValue());
                    resourceList.add(resource2);
                });
            });
            List<MaintenanceResourceDto> collect = resourceList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getId() + ";" + o.getType() + ";" + o.getParentId()))), ArrayList::new));
            return TreeNodeUtil.assembleTreeNew(collect);
        }
        return Lists.newArrayList();
    }

    @Override
    public List<MaintenanceResourceData> combineData(String appKey, String product, String token) {
        List<MaintenanceResourceData> list = equipmentSpecificMapper.getSysEquipClassifyDataList();
        if (!CollectionUtils.isEmpty(list)) {
            return list;
        }
        return Lists.newArrayList();
    }

    @Override
    public IPage<MaintenanceResourceDataVo> combineDataPage(Page page, Long fireFightSysId, Long fireFacilityId, String fireFacilityName, String classifyId, List<Long> buildingId, String appKey, String product, String token) {
        //        存放组合键，ID+type，数据库查看是否已关联
        List<String> keyList = new ArrayList<>();
        int current = Integer.parseInt(String.valueOf(page.getCurrent()));
        long pageSize = page.getSize();
        int size = Integer.parseInt(String.valueOf(pageSize / 2));
        page.setSize(size);
        ResponseModel<Page<WaterResourceDto>> pageResponseModel = jcsFeign.queryForPage(appKey, product, token, current, size, fireFacilityName, buildingId, fireFightSysId, fireFacilityId, classifyId);
        Page<WaterResourceDto> result = pageResponseModel.getResult();
        long pages = result.getPages();
        long total = result.getTotal();
        if (current <= pages) {
            List<WaterResourceDto> records = result.getRecords();
            List<MaintenanceResourceDataVo> resourceDataVoList = new ArrayList<>();
            if (!CollectionUtils.isEmpty(records)) {
                int recordSize = records.size();
                if (size > recordSize) {
                    page.setSize(pageSize - recordSize);
                }
                records.stream().forEach(x -> {
                    MaintenanceResourceDataVo resourceDataVo = new MaintenanceResourceDataVo();
                    Long sequenceNbr = x.getSequenceNbr();
                    String resourceType = x.getResourceType();
                    resourceDataVo.setFireFacilityId(sequenceNbr);
                    resourceDataVo.setFireFacilityName(x.getName());
                    resourceDataVo.setLocation(x.getAddress());
                    resourceDataVo.setFireFacilityType(resourceType);
                    resourceDataVo.setClassifyId(x.getEquipId());
                    resourceDataVo.setClassifyName(x.getEquipName());
                    resourceDataVo.setBuildingId(x.getBelongBuildingId());
                    resourceDataVo.setBuildingName(x.getBelongBuilding());
                    resourceDataVo.setFireFightSysId(x.getBelongFightingSystemId());
                    resourceDataVo.setFireFightSysName(x.getBelongFightingSystem());
                    resourceDataVo.setOwnerUnitId(x.getManagementUnitId());
                    resourceDataVo.setOwnerUnitName(x.getManagementUnit());
                    resourceDataVo.setMaintenanceCompanyId(x.getMaintenanceUnitId());
                    resourceDataVo.setMaintenanceCompanyName(x.getMaintenanceUnit());
                    resourceDataVo.setCreateDate(x.getRecDate());
                    resourceDataVo.setLocation(x.getBelongBuilding());
                    resourceDataVo.setFireFacilityCode(x.getEquipCode());
                    resourceDataVoList.add(resourceDataVo);
                    keyList.add(String.join("-", String.valueOf(sequenceNbr), resourceType));
                });
            } else {
                page.setSize(pageSize);
            }
            IPage<MaintenanceResourceDataVo> dataPage = null;
            if (fireFightSysId != null && fireFightSysId == -2) {
                dataPage = equipmentSpecificMapper.getEquipClassifyDataPage(page, fireFightSysId, fireFacilityName, classifyId, fireFacilityId, buildingId);
            } else {
                dataPage = equipmentSpecificMapper.getSysEquipClassifyDataPage(page, fireFightSysId, fireFacilityName, classifyId, fireFacilityId, buildingId);
            }
            List<MaintenanceResourceDataVo> dataPageRecords = dataPage.getRecords();
            long total1 = dataPage.getTotal();
            dataPage.setSize(pageSize);
            dataPage.setTotal(total + total1);
            dataPage.setPages((long) Math.ceil((total + total1) * 1.0 / pageSize));
            dataPageRecords.stream().forEach(x -> {
                keyList.add(String.join("-", String.valueOf(x.getFireFacilityId()), x.getFireFacilityType()));
            });
//        组合键入库查询是否被关联，返回已关联的组合键
            List<String> relationList = maintenanceResourceDataMapper.getRelationKey(keyList);
            if (!CollectionUtils.isEmpty(relationList)) {
                dataPageRecords.stream().forEach(x -> {
                    String key = String.join("-", String.valueOf(x.getFireFacilityId()), x.getFireFacilityType());
                    if (relationList.contains(key)) {
                        x.setIsRelation(Boolean.TRUE);
                    }
                });
                resourceDataVoList.stream().forEach(x -> {
                    String key = String.join("-", String.valueOf(x.getFireFacilityId()), x.getFireFacilityType());
                    if (relationList.contains(key)) {
                        x.setIsRelation(Boolean.TRUE);
                    }
                });
            }
            if (!CollectionUtils.isEmpty(dataPageRecords) && !CollectionUtils.isEmpty(resourceDataVoList)) {
                dataPageRecords.addAll(resourceDataVoList);
                dataPage.setRecords(dataPageRecords);
            } else if (!CollectionUtils.isEmpty(resourceDataVoList)) {
                dataPage.setRecords(resourceDataVoList);
            } else if (!CollectionUtils.isEmpty(dataPageRecords)) {
                dataPage.setRecords(dataPageRecords);
            }
            return dataPage;
        } else {
            page.setSize(pageSize);
            page.setCurrent(Math.abs(current - (int) Math.ceil(total / 10.0)));
            IPage<MaintenanceResourceDataVo> dataPage = null;
            if (fireFightSysId != null && fireFightSysId == -2) {
                dataPage = equipmentSpecificMapper.getEquipClassifyDataPage(page, fireFightSysId, fireFacilityName, classifyId, fireFacilityId, buildingId);
            } else {
                dataPage = equipmentSpecificMapper.getSysEquipClassifyDataPage(page, fireFightSysId, fireFacilityName, classifyId, fireFacilityId, buildingId);
            }
            List<MaintenanceResourceDataVo> records = dataPage.getRecords();
            records.stream().forEach(x -> {
                keyList.add(String.join("-", String.valueOf(x.getFireFacilityId()), x.getFireFacilityType()));
            });
            List<String> relationList = maintenanceResourceDataMapper.getRelationKey(keyList);
            if (!CollectionUtils.isEmpty(relationList)) {
                records.stream().forEach(x -> {
                    String key = String.join("-", String.valueOf(x.getFireFacilityId()), x.getFireFacilityType());
                    if (relationList.contains(key)) {
                        x.setIsRelation(Boolean.TRUE);
                    }
                });
            }
            dataPage.setTotal(dataPage.getTotal() + total);
            dataPage.setRecords(records);
            return dataPage;
        }
    }

    @Override
    public List<MaintenanceResourceDto> selectCompanyList(String appKey, String product, String token) {
        ResponseModel<List<Map<String, Object>>> companyList = jcsFeign.selectCompanyList(appKey, product, token);
        List<Map<String, Object>> result = companyList.getResult();
        if (!CollectionUtils.isEmpty(result)) {
            List<MaintenanceResourceDto> list = new ArrayList<>();
            result.stream().forEach(x -> {
                list.add(JSONObject.parseObject(JSONObject.toJSONString(x), MaintenanceResourceDto.class));
            });
            return list.stream().filter(x -> MaintenanceResourceEnum.OWNER_UNIT.getValue().equals(x.getType())).distinct().collect(Collectors.toList());
        }
        return Lists.newArrayList();
    }

    @Override
    public List<MaintenanceResourceDto> selectOwnerUnitList(Long id, Integer type) {
        List<MaintenanceResourceDto> list = maintenanceResourceMapper.selectOwnerUnitList(id, type);
        if (!CollectionUtils.isEmpty(list)) {
            return list;
        }
        return Lists.newArrayList();
    }

    @Override
    public IPage<MaintenanceResourceVo> getFireFightSysPage(Page page, Long maintenanceCompanyId, Long ownerUnitId, Long fireFightSysId, Integer type) {
        return maintenanceResourceMapper.getFireFightSysPage(page, maintenanceCompanyId, ownerUnitId, fireFightSysId, type);
    }

    @Override
    public Boolean updateBatch(List<MaintenanceResource> resourceList) {
        return maintenanceResourceMapper.updateBatch(resourceList);
    }

}
