package com.hw.ems.base.service.impl;


import com.hw.common.core.exception.ServiceException;
import com.hw.common.core.text.Convert;
import com.hw.common.core.utils.DateUtils;
import com.hw.common.core.utils.StringUtils;
import com.hw.common.security.utils.SecurityUtils;
import com.hw.ems.base.domain.*;
import com.hw.ems.base.domain.vo.MonitorVo;
import com.hw.ems.base.mapper.*;
import com.hw.ems.base.service.IBaseMonitorInfoService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * 计量设备信息Service业务层处理
 *
 * @author YinQ
 * @date 2023-04-06
 */
@Service
public class BaseMonitorInfoServiceImpl implements IBaseMonitorInfoService {
    @Autowired
    private BaseMonitorInfoMapper baseMonitorInfoMapper;

    @Autowired
    private BaseBusinessTypeMapper baseBusinessTypeMapper;

    @Autowired
    private BaseSubentryTypeMapper baseSubentryTypeMapper;

    @Autowired
    private BaseBuildInfoMapper baseBuildInfoMapper;

    @Autowired
    private BaseTypeRelationMapper baseTypeRelationMapper;

    @Autowired
    private BaseLineLossMapper baseLineLossMapper;

    @Autowired
    private BasePublicUserMapper basePublicUserMapper;

    /**
     * 查询计量设备信息
     *
     * @param objid 计量设备信息主键
     * @return 计量设备信息
     */
    @Override
    //@DS("#header.poolName")
    public BaseMonitorInfo selectBaseMonitorInfoByObjid(Long objid) {
        return baseMonitorInfoMapper.selectBaseMonitorInfoByObjid(objid);
    }

    /**
     * 查询计量设备信息列表
     *
     * @param baseMonitorInfo 计量设备信息
     * @return 计量设备信息
     */
    @Override
//    @DataScope(deptAlias = "null")
    //@DS("#header.poolName")
    public List<BaseMonitorInfo> selectBaseMonitorInfoList(BaseMonitorInfo baseMonitorInfo) {
        return baseMonitorInfoMapper.selectBaseMonitorInfoList(baseMonitorInfo);
    }

    /**
     * 新增计量设备信息
     *
     * @param baseMonitorInfo 计量设备信息
     * @return 结果
     */
    @Override
    //@DS("#header.poolName")
    public int insertBaseMonitorInfo(BaseMonitorInfo baseMonitorInfo) {
        //校验插入校验MonitorId是否合法
        List<BaseMonitorInfo> baseMonitorInfos = baseMonitorInfoMapper.checkMonitorIdLegal(baseMonitorInfo);
        if (baseMonitorInfos.size() != 0) {
            throw new ServiceException("计量设备编号重复:" + baseMonitorInfo.getMonitorId());
        }
        try {
            //查询父计量设备
            BaseMonitorInfo monitor = baseMonitorInfoMapper.selectBaseMonitorInfoByObjid(baseMonitorInfo.getParentId());
            //修改祖籍列表为 原祖籍列表+设备编号，用逗号隔开
            monitor.setAncestors(monitor.getAncestors() + "," + monitor.getMonitorId());
            //获取祖籍列表与设备编号，存入数组中
            String[] split = monitor.getAncestors().split(",");
            //为父设备添加等级信息
            monitor.setGrade(split.length);
            //传参为 新增设备的id，建筑类型，业务类型，分项类型
            this.insertOrUpdateBaseTypeRelation(baseMonitorInfo.getMonitorId(), baseMonitorInfo.getBuildId(),
                    baseMonitorInfo.getBusinessId(), baseMonitorInfo.getSubentryId());
            //查询计量设备有子集的父级List
            List<BaseMonitorInfo> subsetList = this.selectMonitorSubsetList(new BaseMonitorInfo());
            //添加线损对象
            this.insertLineLossList(subsetList);
        } catch (Exception e) {
            System.out.println("新增计量设备信息异常:" + e.getMessage());
        }
        baseMonitorInfo.setCreateTime(DateUtils.getNowDate());
        baseMonitorInfo.setCreateBy(SecurityUtils.getUsername());
        return baseMonitorInfoMapper.insertBaseMonitorInfo(baseMonitorInfo);
    }

    /**
     * 修改计量设备信息
     *
     * @param baseMonitorInfo 计量设备信息
     * @return 结果
     */
    @Override
    //@DS("#header.poolName")
    public int updateBaseMonitorInfo(BaseMonitorInfo baseMonitorInfo) {
        //首先校验修改后的id是否合法
        List<BaseMonitorInfo> baseMonitorInfos = baseMonitorInfoMapper.checkMonitorIdLegal(baseMonitorInfo);
        if (baseMonitorInfos.size() > 1) {
            throw new ServiceException("计量设备编号重复:" + baseMonitorInfo.getMonitorId());
        }
        try {
            //查询父计量设备信息
            BaseMonitorInfo newParenMonitorInfo = baseMonitorInfoMapper.selectBaseMonitorInfoByObjid(baseMonitorInfo.getParentId());
            //查询修改前的计量设备信息
            BaseMonitorInfo oldDeptMonitorInfo = selectBaseMonitorInfoByObjid(baseMonitorInfo.getObjid());
            //若父设备与修改的计量设备信息都不为null
            if (StringUtils.isNotNull(newParenMonitorInfo) && StringUtils.isNotNull(oldDeptMonitorInfo)) {
                //父计量设备祖籍列表+被修改的计量设备的编号
                String newAncestors = newParenMonitorInfo.getAncestors() + "," + oldDeptMonitorInfo.getMonitorId();
                String oldAncestors = oldDeptMonitorInfo.getAncestors();
                baseMonitorInfo.setAncestors(newAncestors);
                String[] split = baseMonitorInfo.getAncestors().split(",");
                baseMonitorInfo.setGrade(split.length);

                updateMonitorChildren(baseMonitorInfo.getMonitorId(), newAncestors, oldAncestors);
            }

            this.insertOrUpdateBaseTypeRelation(baseMonitorInfo.getMonitorId(), baseMonitorInfo.getBuildId(),
                    baseMonitorInfo.getBusinessId(), baseMonitorInfo.getSubentryId());
        } catch (Exception e) {
            e.printStackTrace();
        }
        baseMonitorInfo.setUpdateTime(DateUtils.getNowDate());
        baseMonitorInfo.setUpdateBy(SecurityUtils.getUsername());
        return baseMonitorInfoMapper.updateBaseMonitorInfo(baseMonitorInfo);
    }

    //@DS("#header.poolName")
    public List<BaseMonitorInfo> selectChildrenMonitorById(String monitorId) {
        List<BaseMonitorInfo> children = baseMonitorInfoMapper.selectChildrenMonitorById(monitorId);
        return children;
    }

    /**
     * 修改子元素关系
     *
     * @param monitorId    被修改的ID
     * @param newAncestors 新的父ID集合
     * @param oldAncestors 旧的父ID集合
     */
    //@DS("#header.poolName")
    private void updateMonitorChildren(String monitorId, String newAncestors, String oldAncestors) {
        //查询祖籍列表中是否包含被修改的id
        List<BaseMonitorInfo> children = baseMonitorInfoMapper.selectChildrenMonitorById(monitorId);
        //替换被修改id的祖籍列表
        for (BaseMonitorInfo child : children) {
            child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
        }
        //如果包含，则进行修改
        if (children.size() > 0) {
            baseMonitorInfoMapper.updateMonitorChildren(children);
        }

    }

    /**
     * 修改子元素关系
     *
     * @param deptId 被修改的部门ID
     * @param newAncestors 新的父ID集合
     * @param oldAncestors 旧的父ID集合
     */
//    public void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors)
//    {
//        List<SysDept> children = baseMonitorInfoMapper.selectBaseMonitorInfoByObjid(deptId);
//        for (SysDept child : children)
//        {
//            child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
//        }
//        if (children.size() > 0)
//        {
//            deptMapper.updateDeptChildren(children);
//        }
//    }


    /**
     * 批量删除计量设备信息
     *
     * @param objids 需要删除的计量设备信息主键
     * @return 结果
     */
    @Override
    //@DS("#header.poolName")
    public int deleteBaseMonitorInfoByObjids(String objids) {
        return baseMonitorInfoMapper.deleteBaseMonitorInfoByObjids(Convert.toStrArray(objids));
    }

    /**
     * 删除计量设备信息信息
     *
     * @param objid 计量设备信息主键
     * @return 结果
     */
    @Override
    //@DS("#header.poolName")
    public int deleteBaseMonitorInfoByObjid(Long objid) {
        return baseMonitorInfoMapper.deleteBaseMonitorInfoByObjid(objid);
    }

    /**
     * 查询计量设备信息树列表
     *
     * @return 所有计量设备信息信息
     */
    @Override
    //@DS("#header.poolName")
    public List<BaseTree> selectBaseMonitorInfoTree(Long monitorType) {
        BaseMonitorInfo monitorInfo = new BaseMonitorInfo();
        monitorInfo.setMonitorType(monitorType);
        List<BaseMonitorInfo> baseMonitorInfoList = baseMonitorInfoMapper.selectBaseMonitorInfoList(monitorInfo);
        List<BaseTree> ztrees = new ArrayList<>();
        for (BaseMonitorInfo baseMonitorInfo : baseMonitorInfoList) {
            BaseTree ztree = new BaseTree();
            ztree.setId(baseMonitorInfo.getObjid());
            ztree.setpId(baseMonitorInfo.getParentId());
            ztree.setName(baseMonitorInfo.getMonitorName());
            ztree.setTitle(baseMonitorInfo.getMonitorName());
            ztree.setMonitorId(baseMonitorInfo.getMonitorId());
            ztrees.add(ztree);
        }
        return ztrees;
    }

    /**
     * 查询计量设备有子集的父级List
     *
     * @param baseMonitorInfo 计量设备信息
     * @return
     */
    @Override
    //@DS("#header.poolName")
    public List<BaseMonitorInfo> selectMonitorSubsetList(BaseMonitorInfo baseMonitorInfo) {
        List<BaseMonitorInfo> result = new ArrayList<>();
        try {
            List<BaseMonitorInfo> baseMonitorInfoList = baseMonitorInfoMapper.selectBaseMonitorInfoList(baseMonitorInfo);
            result = baseMonitorInfoList.stream()
                    .filter(info -> info.getParentId() == null || baseMonitorInfoList.stream()
                            .anyMatch(parent -> info.getObjid().equals(parent.getParentId())))
                    .collect(Collectors.toList());
        } catch (Exception e) {
            System.out.println("查询计量设备有子集的父级List异常：" + e.getMessage());
        }
        return result;
    }


    /**
     * monitor获取所有子集
     *
     * @param monitorInfoList
     * @return
     */
    public HashMap<String, List<BaseMonitorInfo>> buildMonitorMap(List<BaseMonitorInfo> monitorInfoList) {
        HashMap<String, List<BaseMonitorInfo>> resultMap = new HashMap<>();
        for (BaseMonitorInfo monitorInfo : monitorInfoList) {
            String monitorId = monitorInfo.getMonitorId();
            Long parentId = monitorInfo.getParentId();
            List<BaseMonitorInfo> subList = resultMap.getOrDefault(monitorId, new ArrayList<>());
            subList.add(monitorInfo);
            resultMap.put(monitorId, subList);
            if (parentId != null) {
                List<BaseMonitorInfo> parentSubList = resultMap.getOrDefault(parentId.toString(), new ArrayList<>());
                parentSubList.add(monitorInfo);
                resultMap.put(parentId.toString(), parentSubList);
            }
        }
        return buildChildMap(resultMap, null);
    }

    private static HashMap<String, List<BaseMonitorInfo>> buildChildMap(HashMap<String, List<BaseMonitorInfo>> resultMap, String parentId) {
        HashMap<String, List<BaseMonitorInfo>> childMap = new HashMap<>();
        for (Map.Entry<String, List<BaseMonitorInfo>> entry : resultMap.entrySet()) {
            String monitorId = entry.getKey();
            BaseMonitorInfo monitorInfo = entry.getValue().get(0);
            Long parent = monitorInfo.getParentId();
            if (parentId == null && parent == null || parentId != null && parentId.equals(parent.toString())) {
                childMap.put(monitorId, entry.getValue());
                List<BaseMonitorInfo> children = buildChildMap(resultMap, monitorId).get(monitorId);
                if (children != null) {
                    entry.getValue().addAll(children);
                }
            }
        }
        return childMap;
    }


    /**
     * 新增或更新计量与类型对应关系
     *
     * @param buildId
     * @param businessId
     * @param subentryId
     */
    //@DS("#header.poolName")
    private void insertOrUpdateBaseTypeRelation(String monitorId, String buildId, String businessId, String subentryId) {
        BaseTypeRelation typeRelation = new BaseTypeRelation();
        //存入计量设备编号
        typeRelation.setMonitorId(monitorId);
        //通过编号查询计量与类型对应关系对象的集合
        List<BaseTypeRelation> baseTypeRelations = baseTypeRelationMapper.selectBaseTypeRelationList(typeRelation);
        //通过objid转换为字符串数组，将之前的对应关系删除
        if (baseTypeRelations.size() > 0) {
            String[] objids = baseTypeRelations.stream().
                    map(BaseTypeRelation::getObjid).map(String::valueOf).toArray(String[]::new);
            baseTypeRelationMapper.deleteBaseTypeRelationByObjids(objids);
        }
        // type: 0-建筑  1-业态  2-分项
        //如果新建出类型对应关系数据
        if (StringUtils.isNotEmpty(buildId)) {
            String[] buildIds = buildId.split(",");
            for (String id : buildIds) {
                BaseTypeRelation relation = new BaseTypeRelation();
                relation.setMonitorId(monitorId);
                relation.setType(0L);
                relation.setRelationId(Long.parseLong(id));
                baseTypeRelationMapper.insertBaseTypeRelation(relation);
            }
        }
        if (StringUtils.isNotEmpty(businessId)) {
            String[] businessIds = businessId.split(",");
            for (String id : businessIds) {
                BaseTypeRelation relation = new BaseTypeRelation();
                relation.setMonitorId(monitorId);
                relation.setType(1L);
                relation.setRelationId(Long.parseLong(id));
                baseTypeRelationMapper.insertBaseTypeRelation(relation);
            }
        }
        if (StringUtils.isNotEmpty(subentryId)) {
            String[] subentryIds = subentryId.split(",");
            for (String id : subentryIds) {
                BaseTypeRelation relation = new BaseTypeRelation();
                relation.setMonitorId(monitorId);
                relation.setType(2L);
                relation.setRelationId(Long.parseLong(id));
                baseTypeRelationMapper.insertBaseTypeRelation(relation);
            }
        }
    }

    /**
     * 新增线损对象信息
     *
     * @param monitorInfoList
     */
    //@DS("#header.poolName")
    private void insertLineLossList(List<BaseMonitorInfo> monitorInfoList) {
        boolean flag = true;
        //查出所有的线损信息对象
        List<BaseLineLoss> baseLineLosses = baseLineLossMapper.selectBaseLineLossList(new BaseLineLoss());
        if (monitorInfoList.size() == 0) {
            return;
        } else if (baseLineLosses.size() == 0) {
            flag = false;
        }
        //双层循环，判断该父级设备是否拥有线损对象，如果有则不生成新的线损对象
        for (BaseMonitorInfo monitorInfo : monitorInfoList) {
            boolean isHaveMonitor = true;
            if (flag) {
                //循环获取监测点编号
                for (BaseLineLoss baseLineLoss : baseLineLosses) {
                    if (baseLineLoss.getMonitorId().equals(monitorInfo.getMonitorId())) {
                        isHaveMonitor = false;
                        break;
                    }
                }
            }
            if (isHaveMonitor) {
                BaseLineLoss baseLineLoss = new BaseLineLoss();
                baseLineLoss.setMonitorId(monitorInfo.getMonitorId());
                baseLineLoss.setMonitorName(monitorInfo.getMonitorName());
                baseLineLoss.setLineLossId(monitorInfo.getMonitorId());
                baseLineLoss.setLineLossName(monitorInfo.getMonitorName());
                baseLineLoss.setMonitorType(monitorInfo.getMonitorType());
                baseLineLoss.setLineLossStatus(monitorInfo.getMonitorStatus());
                baseLineLoss.setCreateBy(SecurityUtils.getUsername());
                baseLineLoss.setCreateTime(new Date());
                baseLineLossMapper.insertBaseLineLoss(baseLineLoss);
            }
        }
    }

    /**
     * 获取monitorId下一级不为假表的节点
     *
     * @param monitors
     * @param monitorId
     * @return
     */
    public static List<BaseMonitorInfo> getNextLevelAmmeter(List<BaseMonitorInfo> monitors, String monitorId) {
        List<BaseMonitorInfo> result = new ArrayList<>();
        BaseMonitorInfo current = null;
        for (BaseMonitorInfo monitor : monitors) {
            if (monitor.getMonitorId().equals(monitorId)) {
                current = monitor;
                break;
            }
        }
        if (current == null) {
            return result;
        }
        for (BaseMonitorInfo child : monitors) {
            if (child.getParentId().equals(current.getObjid()) && child.getMonitorStatus() != 1) {
                if (child.getIsAmmeter().equals("true")) {
                    result.add(child);
                } else {
                    List<BaseMonitorInfo> subResult = getNextLevelAmmeter(monitors, child.getMonitorId());
                    result.addAll(subResult);
                }
            }
        }
        return result;
    }

    /**
     * 查询类型园区下第一级
     * @param type
     * @return
     */
    @Override
    //@DS("#header.poolName")
    public ArrayList<BaseTypeRelation> selectTypeSubset(Long type) {
        ArrayList<BaseTypeRelation> typeRelations = new ArrayList<>();
        BaseTypeRelation relation = new BaseTypeRelation();
        relation.setType(0L);
        relation.setRelationId(1L);
        relation.setUnitName("全部");
        typeRelations.add(relation);
        if (type == 0){
            BaseBuildInfo baseBuildInfo = new BaseBuildInfo();
            baseBuildInfo.setParentId(1L);
            List<BaseBuildInfo> baseBuildInfos = baseBuildInfoMapper.selectBaseBuildInfoList(baseBuildInfo);
            for (BaseBuildInfo buildInfo : baseBuildInfos) {
                BaseTypeRelation typeRelation = new BaseTypeRelation();
                typeRelation.setType(0L);
                typeRelation.setRelationId(buildInfo.getObjid());
                typeRelation.setUnitName(buildInfo.getBuildName());
                typeRelations.add(typeRelation);
            }
        }else if (type == 1L){
            BaseBusinessType businessType = new BaseBusinessType();
            businessType.setParentId(1L);
            List<BaseBusinessType> baseBusinessTypes = baseBusinessTypeMapper.selectBaseBusinessTypeList(businessType);
            for (BaseBusinessType baseBusinessType : baseBusinessTypes) {
                BaseTypeRelation typeRelation = new BaseTypeRelation();
                typeRelation.setType(1L);
                typeRelation.setRelationId(baseBusinessType.getObjid());
                typeRelation.setUnitName(baseBusinessType.getBusinessName());
                typeRelations.add(typeRelation);
            }
        }else if (type == 2L){
            BaseSubentryType subentryType = new BaseSubentryType();
            subentryType.setParentId(1L);
            List<BaseSubentryType> baseSubentryTypes = baseSubentryTypeMapper.selectBaseSubentryTypeList(subentryType);
            for (BaseSubentryType baseSubentryType : baseSubentryTypes) {
                BaseTypeRelation typeRelation = new BaseTypeRelation();
                typeRelation.setType(2L);
                typeRelation.setRelationId(baseSubentryType.getObjid());
                typeRelation.setUnitName(baseSubentryType.getSubentryName());
                typeRelations.add(typeRelation);
            }
        }
        return typeRelations;
    }

    @Override
    //@DS("#header.poolName")
    public List<BaseMonitorInfo> monitorLedgerList(BaseMonitorInfo baseMonitorInfo) {
        return baseMonitorInfoMapper.monitorLedgerList(baseMonitorInfo);
    }

    @Override
    //@DS("#header.poolName")
    public List<BaseMonitorInfo> selectMonitor(Long publicShareId) {
        /**查询修改本条信息*/
        BasePublicUser basePublicUser = basePublicUserMapper.selectBasePublicUserById(publicShareId);
        BaseMonitorInfo baseMonitorInfo=new BaseMonitorInfo();
        baseMonitorInfo.setPublicShareType(1);
        List<BaseMonitorInfo> baseMonitorInfoList=baseMonitorInfoMapper.selectBaseMonitorInfoList(baseMonitorInfo);
        List<BaseMonitorInfo> BaseMonitorInfoVOS=new ArrayList<>();
        if (baseMonitorInfoList.size()>0){
            BaseMonitorInfoVOS=baseMonitorInfoList.stream().map(bmil -> {
                BaseMonitorInfo b=new BaseMonitorInfo();
                b.setMonitorId(bmil.getMonitorId());
                b.setMonitorName(bmil.getMonitorName());
                for (MonitorVo value : basePublicUser.getMonitors()){
                    if (bmil.getMonitorId().equals(value.getMonitorId())){
                        b.setFlag(true);
                    }
                }
                return b;
            }).collect(Collectors.toList());

        }
        return BaseMonitorInfoVOS;
    }

    @Override
    //@DS("#header.poolName")
    public List<BaseMonitorInfo> selectDistinctPublicMonitor(String[] ids) {
        return basePublicUserMapper.selectDistinctPublicMonitor(ids);
    }

    @Override
    //@DS("#header.poolName")
    public BigDecimal queryPublicMonitorExpend(String[] ids, String startTime, String endTime, Long energyType) {
        if (energyType == 3L){
            return basePublicUserMapper.queryPublicMonitorWaterExpend(ids,startTime,endTime);
        }
        return basePublicUserMapper.queryPublicMonitorDnbExpend(ids,startTime,endTime);
    }

}
