package com.yeejoin.equipmanage.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
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.base.Joiner;
import com.google.common.collect.Lists;
import com.yeejoin.amos.boot.biz.common.interceptors.PermissionInterceptorContext;
import com.yeejoin.equipmanage.common.dto.MaintenanceResourceDataDto;
import com.yeejoin.equipmanage.common.entity.MaintenanceResource;
import com.yeejoin.equipmanage.common.entity.MaintenanceResourceData;
import com.yeejoin.equipmanage.common.entity.publics.CommonResponse;
import com.yeejoin.equipmanage.common.enums.MaintenanceResourceEnum;
import com.yeejoin.equipmanage.common.enums.MaintenanceResourceStatusEnum;
import com.yeejoin.equipmanage.common.enums.SubscribeTopicEnum;
import com.yeejoin.equipmanage.common.utils.DateUtils;
import com.yeejoin.equipmanage.common.vo.MaintenanceResourceDataVo;
import com.yeejoin.equipmanage.fegin.MaintenanceFeign;
import com.yeejoin.equipmanage.mapper.MaintenanceResourceDataMapper;
import com.yeejoin.equipmanage.mapper.MaintenanceResourceMapper;
import com.yeejoin.equipmanage.service.IMaintenanceResourceDataService;
import com.yeejoin.equipmanage.service.IMaintenanceResourceService;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.eclipse.paho.client.mqttv3.MqttException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.typroject.tyboot.component.emq.EmqKeeper;

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

/**
 * 消防设施资源数据Service业务层处理
 *
 * @author gaojianqiang
 * @date 2021-07-16
 */
@Service
public class MaintenanceResourceDataServiceImpl extends ServiceImpl<MaintenanceResourceDataMapper, MaintenanceResourceData> implements IMaintenanceResourceDataService {

    private final Logger logger = LogManager.getLogger(MaintenanceResourceDataServiceImpl.class);

    @Autowired
    private IMaintenanceResourceService maintenanceResourceService;

    @Autowired
    private MaintenanceResourceMapper maintenanceResourceMapper;

    @Autowired
    private MaintenanceResourceDataMapper maintenanceResourceDataMapper;

    @Autowired
    private MaintenanceFeign maintenanceFeign;

    @Autowired
    private EmqKeeper emqKeeper;

    @Value("${auth-key-auth-enabled:}")
    private String authKey;

    /**
     * 查询消防设施资源数据
     *
     * @param id 消防设施资源数据ID
     * @return 消防设施资源数据
     */
    @Override
    public MaintenanceResourceData selectMaintenanceResourceDataById(Long id) {
        return maintenanceResourceDataMapper.selectMaintenanceResourceDataById(id);
    }

    /**
     * 查询消防设施资源数据列表
     *
     * @param maintenanceResourceData 消防设施资源数据
     * @return 消防设施资源数据
     */
    @Override
    public List<MaintenanceResourceData> selectMaintenanceResourceDataList(MaintenanceResourceData maintenanceResourceData) {
        return maintenanceResourceDataMapper.selectMaintenanceResourceDataList(maintenanceResourceData);
    }

    /**
     * 新增消防设施资源数据
     *
     * @param maintenanceResourceData 消防设施资源数据
     * @return 结果
     */
    @Override
    public int insertMaintenanceResourceData(MaintenanceResourceData maintenanceResourceData) {
        return maintenanceResourceDataMapper.insertMaintenanceResourceData(maintenanceResourceData);
    }

    /**
     * 修改消防设施资源数据
     *
     * @param maintenanceResourceData 消防设施资源数据
     * @return 结果
     */
    @Override
    public int updateMaintenanceResourceData(MaintenanceResourceData maintenanceResourceData) {
        return maintenanceResourceDataMapper.updateMaintenanceResourceData(maintenanceResourceData);
    }

    /**
     * 批量删除消防设施资源数据
     *
     * @param ids 需要删除的消防设施资源数据ID
     * @return 结果
     */
    @Override
    public int deleteMaintenanceResourceDataByIds(Long[] ids) {
        // 权限处理
        PermissionInterceptorContext.setDataAuthRule(authKey);
        if (ids != null && ids.length > 0) {
            List<MaintenanceResourceDataDto> list = maintenanceResourceDataMapper.deleteBeforeMainResCount(ids);
            List<MaintenanceResourceDataDto> list1 = maintenanceResourceDataMapper.deleteBeforeMainResCount(null);
            List<MaintenanceResourceDataDto> delList = list.stream().filter(item -> list1.contains(item)).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(delList)) {
                List<MaintenanceResourceDataDto> classifyList = delList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getClassifyId() + ";" + o.getFireFightSysId()))), ArrayList::new));
                List<MaintenanceResourceDataDto> fireFightSysList = delList.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getOwnerUnitId() + ";" + o.getFireFightSysId()))), ArrayList::new));
                Integer i = maintenanceResourceDataMapper.deleteClassifyList(classifyList);
                Integer ii = maintenanceResourceDataMapper.deleteFireFightSysList(fireFightSysList);
            }
            List<MaintenanceResourceData> dataList = maintenanceResourceDataMapper.selectBatchIds(Arrays.asList(ids));
            if (!CollectionUtils.isEmpty(dataList)) {
                List<Long> collect = dataList.stream().map(MaintenanceResourceData::getFireFacilityId).collect(Collectors.toList());
                deleteRelationMainResData(collect);
            }
            return maintenanceResourceDataMapper.deleteMaintenanceResourceDataByIds(ids);
        }
        return 0;
    }

    @Async("equipAsyncExecutor")
    void deleteRelationMainResData(List<Long> ids) {
        try {
            maintenanceFeign.pointDelete(Joiner.on(",").join(ids));
        } catch (Exception e) {
//            e.printStackTrace();
            logger.error("异步删除维保关联数据失败：===>>>>deleteRelationMainResData");
        }
    }

    /**
     * 删除消防设施资源数据信息
     *
     * @param id 消防设施资源数据ID
     * @return 结果
     */
    @Override
    public int deleteMaintenanceResourceDataById(Long id) {
        return maintenanceResourceDataMapper.deleteMaintenanceResourceDataById(id);
    }

    @Override
    public List<MaintenanceResourceData> getMaintenanceResourceDataList(String orgCode) {
        return maintenanceResourceDataMapper.getMaintenanceResourceDataList(orgCode);
    }

    @Override
    @Transactional
    public Boolean relationMainResData(String appKey, String product, String token, List<MaintenanceResourceData> list) {
        boolean saveBatch = this.saveOrUpdateBatch(list);
        if (saveBatch) {
            List<MaintenanceResource> resourceList = new ArrayList<>();
            List<MaintenanceResourceData> collect1 = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getMaintenanceCompanyId() + ";" + o.getOwnerUnitId()))), ArrayList::new));
            collect1.stream().forEach(x -> {
                MaintenanceResource resource1 = new MaintenanceResource();
                Long companyId = x.getMaintenanceCompanyId();
                Long ownerUnitId = x.getOwnerUnitId();
                Long fireFightSysId = x.getFireFightSysId();
                resource1.setId(x.getMaintenanceCompanyId());
                resource1.setCode(x.getMaintenanceCompanyCode());
                resource1.setName(x.getMaintenanceCompanyName());
                resource1.setParentId(0L);
                resource1.setType(MaintenanceResourceEnum.MAINTENANCE_COMPANY.getValue());
                resourceList.add(resource1);
                MaintenanceResource resource2 = new MaintenanceResource();
                resource2.setId(x.getOwnerUnitId());
                resource2.setCode(x.getOwnerUnitCode());
                resource2.setName(x.getOwnerUnitName());
                resource2.setParentId(companyId);
                resource2.setType(MaintenanceResourceEnum.OWNER_UNIT.getValue());
                resourceList.add(resource2);
            });
            List<MaintenanceResourceData> collect = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(o -> o.getMaintenanceCompanyId() + ";" + o.getOwnerUnitId() + ";" + o.getFireFightSysId() + ";" + o.getClassifyId()))), ArrayList::new));
            collect.stream().forEach(x -> {
                Long companyId = x.getMaintenanceCompanyId();
                Long ownerUnitId = x.getOwnerUnitId();
                Long fireFightSysId = x.getFireFightSysId();
                MaintenanceResource resource1 = new MaintenanceResource();
                if (fireFightSysId != null) {
                    resource1.setId(fireFightSysId);
                    resource1.setName(x.getFireFightSysName());
                } else {
                    resource1.setId(-2L);
                    resource1.setName("其他");
                }
                resource1.setCode(x.getFireFightSysCode());
                resource1.setParentId(ownerUnitId);
                resource1.setType(MaintenanceResourceEnum.FIREFIGHT_SYS.getValue());
                resourceList.add(resource1);
                MaintenanceResource resource2 = new MaintenanceResource();
                resource2.setId(x.getClassifyId());
                resource2.setCode(x.getClassifyCode());
                resource2.setName(x.getClassifyName());
                resource2.setParentId(fireFightSysId);
                resource2.setType(MaintenanceResourceEnum.CLASSIFY.getValue());
                resourceList.add(resource2);
            });
            boolean b = maintenanceResourceService.updateBatch(resourceList);
            if (b) {
                getPlanTaskList(appKey, product, token, list);
                return Boolean.TRUE;
            } else {
                return Boolean.FALSE;
            }
        }
        return Boolean.FALSE;
    }

    //    @Async
    void getPlanTaskList(String appKey, String product, String token, List<MaintenanceResourceData> list) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    maintenanceFeign.getPlanTaskList(appKey, product, token, (ArrayList<MaintenanceResourceData>) list);
                } catch (Exception e) {
                    log.error("feign调用维保设施数据保存失败！");
                    e.printStackTrace();
                }
            }
        }).start();
    }

    @Override
    public List<Map<String, Long>> findTierKeyByParentId(Long parentId) {
        List<Map<String, Long>> list = maintenanceResourceMapper.findTierKeyByParentId(parentId);
        if (!CollectionUtils.isEmpty(list)) {
            return list;
        }
        return Lists.newArrayList();
    }

    @Override
    public List<MaintenanceResourceDataVo> findByIds(List<Long> ids) {
        List<MaintenanceResourceDataVo> list = maintenanceResourceMapper.findByIds(ids);
        if (!CollectionUtils.isEmpty(list)) {
            return list;
        }
        return Lists.newArrayList();
    }

    @Override
    public IPage<MaintenanceResourceDataDto> getClassifyPage(Page page, Long maintenanceCompanyId, Long ownerUnitId, Long fireFightSysId, String expirationTimeSort) {
        IPage<MaintenanceResourceDataDto> classifyPage = maintenanceResourceDataMapper.getClassifyPage(page, maintenanceCompanyId, ownerUnitId, fireFightSysId, expirationTimeSort);
        if (StringUtils.isNotBlank(expirationTimeSort)) {
            final List<MaintenanceResourceDataDto> records = classifyPage.getRecords();
            if (!CollectionUtils.isEmpty(records)) {
                if ("ASC".equalsIgnoreCase(expirationTimeSort)) {
                    records.sort(Comparator.comparing(MaintenanceResourceDataDto::getExpirationAmount));
                } else if ("DESC".equalsIgnoreCase(expirationTimeSort)) {
                    records.sort(Comparator.comparing(MaintenanceResourceDataDto::getExpirationAmount).reversed());
                }
                classifyPage.setRecords(records);
            }
        }
        return classifyPage;
    }

    @Override
    public IPage<MaintenanceResourceDataDto> getFireFacilityPage(Page page, Long maintenanceCompanyId, Long ownerUnitId, Long fireFightSysId, Long classifyId, List<Long> buildingId, String status) {
        return maintenanceResourceDataMapper.getFireFacilityPage(page, maintenanceCompanyId, ownerUnitId, fireFightSysId, classifyId, buildingId, status);
    }

    @Override
    public CommonResponse getMaintenanceInfoPage(String appKey, String product, String token, String userId, String timeType, String result, String orderRule, String beginTime, String endTime, String person, String teamId, String equipId, Integer pageNumber, Integer pageSize) {
        CommonResponse checkRecord = maintenanceFeign.getCheckRecord(appKey, product, token, userId, timeType, result, orderRule, beginTime, endTime, person, teamId, equipId, pageNumber, pageSize);
        return checkRecord;
    }

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

    @Override
    public void subscribeTopic() {
        try {
            emqKeeper.getMqttClient().subscribe(SubscribeTopicEnum.MAINTENANCE_TOPIC.getTopic(), (s, mqttMessage) -> {
                try {
                    String msg = mqttMessage.toString();
                    if (StringUtils.isNotBlank(msg)) {
                        Map map = JSON.parseObject(msg, Map.class);
                        MaintenanceResourceData data = JSON.parseObject(msg, MaintenanceResourceData.class);
                        Date maintenanceTime = data.getMaintenanceTime();
                        data.setMaintenanceTime(null);
                        List<MaintenanceResourceData> dataList = selectMaintenanceResourceDataList(data);
                        if (!CollectionUtils.isEmpty(dataList)) {
                            MaintenanceResourceData resourceData = dataList.get(0);
                            Integer maintenanceCycle = resourceData.getMaintenanceCycle();
                            Date maintenanceExpirationTime = DateUtils.dateAddMonths(maintenanceTime, maintenanceCycle);
                            resourceData.setMaintenanceTime(maintenanceTime);
                            resourceData.setMaintenanceExpirationTime(maintenanceExpirationTime);
                            resourceData.setStatus(MaintenanceResourceStatusEnum.NORMAL.getCode());
                            UpdateWrapper<MaintenanceResourceData> updateWrapper = new UpdateWrapper<>();
                            updateWrapper.eq("fire_facility_id", data.getFireFacilityId());
                            boolean update = this.update(resourceData, updateWrapper);
                            if (update) {
                                logger.info("维保设施同步更新成功！");
                            }
                        }
                    }
                } catch (Exception e) {
                    logger.error("维保设施同步更新失败！", e);
                }
            });
        } catch (MqttException e) {
            logger.fatal("订阅维保设施同步消息失败，维保设施同步无法同步！", e);
        }
    }
}
