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

import com.hw.common.core.domain.Ztree;
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.BaseLineLoss;
import com.hw.ems.base.domain.BaseLineMonitor;
import com.hw.ems.base.mapper.BaseLineLossMapper;
import com.hw.ems.base.mapper.BaseLineMonitorMapper;
import com.hw.ems.base.service.IBaseLineMonitorService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * 线路计量信息Service业务层处理
 *
 * @author YinQ
 * @date 2023-04-22
 */
@Service
public class BaseLineMonitorServiceImpl implements IBaseLineMonitorService {
    @Autowired
    private BaseLineMonitorMapper baseLineMonitorMapper;

    @Autowired
    private BaseLineLossMapper baseLineLossMapper;

    /**
     * 查询线路计量信息
     *
     * @param objid 线路计量信息主键
     * @return 线路计量信息
     */
    @Override
    //@DS("#header.poolName")
    public BaseLineMonitor selectBaseLineMonitorByObjid(Long objid) {
        return baseLineMonitorMapper.selectBaseLineMonitorByObjid(objid);
    }

    /**
     * 查询线路计量信息列表
     *
     * @param baseLineMonitor 线路计量信息
     * @return 线路计量信息
     */
    @Override
    //@DS("#header.poolName")
//    @DataScope(deptAlias = "null")
    public List<BaseLineMonitor> selectBaseLineMonitorList(BaseLineMonitor baseLineMonitor) {
        return baseLineMonitorMapper.selectBaseLineMonitorList(baseLineMonitor);
    }

    /**
     * 新增线路计量信息
     *
     * @param baseLineMonitor 线路计量信息
     * @return 结果
     */
    @Override
    //@DS("#header.poolName")
    public int insertBaseLineMonitor(BaseLineMonitor baseLineMonitor) {
        baseLineMonitor.setCreateTime(DateUtils.getNowDate());
        try {
            baseLineMonitorMapper.insertBaseLineMonitor(baseLineMonitor);
            //查询计量设备有子集的父级List
            List<BaseLineMonitor> subsetList = this.selectMonitorSubsetList(new BaseLineMonitor());
            //添加线损对象
            this.insertLineLossList(subsetList);
            return 1;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 修改线路计量信息
     *
     * @param baseLineMonitor 线路计量信息
     * @return 结果
     */
    @Override
    //@DS("#header.poolName")
    public int updateBaseLineMonitor(BaseLineMonitor baseLineMonitor) {
        try {
            List<BaseLineMonitor> baseLineMonitors = baseLineMonitorMapper.selectBaseLineMonitorList(new BaseLineMonitor());
            List<Long> objIdList = baseLineMonitors.stream().map(BaseLineMonitor::getObjid).collect(Collectors.toList());

            // 线路计量信息等级更新
            for (BaseLineMonitor lineMonitor : baseLineMonitors) {
                if (lineMonitor.getObjid().equals(lineMonitor.getParentId())){
                    continue;
                }
                Long grade = 0L;
                grade = updateLineMonitorGrade(baseLineMonitors, lineMonitor, objIdList, grade);
                if (StringUtils.isNull(lineMonitor.getGrade()) || !lineMonitor.getGrade().equals(grade)){
                    lineMonitor.setGrade(grade);
                    baseLineMonitorMapper.updateBaseLineMonitor(lineMonitor);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        baseLineMonitor.setUpdateTime(DateUtils.getNowDate());
        return baseLineMonitorMapper.updateBaseLineMonitor(baseLineMonitor);
    }

    /**
     * 线路计量信息等级更新
     * @param baseLineMonitors
     * @param lineMonitor
     * @param objIdList
     * @param grade
     * @return
     */
    private Long updateLineMonitorGrade(List<BaseLineMonitor> baseLineMonitors, BaseLineMonitor lineMonitor, List<Long> objIdList, Long grade) {
        if (objIdList.contains(lineMonitor.getParentId())){
            List<BaseLineMonitor> lineMonitorList = baseLineMonitors.stream().
                    filter(e -> e.getObjid().equals(lineMonitor.getParentId())).collect(Collectors.toList());
            grade = updateLineMonitorGrade(baseLineMonitors, lineMonitorList.get(0), objIdList, grade) + 1L;
        }
        return grade;
    }


    /**
     * 批量删除线路计量信息
     *
     * @param ids 需要删除的线路计量信息主键
     * @return 结果
     */
    @Override
    //@DS("#header.poolName")
    public int deleteBaseLineMonitorByObjids(Long[] ids) {
        return baseLineMonitorMapper.deleteBaseLineMonitorByObjids(ids);
    }

    /**
     * 删除线路计量信息信息
     *
     * @param objid 线路计量信息主键
     * @return 结果
     */
    @Override
    //@DS("#header.poolName")
    public int deleteBaseLineMonitorByObjid(Long objid) {
        return baseLineMonitorMapper.deleteBaseLineMonitorByObjid(objid);
    }

    /**
     * 查询线路计量信息树列表
     *
     * @return 所有线路计量信息信息
     */
    @Override
    //@DS("#header.poolName")
    public List<Ztree> selectBaseLineMonitorTree(BaseLineMonitor lineMonitor) {
        List<BaseLineMonitor> baseLineMonitorList = baseLineMonitorMapper.selectBaseLineMonitorList(lineMonitor);
        List<Ztree> ztrees = new ArrayList<Ztree>();
        for (BaseLineMonitor baseLineMonitor : baseLineMonitorList) {
            Ztree ztree = new Ztree();
            ztree.setId(baseLineMonitor.getObjid());
            ztree.setpId(baseLineMonitor.getParentId());
            ztree.setName(baseLineMonitor.getMonitorName());
            ztree.setTitle(baseLineMonitor.getMonitorName());
            ztrees.add(ztree);
        }
        return ztrees;
    }

    /**
     * 查询计量设备有子集的父级List
     *
     * @param baseLineMonitor 计量设备信息
     * @return
     */
    @Override
    //@DS("#header.poolName")
    public List<BaseLineMonitor> selectMonitorSubsetList(BaseLineMonitor baseLineMonitor) {
        List<BaseLineMonitor> result = new ArrayList<>();
        try {
            List<BaseLineMonitor> baseMonitorInfoList = baseLineMonitorMapper.selectBaseLineMonitorList(baseLineMonitor);
            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;
    }

    /**
     * 新增线损对象信息
     *
     * @param lineMonitorList
     */
    //先查询出有子集的父级list集合
    //然后再将已有线损对象的父级对象删除
    //将多路供电线损根据id转为map
    //
    //@DS("#header.poolName")
    private void insertLineLossList(List<BaseLineMonitor> lineMonitorList) {
        //传入线路计量信息对象集合
        boolean flag = true;
        //多路供电线损
        //null
        List<BaseLineLoss> multipleLosses = baseLineLossMapper.selectMultiplePowerSuppliesList(new BaseLineLoss());
        //空指针
        for (BaseLineLoss multipleLoss : multipleLosses) {
            // 删除符合条件的 BaseLineMonitor 对象
            lineMonitorList.removeIf(lineMonitor -> lineMonitor.getMonitorId().equals(multipleLoss.getMonitorId()));
        }
        Map<String, List<BaseLineLoss>> multipleMap = multipleLosses.stream().collect(Collectors.groupingBy(BaseLineLoss::getLineLossId));
        for (String multipleId : multipleMap.keySet()) {
            List<String> monitorIdList = new ArrayList<>();
            List<String> monitorNameList = new ArrayList<>();
            //父级List
            for (BaseLineLoss baseLineLoss : multipleMap.get(multipleId)) {
                monitorIdList.add(baseLineLoss.getMonitorId());
                monitorNameList.add(baseLineLoss.getMonitorName());
            }
            //如果有多路供电的线路，将其id总和到一起，创建一个线损对象，中间根据“|”分开
            BaseLineMonitor baseLineMonitor = new BaseLineMonitor();
            baseLineMonitor.setMonitorId(String.join("|", monitorIdList));
            baseLineMonitor.setMonitorName(String.join("|", monitorNameList));
            baseLineMonitor.setMonitorType(2L);
            baseLineMonitor.setMonitorStatus(0L);
            baseLineMonitor.setIsAmmeter("false");
            lineMonitorList.add(baseLineMonitor);
        }

        List<BaseLineLoss> baseLineLosses = baseLineLossMapper.selectBaseLineLossList(new BaseLineLoss());
        if (lineMonitorList.size() == 0){
            return;
        }else if (baseLineLosses.size() == 0){
            flag = false;
        }
        for (BaseLineMonitor lineMonitor : lineMonitorList) {
            boolean isHaveMonitor = true;
            if (flag){
                for (BaseLineLoss baseLineLoss : baseLineLosses) {
                    if (baseLineLoss.getMonitorId().equals(lineMonitor.getMonitorId())){
                        isHaveMonitor  = false;
                        break;
                    }
                }
            }
            if (isHaveMonitor && lineMonitor.getIsAmmeter().equals("false")){
                BaseLineLoss baseLineLoss = new BaseLineLoss();
                baseLineLoss.setMonitorId(lineMonitor.getMonitorId());
                baseLineLoss.setMonitorName(lineMonitor.getMonitorName());
                baseLineLoss.setLineLossId(lineMonitor.getMonitorId());
                baseLineLoss.setLineLossName(lineMonitor.getMonitorName());
                baseLineLoss.setMonitorType(lineMonitor.getMonitorType());
                baseLineLoss.setLineLossStatus(lineMonitor.getMonitorStatus());
                baseLineLoss.setCreateBy(SecurityUtils.getUsername());
                baseLineLoss.setCreateTime(new Date());
                baseLineLossMapper.insertBaseLineLoss(baseLineLoss);
            }
        }
    }


    /**
     * 递归查找所有下级子节点中真表
     * isAmmeter为false的节点
     *
     * @param monitors
     * @param monitorId
     * @return
     */
    public static List<BaseLineMonitor> getNextLevelLineMonitorList(List<BaseLineMonitor> monitors, String monitorId) {
        List<BaseLineMonitor> result = new ArrayList<>();
        BaseLineMonitor current = null;
        for (BaseLineMonitor monitor : monitors) {
            if (monitor.getMonitorId().equals(monitorId)) {
                current = monitor;
                break;
            }
        }
        if (current == null) {
            return result;
        }
        for (BaseLineMonitor child : monitors) {
            if (child.getParentId().equals(current.getObjid())) {
                if (child.getIsAmmeter().equals("false")) {
                    result.add(child);
                } else {
                    List<BaseLineMonitor> subResult = getNextLevelLineMonitorList(monitors, child.getMonitorId());
                    result.addAll(subResult);
                }
            }
        }
        return result;
    }

    /**
     * 递归查找monitorId最下级节点中的表
     * @param monitors
     * @param monitorId
     * @return
     */
    public static List<BaseLineMonitor> getLowestLevelLineMonitorList(List<BaseLineMonitor> monitors, String monitorId) {
        List<BaseLineMonitor> result = new ArrayList<>();
        HashSet<Long> parentIdSet = new HashSet<>();
        BaseLineMonitor current = null;
        for (BaseLineMonitor monitor : monitors) {
            if (monitor.getMonitorId().equals(monitorId)) {
                current = monitor;
            }
            parentIdSet.add(monitor.getParentId());
        }
        if (current == null) {
            return result;
        }
        for (BaseLineMonitor child : monitors) {
            if (child.getParentId().equals(current.getObjid())) {
                if (parentIdSet.contains(child.getObjid())) {
                    List<BaseLineMonitor> subResult = getLowestLevelLineMonitorList(monitors, child.getMonitorId());
                    result.addAll(subResult);
                }else {
                    result.add(child);
                }
            }
        }
        return result;
    }

}

