package com.njcn.device.pms.service.majornetwork.impl;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.common.pojo.dto.SimpleDTO;
import com.njcn.common.pojo.enums.common.DataStateEnum;

import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.exception.BusinessException;

import com.njcn.device.biz.enums.DeviceResponseEnum;

import com.njcn.device.biz.pojo.dto.DeptGetChildrenDTO;
import com.njcn.device.biz.pojo.param.DeptGetLineParam;
import com.njcn.device.biz.pojo.po.DeviceBak;
import com.njcn.device.biz.utils.COverlimit;
import com.njcn.device.biz.utils.COverlimitUtil;
import com.njcn.device.pms.enums.PmsDeviceResponseEnum;
import com.njcn.device.pms.mapper.majornetwork.*;
import com.njcn.device.pms.pojo.dto.PmsMonitorBaseDTO;
import com.njcn.device.pms.pojo.dto.PmsMonitorDTO;
import com.njcn.device.pms.pojo.dto.PmsMonitorInfoDTO;
import com.njcn.device.pms.pojo.param.*;
import com.njcn.device.pms.pojo.po.*;
import com.njcn.device.pms.pojo.vo.MonitorVO;
import com.njcn.device.pms.pojo.vo.PmsMonitorVO;
import com.njcn.device.pms.service.majornetwork.IDistributionMonitorService;
import com.njcn.device.pms.service.majornetwork.IMonitorService;
import com.njcn.device.pms.service.majornetwork.IPowerDistributionareaService;

import com.njcn.device.pq.pojo.bo.excel.OracleTerminalExcel;

import com.njcn.device.pq.pojo.po.LineBak;
import com.njcn.poi.excel.ExcelUtil;
import com.njcn.poi.util.PoiUtil;
import com.njcn.system.enums.DicDataEnum;
import com.njcn.system.enums.DicDataTypeEnum;
import com.njcn.user.api.DeptFeignClient;
import com.njcn.device.biz.pojo.po.Overlimit;
import com.njcn.system.api.DicDataFeignClient;
import com.njcn.system.enums.SystemResponseEnum;
import com.njcn.system.pojo.po.DictData;
import com.njcn.user.pojo.dto.DeptDTO;
import com.njcn.user.pojo.po.Dept;
import com.njcn.web.factory.PageFactory;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author cdf
 * @since 2022-10-14
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class MonitorServiceImpl extends ServiceImpl<MonitorMapper, Monitor> implements IMonitorService {

    private final MonitorMapper monitorMapper;

    private final OverlimitMapper overlimitMapper;

    private final DicDataFeignClient dicDataFeignClient;

    private final DeptFeignClient deptFeignClient;

    private final PmsGeneratrixWireMapper generatrixWireMapper;

    private final SpecialMonitorMapper specialMonitorMapper;

    private final IDistributionMonitorService iDistributionMonitorService;

    private final StatationStatMapper statationStatMapper;

    private final TerminalMapper terminalMapper;

    private final LineBakMapper lineBakMapper;

    private final DeviceBakMapper deviceBakMapper;


    @Override
    public List<PmsMonitorBaseDTO> getMonitorByCondition(List<String> deptIdList, PmsDeviceInfoParam pmsDeviceInfoParam) {
        return this.baseMapper.getMonitorByCondition(deptIdList, pmsDeviceInfoParam);
    }

    /**
     * 获取指定的监测点信息
     *
     * @param pmsMonitorInfoParam 获取监测点详情数据入参
     * @return 指定的监测点信息
     */
    @Override
    public List<PmsMonitorInfoDTO> getMonitorInfo(PmsMonitorInfoParam pmsMonitorInfoParam) {
        return monitorMapper.getMonitorInfo(pmsMonitorInfoParam);
    }

    /***
     * 根据条件获取监测点列表（包含监测点所有信息）
     * @author jianghaifei
     * @date 2022-10-20 20:29
     * @param pmsMonitorParam
     * @return java.util.List<com.njcn.device.pms.pojo.dto.PmsMonitorDTO>
     */
    @Override
    public List<PmsMonitorDTO> getMonitorInfoListByCond(PmsMonitorParam pmsMonitorParam) {
        LambdaQueryWrapper<Monitor> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //组装条件：org_id in (orgIds) and id in (monitorIds) and name like "%monitorName%"
        //            and voltage_Level in (voltageLevels)
        lambdaQueryWrapper.in(CollUtil.isNotEmpty(pmsMonitorParam.getOrgIds()), Monitor::getOrgId, pmsMonitorParam.getOrgIds())
                .in(CollUtil.isNotEmpty(pmsMonitorParam.getMonitorIds()), Monitor::getId, pmsMonitorParam.getMonitorIds())
                .like(StringUtils.isNotBlank(pmsMonitorParam.getMonitorName()), Monitor::getName, pmsMonitorParam.getMonitorName())
                .in(CollUtil.isNotEmpty(pmsMonitorParam.getVoltageLevels()), Monitor::getVoltageLevel, pmsMonitorParam.getVoltageLevels())
                .in(CollUtil.isNotEmpty(pmsMonitorParam.getPowerrIds()), Monitor::getPowerrId, pmsMonitorParam.getPowerrIds())
                .like(StringUtils.isNotBlank(pmsMonitorParam.getPowerrName()), Monitor::getPowerrName, pmsMonitorParam.getPowerrName())
                .eq(Objects.nonNull(pmsMonitorParam.getIsSpecialMonitor()), Monitor::getIsSpecialMonitor, pmsMonitorParam.getIsSpecialMonitor())
                .eq(StringUtils.isNotBlank(pmsMonitorParam.getMonitorType()), Monitor::getMonitorType, pmsMonitorParam.getMonitorType())

                .in(CollUtil.isNotEmpty(pmsMonitorParam.getMonitorTags()), Monitor::getMonitorTag, pmsMonitorParam.getMonitorTags())

                .eq(StringUtils.isNotBlank(pmsMonitorParam.getMonitorState()), Monitor::getMonitorState, pmsMonitorParam.getMonitorState())
                .eq(StringUtils.isNotBlank(pmsMonitorParam.getMonitorTag()), Monitor::getMonitorTag, pmsMonitorParam.getMonitorTag());

        List<Monitor> list = this.list(lambdaQueryWrapper);
        List<PmsMonitorDTO> dtoList = list.stream().map(item -> {
            PmsMonitorDTO dto = new PmsMonitorDTO();
            BeanUtils.copyProperties(item, dto);
            return dto;
        }).collect(Collectors.toList());
        return dtoList;
    }

    /***
     * 获取所有监测点信息
     * @author jianghaifei
     * @date 2022-10-24 20:01
     * @param
     * @return java.util.List<com.njcn.device.pms.pojo.vo.PmsMonitorVO>
     */
    @Override
    public List<PmsMonitorVO> getAllMonitorList() {
        List<Monitor> monitorList = this.list();
        List<PmsMonitorVO> resultList = monitorList.stream().map(item -> {
            PmsMonitorVO pmsMonitorVO = new PmsMonitorVO();
            BeanUtils.copyProperties(item, pmsMonitorVO);
            return pmsMonitorVO;
        }).collect(Collectors.toList());
        return resultList;
    }

    @Override
    public Overlimit getOverLimitData(String id) {
        return overlimitMapper.selectById(id);
    }

    @Override
    public Page<Monitor> getAllMonitorPageList(TerminalQueryParam baseParam) {
        LambdaQueryWrapper<Monitor> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper
                .eq(StrUtil.isNotBlank(baseParam.getMonitorState()), Monitor::getMonitorState, baseParam.getMonitorState())
                .eq(StrUtil.isNotBlank(baseParam.getMonitorTag()), Monitor::getMonitorTag, baseParam.getMonitorTag())
                .and(StrUtil.isNotBlank(baseParam.getSearchValue()), i -> i.like(Monitor::getName, baseParam.getSearchValue())
                        .or()
                        .like(Monitor::getId, baseParam.getSearchValue())
                        .or()
                        .like(Monitor::getPowerrName, baseParam.getSearchValue())
                        .or()
                        .like(Monitor::getOrgName, baseParam.getSearchValue()))
                .eq(Monitor::getStatus, DataStateEnum.ENABLE.getCode())
                .orderByDesc(Monitor::getCreateTime);
        Page<Monitor> page = this.page(new Page<>(PageFactory.getPageNum(baseParam), PageFactory.getPageSize(baseParam)), lambdaQueryWrapper);

        List<DictData> dictDataList = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.DEV_VOLTAGE.getCode()).getData();
        Map<String, DictData> map = dictDataList.stream().collect(Collectors.toMap(DictData::getId, Function.identity()));
        List<Monitor> tem = page.getRecords().stream().peek(item -> item.setStandShortCapacity(COverlimit.getStandShortCap(map.get(item.getVoltageLevel()).getValue()))).collect(Collectors.toList());
        page.setRecords(tem);
        return page;
    }

    @Override
    public List<Monitor> getMonitorList(List<String> monitorIds) {
        List<Monitor> monitorList = new ArrayList<>();
        LambdaQueryWrapper<Monitor> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Monitor::getStatus, DataStateEnum.ENABLE.getCode());
        if (CollUtil.isEmpty(monitorIds)) {
            //为空查询所有监测点
            monitorList = this.list(lambdaQueryWrapper);
        } else {
            lambdaQueryWrapper.in(Monitor::getId, monitorIds);
            monitorList = this.list(lambdaQueryWrapper);
        }
        return monitorList;
    }

    @Override
    public List<Monitor> getMonitorListByParam(MonitorParam monitorParam) {
        LambdaQueryWrapper<Monitor> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        //根据部门
        if (StrUtil.isNotBlank(monitorParam.getOrgId())) {
            List<String> deptIds = deptFeignClient.getDepSonSelfCodetByDeptId(monitorParam.getOrgId()).getData();
            lambdaQueryWrapper.in(Monitor::getOrgId, deptIds).eq(Monitor::getStatus, DataStateEnum.ENABLE.getCode());
        }
        return this.list(lambdaQueryWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean addMonitor(MonitorParam monitorParam) {
        checkParam(monitorParam, false);
        Monitor monitor = new Monitor();
        BeanUtils.copyProperties(monitorParam, monitor);
        checkOther(monitorParam, monitor, false);
        monitor.setStatus(DataStateEnum.ENABLE.getCode());

        //主网测点限值计算
        Overlimit overlimit = overLimitCal(monitorParam, monitor);
        this.save(monitor);

        //新增监测点同时新增pms_special_monitor
        SpecialMonitor specialMonitor = new SpecialMonitor();
        specialMonitor.setId(monitor.getId());
        specialMonitor.setCapacity(100f);
        specialMonitor.setType(1);
        specialMonitorMapper.insert(specialMonitor);

        overlimit.setId(monitor.getId());
        overlimitMapper.deleteById(monitor.getId());
        overlimitMapper.insert(overlimit);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateMonitor(MonitorParam monitorParam) {
        checkParam(monitorParam, true);
        Monitor monitor = new Monitor();
        BeanUtils.copyProperties(monitorParam, monitor);
        checkOther(monitorParam, monitor, true);

        this.updateById(monitor);

        //修改监测点同时修改pms_special_monitor
        SpecialMonitor specialMonitor = new SpecialMonitor();
        specialMonitor.setId(monitor.getId());
        specialMonitor.setCapacity(100f);
        specialMonitor.setType(1);
        specialMonitorMapper.updateById(specialMonitor);

        //修改主网监测点如何配网表中也存在需要同时修改
        DistributionMonitor distributionMonitor = iDistributionMonitorService.getById(monitor.getId());
        if (Objects.nonNull(distributionMonitor)) {
            distributionMonitor.setTerminalId(monitor.getTerminalId());
            distributionMonitor.setTerminalWiringMethod(monitor.getTerminalWiringMethod());
            distributionMonitor.setVoltageLevel(monitor.getVoltageLevel());
            distributionMonitor.setMonitorState(monitor.getMonitorState());
            iDistributionMonitorService.updateById(distributionMonitor);
        }

        Overlimit overlimit = overLimitCal(monitorParam, monitor);
        overlimitMapper.deleteById(monitor.getId());
        overlimit.setId(monitor.getId());
        overlimitMapper.insert(overlimit);
        return true;

    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public boolean delMonitor(List<String> monitorIds) {
        //需要先判断配网表中是否存在此监测点
        iDistributionMonitorService.removeByIds(monitorIds);
        this.removeByIds(monitorIds);
        specialMonitorMapper.deleteBatchIds(monitorIds);
        overlimitMapper.deleteBatchIds(monitorIds);

        lineBakMapper.deleteBatchIds(monitorIds);
        return true;
    }

    @Override
    public boolean retirementMonitor(Integer type, List<String> lineIds) {
        List<DictData> dictDataList = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.LINE_STATE.getCode()).getData();
        Map<String, DictData> map = dictDataList.stream().collect(Collectors.toMap(DictData::getCode, Function.identity()));
        DictData dictData = map.get(DicDataEnum.RETIREMENT.getCode());
        if (type == 0) {
            //主网
            LambdaUpdateWrapper<Monitor> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            lambdaUpdateWrapper.in(Monitor::getId, lineIds).eq(Monitor::getStatus, DataStateEnum.ENABLE.getCode());
            //退役
            lambdaUpdateWrapper.set(Monitor::getMonitorState, dictData.getId());
            this.update(lambdaUpdateWrapper);
        } else if (type == 1) {
            //配网
            LambdaUpdateWrapper<DistributionMonitor> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
            lambdaUpdateWrapper.in(DistributionMonitor::getMonitorId, lineIds).eq(DistributionMonitor::getStatus, DataStateEnum.ENABLE.getCode());
            //退役
            lambdaUpdateWrapper.set(DistributionMonitor::getMonitorState, dictData.getId());
            iDistributionMonitorService.update(lambdaUpdateWrapper);
        }
        return true;
    }

    @Override
    public List<SimpleDTO> getPmsPowerrInfoWithInOrg(List<String> orgIdList, PmsDeviceInfoParam pmsDeviceInfoParam) {
        return this.baseMapper.getPmsPowerrInfoWithInOrg(orgIdList, pmsDeviceInfoParam);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateStatus(MonitorStatus monitorParam) {
        LambdaUpdateWrapper<Monitor> update = new LambdaUpdateWrapper<>();
        update.set(Monitor::getStatus, monitorParam.getStatus())
                .in(Monitor::getId, monitorParam.getId());
        return this.update(update);
    }

    @Override
    public MonitorVO monitorTerminal(MonitorTerminalParam param) {
        //type 0:主网 1:配网
        MonitorVO monitorTerminal;
        if (param.getType() == 0) {
            monitorTerminal = this.baseMapper.getMonitorTerminal(param.getId());
        } else {
            monitorTerminal = this.baseMapper.getPwMonitorTerminal(param.getId());
        }
        String terminalWiringMethod = monitorTerminal.getTerminalWiringMethod();
        DictData data = dicDataFeignClient.getDicDataById(terminalWiringMethod).getData();
        if (DicDataEnum.STAR.getCode().equals(data.getCode())) {
            monitorTerminal.setTerminalWiringMethod("0");
        }
        if (DicDataEnum.STAR_TRIANGLE.getCode().equals(data.getCode())) {
            monitorTerminal.setTerminalWiringMethod("1");
        }
        if (DicDataEnum.OPEN_DELTA.getCode().equals(data.getCode())) {
            monitorTerminal.setTerminalWiringMethod("2");
        } else {
            monitorTerminal.setTerminalWiringMethod("-1");
        }
        return monitorTerminal;
    }

    @Override
    public List<DeptGetChildrenDTO> deptMonitor(DeptGetLineParam param) {
        //返回主网和配网监测信息
        List<DeptGetChildrenDTO> deviceInfos = new ArrayList<>();
        List<DeptDTO> deptInfos = deptFeignClient.getDeptDescendantIndexes(param.getDeptId(), Stream.of(0, 1).collect(Collectors.toList())).getData();
        List<DeptDTO> directDeptInfos = deptInfos.stream()
                .filter(deptDTO -> deptDTO.getPid().equals(param.getDeptId()))
                .collect(Collectors.toList());
        if (CollUtil.isEmpty(directDeptInfos)) {
            //没有直接子部门，获取当前部门所有信息
            List<DeptDTO> dept = deptInfos.stream()
                    .filter(deptDTO -> deptDTO.getId().equals(param.getDeptId()))
                    .collect(Collectors.toList());
            deviceInfos.add(getPmsMonitor(dept.get(0), Collections.singletonList(dept.get(0).getCode())));
        } else {
            for (DeptDTO deptDTO : directDeptInfos) {
                //筛选上级部门pids包含该id的所有部门
                List<DeptDTO> descendantDeptDTO = deptInfos.stream()
                        .filter(d -> d.getPids().contains(deptDTO.getId()))
                        .collect(Collectors.toList());
                //形成需要查询监测点的部门索引
                List<String> deptIdList = descendantDeptDTO.stream()
                        .map(DeptDTO::getCode)
                        .distinct()
                        .collect(Collectors.toList());
                deptIdList.add(deptDTO.getCode());
                deviceInfos.add(getPmsMonitor(deptDTO, deptIdList));
            }
        }
        return deviceInfos;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String importOracleLedgerToMysql(MultipartFile file, HttpServletResponse response) {
        ImportParams importParams = new ImportParams();
        importParams.setHeadRows(1);
        importParams.setTitleRows(1);
        importParams.setNeedVerify(true);

        try {
            ExcelImportResult<OracleTerminalExcel> terminalExcelExcelImportResult = ExcelImportUtil.importExcelMore(file.getInputStream(), OracleTerminalExcel.class, importParams);

            //如果存在非法数据，将不合格的数据导出
            if (terminalExcelExcelImportResult.isVerifyFail()) {
                PoiUtil.exportFileByWorkbook(terminalExcelExcelImportResult.getFailWorkbook(), "非法台账信息.xlsx", response);
                return null;
            } else {
                //执行台账信息导入（不考虑，存在监测点却不存在限值信息）
                return dealData(terminalExcelExcelImportResult.getList());
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(DeviceResponseEnum.IMPORT_ORACLE_EXCEPTION);
        }

    }


    /**
     * 获取主配网监测点id集合
     *
     * @param deptDTO
     * @param deptIdList
     * @return
     */
    private DeptGetChildrenDTO getPmsMonitor(DeptDTO deptDTO, List<String> deptIdList) {
        DeptGetChildrenDTO pmsDeptGetChildrenDTO = new DeptGetChildrenDTO();
        pmsDeptGetChildrenDTO.setDeptId(deptDTO.getCode());
        if (deptDTO.getType() == 0) {
            pmsDeptGetChildrenDTO.setDeptName(deptDTO.getArea());
        } else {
            pmsDeptGetChildrenDTO.setDeptName(deptDTO.getName());
        }
        pmsDeptGetChildrenDTO.setDeptChildren(deptIdList);
        if (CollUtil.isNotEmpty(deptIdList)) {
            //主网监测点
            List<Monitor> monitorList = this.list(new LambdaQueryWrapper<Monitor>().in(CollUtil.isNotEmpty(deptIdList), Monitor::getOrgId, deptIdList));
            //配网监测点
            List<PmsMonitorBaseDTO> pwMonitorList = iDistributionMonitorService.getMonitorByCondition(deptIdList, null);

            pmsDeptGetChildrenDTO.setLineIds(monitorList.stream().map(Monitor::getId).distinct().collect(Collectors.toList()));
            pmsDeptGetChildrenDTO.setPwMonitorIds(pwMonitorList.stream().map(PmsMonitorBaseDTO::getMonitorId).distinct().collect(Collectors.toList()));
        } else {
            pmsDeptGetChildrenDTO.setLineIds(new ArrayList<>());
            pmsDeptGetChildrenDTO.setPwMonitorIds(new ArrayList<>());
        }
        return pmsDeptGetChildrenDTO;
    }

    private void checkParam(MonitorParam monitorParam, boolean update) {

        //校验同一单位下面不能有同名1类监测点
        LambdaQueryWrapper<Monitor> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Monitor::getName, monitorParam.getName())
                .eq(Monitor::getPowerrId, monitorParam.getPowerrId())
                .eq(Monitor::getStatus, DataStateEnum.ENABLE.getCode());

        if (update) {
            lambdaQueryWrapper.ne(Monitor::getId, monitorParam.getId());
        }

        int count = this.count(lambdaQueryWrapper);
        if (count > 0) {
            throw new BusinessException(PmsDeviceResponseEnum.DEPT_MONITOR_REPEAT);
        }

        //校验电压等级数据
        DictData voltageDic = dicDataFeignClient.getDicDataById(monitorParam.getVoltageLevel()).getData();
        if (Objects.isNull(voltageDic)) {
            throw new BusinessException(SystemResponseEnum.VOLTAGE_EMPTY);
        }

        //校验监测点状态
        DictData stateDic = dicDataFeignClient.getDicDataById(monitorParam.getMonitorState()).getData();
        if (Objects.isNull(stateDic)) {
            throw new BusinessException(SystemResponseEnum.LINE_STATE_EMPTY);
        }

        //校验监测点类型
        DictData typeDic = dicDataFeignClient.getDicDataById(monitorParam.getMonitorType()).getData();
        if (Objects.isNull(typeDic)) {
            throw new BusinessException(SystemResponseEnum.LINE_TYPE_EMPTY);
        }

        //校验电压互感器
        DictData potentialDic = dicDataFeignClient.getDicDataById(monitorParam.getPotentialTransFormerType()).getData();
        if (Objects.isNull(potentialDic)) {
            throw new BusinessException(SystemResponseEnum.POTENTIAL_TYPE_EMPTY);
        }

        //校验中性点接地方式
        DictData neutralDic = dicDataFeignClient.getDicDataById(monitorParam.getNeutralGroundingMode()).getData();
        if (Objects.isNull(neutralDic)) {
            throw new BusinessException(SystemResponseEnum.Neutral_Mode_EMPTY);
        }

        //校验监测点标签
        DictData tagDic = dicDataFeignClient.getDicDataById(monitorParam.getMonitorTag()).getData();
        if (Objects.isNull(tagDic)) {
            throw new BusinessException(SystemResponseEnum.MONITOR_TAG_EMPTY);
        }


        //校验监测终端接线方式
        DictData wireDic = dicDataFeignClient.getDicDataById(monitorParam.getTerminalWiringMethod()).getData();
        if (Objects.isNull(wireDic)) {
            throw new BusinessException(SystemResponseEnum.TERMINAL_WIRING_EMPTY);
        }
    }

    private void checkOther(MonitorParam monitorParam, Monitor monitor, boolean update) {
        //校验组织机构
        Dept dept = deptFeignClient.getDeptByCode(monitorParam.getOrgId()).getData();
        if (Objects.isNull(dept)) {
            throw new BusinessException(PmsDeviceResponseEnum.ORG_ITEM_EMPTY);
        }

        //校验运维单位
        Dept deptOp = deptFeignClient.getDeptByCode(monitorParam.getOperationId()).getData();
        if (Objects.isNull(deptOp)) {
            throw new BusinessException(PmsDeviceResponseEnum.Operation_ITEM_EMPTY);
        }

        //校验线路
        GeneratrixWire generatrix = generatrixWireMapper.selectById(monitorParam.getLineId());
        if (Objects.isNull(generatrix)) {
            throw new BusinessException(PmsDeviceResponseEnum.VOLTAGE_EMPTY);
        }

    }


    /**
     * 监测点限值计算
     */
    public Overlimit overLimitCal(MonitorParam monitorParam, Monitor monitor) {
        //主网测点限值计算
        DictData dictData = dicDataFeignClient.getDicDataById(monitor.getVoltageLevel()).getData();
        float voltageLevel = Float.parseFloat(dictData.getValue());
        Overlimit overlimit = COverlimitUtil.globalAssemble(voltageLevel, monitor.getUserAgreementCapacity(), monitor.getPowerSupplyEqCapacity(), monitor.getMinShortCircuitCapacity(), 1, 0);
        if (Objects.nonNull(monitorParam.getVoltageDeviationUpperLimit())) {
            monitor.setVoltageDeviationUpperLimit(monitorParam.getVoltageDeviationUpperLimit());
            overlimit.setVoltageDev(monitorParam.getVoltageDeviationUpperLimit());
        } else {
            monitor.setVoltageDeviationUpperLimit(overlimit.getVoltageDev());
        }
        if (Objects.nonNull(monitorParam.getVoltageDeviationLowerLimit())) {
            monitor.setVoltageDeviationLowerLimit(monitorParam.getVoltageDeviationLowerLimit());
            overlimit.setUvoltageDev(monitorParam.getVoltageDeviationLowerLimit());
        } else {
            monitor.setVoltageDeviationLowerLimit(overlimit.getUvoltageDev());
        }
        return overlimit;
    }


    private String dealData(List<OracleTerminalExcel> oracleTerminalExcelList) {
        List<OracleTerminalExcel.OracleTerminalExcelMsg> oracleTerminalExcelMsg = new ArrayList<>();

        List<DeptDTO> allDept = deptFeignClient.getDeptDescendantIndexes(deptFeignClient.getRootDept().getData().getId(), Stream.of(0, 1, 2).collect(Collectors.toList())).getData();
        Map<String, DeptDTO> mapDept = allDept.stream().collect(Collectors.toMap(DeptDTO::getName, Function.identity()));

        List<DictData> voltageLevelDic = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.DEV_VOLTAGE.getCode()).getData();
        Map<String, DictData> voltageLevelMap = voltageLevelDic.stream().collect(Collectors.toMap(DictData::getName, Function.identity()));

        //装置型号
        List<DictData> devTypelDic = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.DEV_TYPE.getCode()).getData();
        Map<String, DictData> devTypelDicMap = devTypelDic.stream().collect(Collectors.toMap(DictData::getName, Function.identity()));

        //装置类别
        DictData devCategoryDic = dicDataFeignClient.getDicDataByNameAndTypeName(DicDataTypeEnum.DEV_CATEGORY.getName(), DicDataEnum.Monitor_Terminals.getName()).getData();

        //装置状态
        List<DictData> devStatelDic = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.DEV_STATUS.getCode()).getData();
        Map<String, DictData> devStateDicMap = devStatelDic.stream().collect(Collectors.toMap(DictData::getName, Function.identity()));

        //监测点状态
        List<DictData> monitorStatelDic = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.LINE_STATE.getCode()).getData();
        Map<String, DictData> monitorStateDicMap = monitorStatelDic.stream().collect(Collectors.toMap(DictData::getName, Function.identity()));

        //检测点对象类型（原监测点标签）
        List<DictData> objTypeList = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.MONITORING_LABELS.getCode()).getData();
        Map<String, DictData> objTypeDicMap = objTypeList.stream().collect(Collectors.toMap(DictData::getName, Function.identity()));

        //装置厂家
        List<DictData> manList = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.DEV_MANUFACTURER.getCode()).getData();
        Map<String, DictData> manDicMap = manList.stream().collect(Collectors.toMap(DictData::getName, Function.identity()));

        //装作等级
        DictData devGrade = dicDataFeignClient.getDicDataByNameAndTypeName(DicDataTypeEnum.DEV_GRADE.getName(), DicDataEnum.MOST_IMPORMENT.getName()).getData();

        //
        DictData devInputType = dicDataFeignClient.getDicDataByNameAndTypeName(DicDataTypeEnum.INPUT_SIGNAL.getName(), DicDataEnum.SIMULATION_SIGNAL.getName()).getData();

        //监测点类型
        DictData monitorType = dicDataFeignClient.getDicDataByNameAndTypeName(DicDataTypeEnum.LINE_TYPE.getName(), DicDataEnum.Power_Supply_Point.getName()).getData();

        //接线方式
        List<DictData> wireList = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.DEV_CONNECT.getCode()).getData();
        Map<String, DictData> wireListMap = wireList.stream().collect(Collectors.toMap(DictData::getName, Function.identity()));

        DictData potentialDic = dicDataFeignClient.getDicDataByNameAndTypeName(DicDataTypeEnum.VOLTAGE_TRANSFORMER.getName(), DicDataEnum.Cap_V.getName()).getData();

        DictData neutralDic = dicDataFeignClient.getDicDataByNameAndTypeName(DicDataTypeEnum.Neutral_Point.getName(), DicDataEnum.Ground_Res.getName()).getData();


        for (OracleTerminalExcel oracleTerminalExcel : oracleTerminalExcelList) {
            //单位
            if (!mapDept.containsKey(oracleTerminalExcel.getGdName())) {
                oracleTerminalExcelMsg.add(assembleMsg(oracleTerminalExcel, "单位名称不存在，请确认单位名称是否正确"));
                continue;
            }

            //判断是否操作过该条记录
            LineBak lineBak = lineBakMapper.selectOne(new LambdaQueryWrapper<LineBak>().eq(LineBak::getLineId,oracleTerminalExcel.getId()));

            DeviceBak deviceBak = deviceBakMapper.selectOne(new LambdaQueryWrapper<DeviceBak>().eq(DeviceBak::getDevId,oracleTerminalExcel.getDeviceId()));


            //单位
            DeptDTO deptDTO = mapDept.get(oracleTerminalExcel.getGdName());

            //电站
            String stationId = null, stationName = null;
            LambdaQueryWrapper<StatationStat> statLambdaQueryWrapper = new LambdaQueryWrapper<>();
            statLambdaQueryWrapper.eq(StatationStat::getPowerName, oracleTerminalExcel.getSubstationName())
                    .eq(StatationStat::getOrgId, deptDTO.getCode());
            StatationStat statationStat = statationStatMapper.selectOne(statLambdaQueryWrapper);

            StatationStat statationStatPO = new StatationStat();
            statationStatPO.setOrgId(deptDTO.getCode());
            statationStatPO.setOrgName(deptDTO.getName());
            statationStatPO.setPowerName(oracleTerminalExcel.getSubstationName());
            statationStatPO.setLongitude(oracleTerminalExcel.getLng().doubleValue());
            statationStatPO.setLatitude(oracleTerminalExcel.getLat().doubleValue());
            statationStatPO.setShouldBeNum(100);
            statationStatPO.setStatus(DataStateEnum.ENABLE.getCode());

            String dicVoltage = dealVoltageLevel(oracleTerminalExcel.getSubStationScale());
            if (voltageLevelMap.containsKey(dicVoltage)) {
                statationStatPO.setVoltageLevel(voltageLevelMap.get(dicVoltage).getId());
            } else {
                oracleTerminalExcelMsg.add(assembleMsg(oracleTerminalExcel, "字典变电站电压等级不存在，请确认电压等级存在"));
                continue;
            }
            if (Objects.isNull(statationStat)) {
                statationStatMapper.insert(statationStatPO);
                stationId = statationStatPO.getPowerId();
                stationName = statationStatPO.getPowerName();
            } else {
                //更新信息
                statationStatPO.setPowerId(statationStat.getPowerId());
                statationStatMapper.updateById(statationStatPO);
                stationId = statationStat.getPowerId();
                stationName = statationStat.getPowerName();
            }

            //装置
            String devId = null;
            LambdaQueryWrapper<PmsTerminal> terminalLambdaQueryWrapper = new LambdaQueryWrapper<>();
            terminalLambdaQueryWrapper.eq(PmsTerminal::getName, oracleTerminalExcel.getDeviceName())
                    .eq(PmsTerminal::getPowerStationId, stationId);
            PmsTerminal pmsTerminal = terminalMapper.selectOne(terminalLambdaQueryWrapper);

            PmsTerminal pmsTerminalPO = new PmsTerminal();
            pmsTerminalPO.setOrgId(deptDTO.getCode());
            pmsTerminalPO.setOrgName(deptDTO.getName());
            pmsTerminalPO.setName(oracleTerminalExcel.getDeviceName());
            pmsTerminalPO.setOperationId(deptDTO.getCode());
            pmsTerminalPO.setOperationName(deptDTO.getName());
            pmsTerminalPO.setPowerrName(stationName);
            pmsTerminalPO.setPowerStationId(stationId);
            pmsTerminalPO.setIp(oracleTerminalExcel.getIp());
            pmsTerminalPO.setUseDate(oracleTerminalExcel.getLoginTime());
            pmsTerminalPO.setVerificationDate(oracleTerminalExcel.getThisTimeCheck());
            pmsTerminalPO.setDeviceCategory(devCategoryDic.getId());

            if (devTypelDicMap.containsKey(oracleTerminalExcel.getDevType())) {
                pmsTerminalPO.setDeviceModel(devTypelDicMap.get(oracleTerminalExcel.getDevType()).getId());
            } else {
                oracleTerminalExcelMsg.add(assembleMsg(oracleTerminalExcel, "字典装置类型不存在，请确认后重试"));
               continue;
            }


          /*  if (devTypelDicMap.containsKey(oracleTerminalExcel.getDevType())) {
                pmsTerminalPO.setTerminalState(devTypelDicMap.get(oracleTerminalExcel.getDevType()).getId());
            } else {
                oracleTerminalExcelMsg.add(assembleMsg(oracleTerminalExcel, "字典终端状态不存在，请确认后重试"));
                continue;
            }*/

            //终端状态
            String devState = null;
            switch (oracleTerminalExcel.getRunFlag()) {
                case 0:
                    devState = DicDataEnum.RUNNING.getName();
                    break;
                case 1:
                    devState = DicDataEnum.NOT_OPERATION.getName();
                    break;
                case 2:
                    devState = DicDataEnum.RETIRE.getName();
                    break;
            }
            if (devStateDicMap.containsKey(devState)) {
                pmsTerminalPO.setTerminalState(devStateDicMap.get(devState).getId());
            } else {
                oracleTerminalExcelMsg.add(assembleMsg(oracleTerminalExcel, "字典装置运行状态不存在，请确认后重试"));
                continue;
            }
            pmsTerminalPO.setTerminalLevel(devGrade.getId());
            pmsTerminalPO.setInputType(devInputType.getId());
            pmsTerminalPO.setStatus(DataStateEnum.ENABLE.getCode());
            pmsTerminalPO.setPort(oracleTerminalExcel.getPort().toString());
            pmsTerminalPO.setIsUpToGrid(0);

            if(manDicMap.containsKey(oracleTerminalExcel.getManufacturer())){
                pmsTerminalPO.setManufacture(manDicMap.get(oracleTerminalExcel.getManufacturer()).getId());
            }else {
                oracleTerminalExcelMsg.add(assembleMsg(oracleTerminalExcel, "字典制造厂商不存在，请确认后重试"));
                continue;
            }
            if (Objects.isNull(pmsTerminal) && Objects.isNull(deviceBak)) {
                terminalMapper.insert(pmsTerminalPO);
                devId = pmsTerminalPO.getId();

                DeviceBak deviceBakPO = new DeviceBak();
                deviceBakPO.setId(devId);
                deviceBakPO.setDevId(oracleTerminalExcel.getDeviceId());
                deviceBakMapper.insert(deviceBakPO);
            } else {
                if(Objects.isNull(deviceBak)) {
                    pmsTerminalPO.setId(pmsTerminal.getId());
                    DeviceBak deviceBakPO = new DeviceBak();
                    deviceBakPO.setId(pmsTerminal.getId());
                    deviceBakPO.setDevId(oracleTerminalExcel.getDeviceId());
                    deviceBakMapper.insert(deviceBakPO);
                    terminalMapper.updateById(pmsTerminalPO);
                    devId = pmsTerminal.getId();
                }else if(Objects.isNull(pmsTerminal)){

                    terminalMapper.deleteById(deviceBak.getId());
                    pmsTerminalPO.setId(deviceBak.getId());
                    terminalMapper.insert(pmsTerminalPO);
                    devId = pmsTerminalPO.getId();
                }else {
                    devId = pmsTerminal.getId();
                }

            }

            //线路
            LambdaQueryWrapper<GeneratrixWire> generatrixWireLambdaQueryWrapper = new LambdaQueryWrapper<>();
            generatrixWireLambdaQueryWrapper.eq(GeneratrixWire::getName, oracleTerminalExcel.getSubvName())
                    .eq(GeneratrixWire::getStationId, stationId);
            GeneratrixWire generatrixWire = generatrixWireMapper.selectOne(generatrixWireLambdaQueryWrapper);

            String lineId = null, lineName = null, genScale = null;


            GeneratrixWire generatrixWirePO = new GeneratrixWire();
            generatrixWirePO.setGeneratrixName(oracleTerminalExcel.getSubvName());
            generatrixWirePO.setStatus(DataStateEnum.ENABLE.getCode());
            generatrixWirePO.setName(oracleTerminalExcel.getSubvName());
            generatrixWirePO.setOrgId(deptDTO.getCode());
            generatrixWirePO.setStationId(stationId);
            generatrixWirePO.setStationName(stationName);

            String dicVoltagePms = dealVoltageLevel(oracleTerminalExcel.getSubvScale());
            if (voltageLevelMap.containsKey(dicVoltagePms)) {
                DictData temVoltage = voltageLevelMap.get(dicVoltagePms);
                generatrixWirePO.setScale(temVoltage.getId());
            }else {
                oracleTerminalExcelMsg.add(assembleMsg(oracleTerminalExcel, "字典母线电压等级不存在，请确认后重试"));
                continue;
            }

            if (Objects.isNull(generatrixWire)) {
                generatrixWireMapper.insert(generatrixWirePO);
                lineId = generatrixWirePO.getId();
                lineName = generatrixWirePO.getName();
                genScale = generatrixWirePO.getScale();
            } else {
                generatrixWirePO.setId(generatrixWire.getId());
                generatrixWireMapper.updateById(generatrixWirePO);
                lineId = generatrixWire.getId();
                lineName = generatrixWirePO.getName();
                genScale = generatrixWirePO.getScale();
            }

            //监测点
            LambdaQueryWrapper<Monitor> monitorLambdaQueryWrapper = new LambdaQueryWrapper<>();
            monitorLambdaQueryWrapper.eq(Monitor::getLineId, lineId)
                    .eq(Monitor::getName, oracleTerminalExcel.getLineName());
            Monitor monitor = monitorMapper.selectOne(monitorLambdaQueryWrapper);


            //当前电站下面没有监测点，可以新增
            Monitor monitorPO = new Monitor();
            monitorPO.setName(oracleTerminalExcel.getLineName());
            monitorPO.setPowerrName(stationName);
            monitorPO.setPowerrId(stationId);
            monitorPO.setOperationName(deptDTO.getName());
            monitorPO.setOperationId(deptDTO.getCode());
            monitorPO.setOrgName(deptDTO.getName());
            monitorPO.setOrgId(deptDTO.getCode());
            monitorPO.setLineName(lineName);
            monitorPO.setLineId(lineId);
            monitorPO.setVoltageLevel(genScale);

            String monitorState = null;
            switch (oracleTerminalExcel.getRunFlag()) {
                case 0:
                    monitorState = DicDataEnum.RUN.getName();
                    break;
                case 1:
                    monitorState = DicDataEnum.DEBUGGING.getName();
                    break;
                case 2:
                    monitorState = DicDataEnum.DECOMMISSIONING.getName();
                    break;
                default:
                    oracleTerminalExcelMsg.add(assembleMsg(oracleTerminalExcel, "字典监测点状态不存在，请确认后重试"));
                    break;

            }
            if (monitorStateDicMap.containsKey(monitorState)) {
                monitorPO.setMonitorState(monitorStateDicMap.get(monitorState).getId());
            } else {
                oracleTerminalExcelMsg.add(assembleMsg(oracleTerminalExcel, "字典监测点运行状态不存在，请确认后重试"));
                continue;
            }

            monitorPO.setMonitorType(monitorType.getId());
            monitorPO.setStandShortCapacity(oracleTerminalExcel.getStandardCapacity());
            monitorPO.setMinShortCircuitCapacity(oracleTerminalExcel.getShortCapacity());
            monitorPO.setUserAgreementCapacity(oracleTerminalExcel.getDealCapacity());
            monitorPO.setPowerSupplyEqCapacity(oracleTerminalExcel.getDevCapacity());
            DictData scale = dicDataFeignClient.getDicDataById(monitorPO.getVoltageLevel()).getData();
            Overlimit overlimitTem = new Overlimit();
            COverlimitUtil.voltageDeviation(overlimitTem, Float.parseFloat(scale.getValue()));
            monitorPO.setVoltageDeviationLowerLimit(overlimitTem.getUvoltageDev());
            monitorPO.setVoltageDeviationUpperLimit(overlimitTem.getVoltageDev());
            monitorPO.setPotentialTransFormerType(potentialDic.getId());
            monitorPO.setNeutralGroundingMode(neutralDic.getId());
            monitorPO.setStatisticalInterval(oracleTerminalExcel.getTimeInterval());
            monitorPO.setTerminalId(devId);
            monitorPO.setIsSpecialSupplyElectricity(0);


            if (objTypeDicMap.containsKey(oracleTerminalExcel.getLoadType())) {
                String objTypeId = objTypeDicMap.get(oracleTerminalExcel.getLoadType()).getId();
                monitorPO.setMonitorTag(objTypeId);
            } else {
                oracleTerminalExcelMsg.add(assembleMsg(oracleTerminalExcel, "字典监测对象类型不存在，请确认后重试"));
                continue;
            }


            String wireMethod = "";
            switch (oracleTerminalExcel.getPtType()) {
                case 0:
                    wireMethod = DicDataEnum.STAR.getName();
                    break;
                case 1:
                    wireMethod = DicDataEnum.STAR_TRIANGLE.getName();
                    break;
                case 2:
                    wireMethod = DicDataEnum.OPEN_DELTA.getName();
                    break;
                default:
                    oracleTerminalExcelMsg.add(assembleMsg(oracleTerminalExcel, "字典接线方式不存在，请确认后重试"));
                    break;
            }
            if (wireListMap.containsKey(wireMethod)) {
                monitorPO.setTerminalWiringMethod(wireListMap.get(wireMethod).getId());
            } else {
                oracleTerminalExcelMsg.add(assembleMsg(oracleTerminalExcel, "字典接线方式不存在，请确认后重试"));
                continue;
            }
            monitorPO.setIsUpToGrid(0);
            monitorPO.setStatus(DataStateEnum.ENABLE.getCode());
            monitorPO.setIsSpecialMonitor(0);
            monitorPO.setPt1(oracleTerminalExcel.getPt1());
            monitorPO.setPt2(oracleTerminalExcel.getPt2());
            monitorPO.setCt1(oracleTerminalExcel.getCt1());
            monitorPO.setCt2(oracleTerminalExcel.getCt2());


            if (Objects.isNull(lineBak) && Objects.isNull(monitor)) {
                monitorMapper.insert(monitorPO);
                Overlimit overlimit = COverlimitUtil.globalAssemble(Float.parseFloat(scale.getValue()), oracleTerminalExcel.getDealCapacity(), oracleTerminalExcel.getDevCapacity(), oracleTerminalExcel.getShortCapacity(), 0, 0);
                overlimit.setId(monitorPO.getId());
                Overlimit overlimitRes = overlimitMapper.selectById(monitorPO.getId());
                if (Objects.isNull(overlimitRes)) {
                    overlimitMapper.insert(overlimit);
                } else {
                    overlimitMapper.updateById(overlimit);
                }

                LineBak lineBakPO = new LineBak();
                lineBakPO.setId(monitorPO.getId());
                lineBakPO.setLineId(oracleTerminalExcel.getId());
                lineBakMapper.insert(lineBakPO);
            }else {
                if(Objects.isNull(lineBak)){
                    LineBak lineBakPO = new LineBak();
                    lineBakPO.setId(monitor.getId());
                    lineBakPO.setLineId(oracleTerminalExcel.getId());
                    lineBakMapper.insert(lineBakPO);
                    monitorMapper.updateById(monitorPO);
                }else if(Objects.isNull(monitor)){
                    monitorMapper.deleteById(lineBak.getId());
                    overlimitMapper.deleteById(lineBak.getId());
                    monitorPO.setId(lineBak.getId());
                    monitorMapper.insert(monitorPO);
                }else{
                    monitorMapper.deleteById(monitor.getId());
                    overlimitMapper.deleteById(monitor.getId());
                    monitorPO.setId(lineBak.getId());
                    monitorMapper.insert(monitorPO);
                }

                Overlimit overlimit = COverlimitUtil.globalAssemble(Float.parseFloat(scale.getValue()), oracleTerminalExcel.getDealCapacity(), oracleTerminalExcel.getDevCapacity(), oracleTerminalExcel.getShortCapacity(), 0, 0);
                overlimit.setId(monitorPO.getId());
                Overlimit overlimitRes = overlimitMapper.selectById(monitorPO.getId());
                if (Objects.isNull(overlimitRes)) {
                    overlimitMapper.insert(overlimit);
                } else {
                    overlimitMapper.updateById(overlimit);
                }

            }


        }

        if (CollectionUtil.isNotEmpty(oracleTerminalExcelMsg)) {
            ExcelUtil.exportExcel("失败列表.xlsx", OracleTerminalExcel.OracleTerminalExcelMsg.class, oracleTerminalExcelMsg);
            return null;
        }
        return CommonResponseEnum.SUCCESS.getMessage();
    }


    private String dealVoltageLevel(String voltage) {
        float scale = Float.parseFloat(voltage.substring(0, voltage.indexOf("kV")));
        if (scale < 500) {
            return "交流" + voltage;
        } else {
            return "直流" + voltage;
        }

    }

    /**
     * 组装不能正常插入的记录，稍后导出给用户
     *
     * @param oracleTerminalExcel 记录信息
     * @param msg                 错误信息
     */
    private OracleTerminalExcel.OracleTerminalExcelMsg assembleMsg(OracleTerminalExcel oracleTerminalExcel, String msg) {
        OracleTerminalExcel.OracleTerminalExcelMsg oracleTerminalExcelMsg = new OracleTerminalExcel.OracleTerminalExcelMsg();
        BeanUtils.copyProperties(oracleTerminalExcel, oracleTerminalExcelMsg);
        oracleTerminalExcelMsg.setMsg(msg);
        return oracleTerminalExcelMsg;
    }

}
