package cn.cecep.talroad.service.impl;

import cn.cecep.talroad.common.core.domain.R;
import cn.cecep.talroad.common.core.utils.DateUtils;
import cn.cecep.talroad.common.core.utils.StringUtils;
import cn.cecep.talroad.common.security.utils.SecurityUtils;
import cn.cecep.talroad.domain.*;
import cn.cecep.talroad.enums.OperationTypeEnum;
import cn.cecep.talroad.feign.BaseRegionService;
import cn.cecep.talroad.mapper.*;
import cn.cecep.talroad.service.IPcAdslFactoryService;
import cn.cecep.talroad.service.IPcFactoryCoordinateOperationLogService;
import cn.cecep.talroad.service.IPcFactoryService;
import cn.cecep.talroad.vo.*;
import cn.cecep.talroad.vo.analysis.FactoryOutletVo;
import cn.cecep.talroad.vo.query.PcFactoryQuery;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.collections4.ListUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

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


/**
 * 企业基本信息Service业务层处理
 *
 * @author szhpt
 * @date 2023-01-11*/
@Service
public class PcFactoryServiceImpl extends ServiceImpl<PcFactoryMapper,PcFactory> implements IPcFactoryService
{

    @Autowired
    private BasDeviceMapper deviceMapper;

    @Autowired
    private PcLabelFactoryMapper labelFactoryMapper;

    @Autowired
    private PcFactoryMapper pcFactoryMapper;

    @Autowired
    private IPcAdslFactoryService iPcAdslFactoryService;

    @Autowired
    private PcAdslFactoryMapper pcAdslFactoryMapper;

    @Autowired
    private PcLabelMapper labelMapper;

    @Autowired
    private PcLabelValueMapper labelValueMapper;
    @Autowired
    @Qualifier("baseRegionService")
    private BaseRegionService baseRegionService;
    @Autowired
    private PcIndustryMapper pcIndustryMapper;
    @Autowired
    private IPcFactoryCoordinateOperationLogService pcFactoryCoordinateOperationLogService;

    @Override
    public List<Map<String, Object>> getDeviceType(String id) {
        PcFactory factory = getById(id);

        if (factory == null || StringUtils.isEmpty(factory.getIndustryCategory())) {
            return new ArrayList<>();
        }
        List<Map<String, Object>> list = deviceMapper.selectDeviceType(factory.getIndustryCategory());
        list.forEach(o -> o.put("industry", factory.getIndustryCategory()));
        return list;
    }

    /**
     * 获取指定企业标签描述
     * @param factoryId
     */
    @Override
    public List<String> getLabel(String factoryId, Boolean isMain) {
        List<String> list = getLabel(Arrays.asList(factoryId), isMain).get(factoryId);
        return list == null ? new ArrayList<>() : list;
    }

    /**
     * 批量获取指定企业标签描述
     * @param factoryIds
     */
    @Override
    public Map<String, List<String>> getLabel(List<String> factoryIds, Boolean isMain) {
        Map<String, List<String>> factoryMap = new HashMap<>();
        if (factoryIds.isEmpty()) {
            return factoryMap;
        }

        QueryWrapper<PcLabelFactory> wrapper = new QueryWrapper<PcLabelFactory>().in("factory_id", factoryIds);
        if (isMain != null) {
            wrapper.eq("lable_useing", isMain ? "1" : "0");
        }
        wrapper.orderByAsc("label_id");

        // 获取企业与标签中间表的数据
        List<PcLabelFactory> labelFactories = labelFactoryMapper.selectList(wrapper);
        if (labelFactories.isEmpty()) {
            return factoryMap;
        }

        // 获取标签本身
        List<PcLabel> pcLabels = labelMapper.selectBatchIds(labelFactories.stream().map(PcLabelFactory::getLabelId).collect(Collectors.toSet()));
        if (pcLabels.isEmpty()) {
            return factoryMap;
        }

        // 标签值
        List<PcLabelValue> labelValues = labelValueMapper.selectList(
                new QueryWrapper<PcLabelValue>().in("label_id", pcLabels.stream().map(PcLabel::getId).collect(Collectors.toList())));

        // 按照企业分组
        Map<String, List<PcLabelFactory>> groupMap = labelFactories.stream().collect(Collectors.groupingBy(PcLabelFactory::getFactoryId));

        groupMap.forEach((factoryId, labelFactoryList) -> {
            List<String> labels = new ArrayList<>();

            for (PcLabelFactory lf : labelFactoryList) {
                PcLabel pcLabel = pcLabels.stream().filter(label -> label.getId().equals(lf.getLabelId())).findFirst().orElse(null);

                // 标签不存在
                if (pcLabel == null) {
                    continue;
                }

                // 标签值不为空
                if (!StringUtils.isEmpty(lf.getLabelValue())) {
                    List<String> values = Arrays.asList(lf.getLabelValue().split(","));

                    List<PcLabelValue> collect = labelValues.stream()
                            .filter(lv -> lv.getLabelId().equals(lf.getLabelId()) && values.contains(lv.getArgumentsCode()))
                            .collect(Collectors.toList());

                    // 标签值无效（pc_label_value表中未记录）
                    if (collect.isEmpty()) {
                        // 忽略
                    } else {
                        // 获取有别名的标签值
                        List<PcLabelValue> aliasList = collect.stream().filter(o -> StringUtils.isNotEmpty(o.getLabelAlias())).collect(Collectors.toList());
                        // 标签值没有别名，展示标签值，否则展示别名
                        if (aliasList.isEmpty()) {
                            labels.add(collect.stream().map(PcLabelValue::getArgumentsName).collect(Collectors.joining(", ")));
                        } else {
                            labels.add(aliasList.stream().map(PcLabelValue::getLabelAlias).collect(Collectors.joining(", ")));
                        }
                    }
                }
            }
            factoryMap.put(factoryId, labels);
        });
        return factoryMap;
    }

    @Override
    public PcFactoryVo getInfo(String id) {
        PcFactoryQuery query = new PcFactoryQuery();
        query.setId(id);
        List<PcFactoryVo> pcFactoryVos = baseMapper.selectPcFactoryVoList(query, null,null);
        if (CollUtil.isEmpty(pcFactoryVos)) return new PcFactoryVo();

        PcFactoryVo vo = pcFactoryVos.get(0);
        vo.setLabels(getLabel(vo.getId(), true));
        vo.setNonMajorLabels(getLabel(vo.getId(), false));
        vo.setLabelStr(String.join( "，", vo.getLabels()));
        vo.setRegionStr((vo.getCityName() == null ? "" : vo.getCityName()) + (vo.getCountryName() == null ? "" : vo.getCountryName()));
        return vo;
    }

    /**
     * 若标签关联了企业表字段，则需要生成这些字段的企业标签数据，保证企业表数据与企业标签数据一致
     */
    @Override
    public void batchCreateLabel() {
        // 找到所有factory_field不为空的记录
        List<PcLabel> pcLabels = labelMapper.selectList(new QueryWrapper<PcLabel>().isNotNull("factory_field").ne("factory_field", ""));

        if (pcLabels.isEmpty()) {
            return;
        }
        // 所有企业
        List<PcFactory> factories = list();

        // 企业标签表数据
        List<PcLabelFactory> labelFactories = labelFactoryMapper.selectList(new QueryWrapper<PcLabelFactory>()
                .in("label_id", pcLabels.stream().map(PcLabel::getId).collect(Collectors.toList())));

        // 根据企业和标签的组合分组
        Map<String, PcLabelFactory> labelFactoryMap = labelFactories.stream()
                .collect(Collectors.toMap(o -> o.getFactoryId() + "_" + o.getLabelId(), o -> o));

        List<PcLabelFactory> addList = new ArrayList<>(); // 新增的企业标签
        List<PcLabelFactory> updateList = new ArrayList<>(); // 修改的企业标签

        for (PcFactory factory : factories) {
            for (PcLabel pcLabel : pcLabels) {
                String value = BeanUtil.getProperty(factory, pcLabel.getFactoryField());

                PcLabelFactory lf = labelFactoryMap.get(factory.getId() + "_" + pcLabel.getId());
                if (lf == null) {
                    lf = new PcLabelFactory();
                    lf.setFactoryId(factory.getId());
                    lf.setLabelId(pcLabel.getId());
                    lf.setLableUseing("1");
                    lf.setLabelValue(value);
                    lf.setId(UUID.randomUUID().toString());
                    addList.add(lf);
                } else {
                    // 企业表字段与标签值数据不一致
                    if (!Objects.equals(value, lf.getLabelValue())) {
                        lf.setLabelValue(value);
                        updateList.add(lf);
                    }
                }
            }
        }
        if (!addList.isEmpty()) {
            List<List<PcLabelFactory>> partition = ListUtils.partition(addList, 2000);
            for (List<PcLabelFactory> pcLabelFactories : partition) {
                labelFactoryMapper.batchSave(pcLabelFactories);
            }
        }
        if (!updateList.isEmpty()) {
            List<List<PcLabelFactory>> partition = ListUtils.partition(updateList, 2000);
            for (List<PcLabelFactory> pcLabelFactories : partition) {
                labelFactoryMapper.batchUpdateValue(pcLabelFactories);
            }
        }
    }

    @Override
    public void timingUpdateAdslFactory() {
        //查询所有企业 1000分页 遍历
        int offset = 0;
        int limit = 1000;

        // 清空表
        pcAdslFactoryMapper.truncateAll();
        // 插入各个类型的数据
        pcAdslFactoryMapper.onlineAdsl();
        pcAdslFactoryMapper.elecAdsl();
        pcAdslFactoryMapper.dcsAdsl();
        pcAdslFactoryMapper.inorgAdsl();
        pcAdslFactoryMapper.videoAdsl();
        pcAdslFactoryMapper.dynamicAdsl();
        pcAdslFactoryMapper.doorAdsl();

//        //删除企业下 所有关系 改为删除所有数据重新录入
//        pcAdslFactoryMapper.delete(null);
//
//        List<PcFactory> pcFactories = pcFactoryMapper.selectList(Wrappers.<PcFactory>lambdaQuery().select(PcFactory::getId).orderByAsc(PcFactory::getId).last("limit "+ limit +" offset " + offset));
//        while (CollectionUtils.isNotEmpty(pcFactories)) {
//            ((PcFactoryServiceImpl)AopContext.currentProxy()).disposeAdslFactory(pcFactories);
//
//            //循环更新后面的企业
//            offset += limit;
//            pcFactories = pcFactoryMapper.selectList(Wrappers.<PcFactory>lambdaQuery().select(PcFactory::getId).last("limit "+ limit +" offset " + offset));
//        }

        //1	在线监测	A001
        //2	分表计电	A002
        //3	工况监控	A003
        //4	无组织监控A004
        //5	视频监控	A005
        //6	动态管控	A006
        //7	门禁监控	A007

    }

    @Override
    public PcFactory selectPcFactoryById(String factoryId) {
        return pcFactoryMapper.selectPcFactoryById(factoryId);
    }

    @Override
    public List<PcFactoryVo.WarningRank> getWarningRank() {
        // TODO 分表计电报警未接数据
        List<PcFactoryVo.WarningRank> list = new ArrayList<>();
        list.add(new PcFactoryVo.WarningRank("乐亭渤乐畜禽养殖专业合作社", 98L));
        list.add(new PcFactoryVo.WarningRank("广生建材装饰商店", 67L));
        list.add(new PcFactoryVo.WarningRank("迁西县融丰再生资源有限公司", 65L));
        list.add(new PcFactoryVo.WarningRank("唐山金悦食品有限公司", 42L));
        list.add(new PcFactoryVo.WarningRank("玉田县鸦鸿桥镇国永雨衣加工部", 31L));
        list.add(new PcFactoryVo.WarningRank("遵化市平安城镇建营食用菌种植场", 21L));
        list.add(new PcFactoryVo.WarningRank("曹文坤养殖场", 21L));
        list.add(new PcFactoryVo.WarningRank("唐山市远芳食品厂", 13L));
        list.add(new PcFactoryVo.WarningRank("唐山市丰南区侉子庄富强拉丝厂", 13L));
        list.add(new PcFactoryVo.WarningRank("吴艳涛养猪场", 12L));
        return list;
    }

    @Override
    public FactoryOutletVo selectByFactoryAndOutletId(String factoryId, String outletId) {
        return pcFactoryMapper.selectByFactoryAndOutletId(factoryId,outletId);
    }

    @Override
    public void editBatch(PcFactory[] pcFactoryArr) {
        List<PcFactory> pcFactoryList = Arrays.asList(pcFactoryArr);
        //记录操作日志
        List<PcFactoryCoordinateOperationLog> logList = new ArrayList<>();
        pcFactoryList.forEach(e -> {
            PcFactoryCoordinateOperationLog log = new PcFactoryCoordinateOperationLog();
            PcFactory pcFactory = this.getById(e.getId());
            String uuid = UUID.randomUUID().toString().trim().replaceAll("-", "");
            log.setLogId(uuid);
            log.setFactoryId(pcFactory.getId());
            log.setOperationTime(DateUtils.parseFormatDate("yyyy-MM-dd HH:mm:ss", new Date()));
            log.setOperationStatus(OperationTypeEnum.UPDATE_OPERATION.getName());
            log.setOperator(SecurityUtils.getLoginUser().getSysUser().getUserName());
            log.setOperatorId(SecurityUtils.getLoginUser().getSysUser().getUserId() + "");
            log.setFactoryName(pcFactory.getFactoryName());
            log.setBeforeModifyLag(StrUtil.toStringOrNull(pcFactory.getProductionLat()));
            log.setBeforeModifyLng(StrUtil.toStringOrNull(pcFactory.getProductionLon()));
            log.setAfterModifyLag(StrUtil.toStringOrNull(e.getProductionLat()));
            log.setAfterModifyLng(StrUtil.toStringOrNull(e.getProductionLon()));
            logList.add(log);
        });
        baseMapper.updateBatchCoordinate(pcFactoryList);
        pcFactoryCoordinateOperationLogService.saveBatch(logList);
    }

    @Override
    public PcFactoryLicensingStatusVo licenSingStatusList() {
        PcFactoryLicensingStatusVo pcFactoryLicensingStatusVo = pcFactoryMapper.factoryLicensingStatus();
        List<PcCountryLicensingStatusVo> pcCountryLicensingStatusVos = pcFactoryMapper.countryLicensingStatus();
        pcFactoryLicensingStatusVo.setPcCountryLicensingStatusVo(pcCountryLicensingStatusVos);
        return pcFactoryLicensingStatusVo;
    }

    @Override
    public PcProfessionLicensingStatusVo professionStatusChart() {
        PcProfessionLicensingStatusVo pcProfessionLicensingStatusVo = new PcProfessionLicensingStatusVo();
        List<PcIndustry> pcIndustries = pcIndustryMapper.selectList(new QueryWrapper<PcIndustry>().orderByAsc("order_num"));
        List<String> dataX = pcIndustries.stream().map(PcIndustry::getIndusName).collect(Collectors.toList());
        pcProfessionLicensingStatusVo.setDataX(dataX);
        Map<String, String> licenseManType = MapUtil.<String, String>builder()
                .put("FOCUS", "重点管理")
                .put("SIMPLIFY", "简化管理")
                .put("REGISTER", "登记管理")
                .build();
        List<Map<String,Object>> seriesList = new ArrayList<>();
        QueryWrapper<PcFactory> queryWrapper = new QueryWrapper<>();
        for (String type : licenseManType.keySet()) {
            Map<String,Object> series = new HashMap<>();
            series.put("name",licenseManType.get(type));
            List<Integer> dataList = new ArrayList<>();
            for (PcIndustry pcIndustry : pcIndustries) {
                queryWrapper.clear();
                queryWrapper.eq("license_man_type",type);
                queryWrapper.eq("industry_category",pcIndustry.getIndusCode());
                Integer count = pcFactoryMapper.selectCount(queryWrapper);
                dataList.add(count);
            }
            series.put("data",dataList);
            seriesList.add(series);
        }
        pcProfessionLicensingStatusVo.setSeries(seriesList);
        return pcProfessionLicensingStatusVo;
    }

    @Override
    public List<PwxkFactoryVo> selectPwxkList(Page<PwxkFactoryVo> page, PcFactoryQuery.SearchVo searchVo) {
        Page<PcFactoryVo> pcFactoryVoPage = new Page<>(searchVo.getPageNum(), searchVo.getPageSize());
        List<PcFactoryVo> list = search(pcFactoryVoPage, searchVo, null, SecurityUtils.getLoginUser().getSysUser().getRegionCode());

        List<PwxkFactoryVo> collect = list.stream().map(o -> {
            PwxkFactoryVo pwxkFactoryVo = new PwxkFactoryVo();
            BeanUtils.copyProperties(o, pwxkFactoryVo);

            if (StringUtils.isNotBlank(pwxkFactoryVo.getEnvironmentalCode())) {
                try {
                    Map<String, Object> extra = JSON.parseObject(pwxkFactoryVo.getEnvironmentalCode(), new TypeReference<Map<String, Object>>() {});
                    pwxkFactoryVo.setEnvironmentalCode((String) extra.get("itempfwh"));
                } catch (Exception e) {
                    // 解析失败
                }
            }
            return pwxkFactoryVo;
        }).collect(Collectors.toList());

        page.setTotal(pcFactoryVoPage.getTotal());
        return collect;
    }

    //    @Transactional(rollbackFor=Exception.class)  数据配置太低  无法支持事务处理方式 暂时去掉
    public void disposeAdslFactory(List<PcFactory> pcFactories) {
        Set<String> factoryIds = pcFactories.stream().map(x -> {
            return x.getId();
        }).collect(Collectors.toSet());

//            pcFactoryMapper.selectList(Wrappers.<PcFactory>lambdaQuery().in(PcFactory::getFactoryName, factoryIds));
        if (CollectionUtils.isNotEmpty(factoryIds)) {
            List<PcAdslFactory> pcAdslFactories = pcFactoryMapper.selectSourceIsHaveDataByFacIds(factoryIds);

            //更新企业与数据源的关系
            for (PcAdslFactory pcAdslFactory : pcAdslFactories) {
                try {
                    iPcAdslFactoryService.save(pcAdslFactory);
                } catch (Exception e) {
                    log.error("更新企业与数据源的关系失败 : " + e.toString() +"信息" + pcAdslFactory.toString());
                }
            }
        }
    }

    @Override
    public List<PcFactoryVo> search(Page<PcFactoryVo> page, PcFactoryQuery.SearchVo searchVo, String home,String regionCode) {
        String factoryName = searchVo.getFactoryName();
        List<String> regionCodes=new ArrayList<>();
        R<List<String>> r = baseRegionService.getRegionCodeListChild(regionCode);
        if(r.getCode()==200){
            regionCodes=r.getData();
        }
        List<PcFactoryVo> pcFactoryVos = new ArrayList<>();

        // 若未指定标签，直接查询企业表
        if (searchVo.getLabelMap() == null || searchVo.getLabelMap().size() == 0) {
            PcFactoryQuery query = new PcFactoryQuery();
            query.setFactoryName(factoryName);
            query.setLabelAndValue(searchVo.getLabelAndValue());

            if (page == null) {
                pcFactoryVos = baseMapper.selectPcFactoryVoList(query,home,regionCodes);
            } else {
                pcFactoryVos = baseMapper.selectPcFactoryVoPage(page, query, home,regionCodes);
            }
        } else {
            Map<String, List<String>> labelMap = new HashMap<>();

            // 将Map<String, Object>转换为Map<String, List<String>>
            searchVo.getLabelMap().forEach((key, value) -> {
                List<String> l = new ArrayList<>();
                if (value instanceof Collection) {
                    Collection c = (Collection) value;
                    c.forEach(o -> l.add(o.toString()));
                } else {
                    l.add(value.toString());
                }
                labelMap.put(key, l);
            });
            List<PcLabelFactory> labelFactories = labelFactoryMapper.selectLabelFactory(factoryName, labelMap.keySet());

            // 按照企业分组
            Map<String, List<PcLabelFactory>> factoryMap = labelFactories.stream().collect(Collectors.groupingBy(PcLabelFactory::getFactoryId, LinkedHashMap::new, Collectors.toList()));

            // 根据标签过滤企业
            List<String> factoryIds = factoryMap.entrySet().stream().filter(entry -> {
                // 遍历所有页面传入的标签，判断企业是否都满足
                for (String labelId : labelMap.keySet()) {
                    PcLabelFactory lf = entry.getValue().stream().filter(o -> o.getLabelId().equals(labelId)).findFirst().orElse(null);
                    // 企业不存在该标签，不满足条件
                    if (lf == null) {
                        return false;
                    }
                    // 标签值为空，不满足条件
                    if (StringUtils.isEmpty(lf.getLabelValue())) {
                        return false;
                    }
                    // 企业某项标签值可能有多个，表中存储时会用逗号分隔
                    String[] factoryLabelValues = lf.getLabelValue().split(",");
                    List<String> inputLabelValues = labelMap.get(labelId);

                    // 若标签是“包含数据类型”，需要满足并且的关系，其余标签满足或的关系
                    if (labelId.equals("105")) {
                        for (String s : inputLabelValues) {
                            boolean exists = false;
                            for (String flv : factoryLabelValues) {
                                if (s.equals(flv)) {
                                    exists = true;
                                    break;
                                }
                            }
                            if (!exists) {
                                return false;
                            }
                        }
                    } else {
                        // 企业的标签值与页面传入的标签值是否存在交集，默认不存在
                        boolean exists = false;

                        for (String s : inputLabelValues) {
                            for (String flv : factoryLabelValues) {
                                if (s.equals(flv)) {
                                    exists = true;
                                    break;
                                }
                            }
                            if (exists) {
                                break;
                            }
                        }
                        // 标签值不存在交集，不满足条件
                        if (!exists) {
                            return false;
                        }
                    }
                }
                return true;
            }).map(Map.Entry::getKey).collect(Collectors.toList());

            if (page != null) {
                page.setTotal(factoryIds.size());
                factoryIds = factoryIds.stream()
                        // 分页
                        .skip((page.getCurrent() - 1) * page.getSize())
                        .limit(page.getSize())
                        .collect(Collectors.toList());
            }

            if (!factoryIds.isEmpty()) {
                PcFactoryQuery query = new PcFactoryQuery();
                query.setIds(factoryIds);
                pcFactoryVos = baseMapper.selectPcFactoryVoList(query, home,regionCodes);
            }
        }
        if (page != null) {
            page.setRecords(pcFactoryVos);
        }

        if (searchVo.getShowMainLable() != null && searchVo.getShowMainLable()) {
            // >> 获取指定企业重点标签
            Map<String, List<String>> mainLabel = getLabel(pcFactoryVos.stream().map(PcFactoryVo::getId).collect(Collectors.toList()), true);

            pcFactoryVos.forEach(vo -> {
                List<String> list = mainLabel.get(vo.getId());
                vo.setLabels(list == null ? new ArrayList<>() : list);
                vo.setLabelStr(String.join( "，", vo.getLabels()));
            });
        }
        pcFactoryVos.forEach(vo -> {
            vo.setRegionStr((vo.getCityName() == null ? "" : vo.getCityName()) + (vo.getCountryName() == null ? "" : vo.getCountryName()));
        });
        return pcFactoryVos;
    }

}
