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

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import com.hw.common.core.constant.Constants;
import com.hw.common.core.constant.SecurityConstants;
import com.hw.common.core.constant.TdEngineConstants;
import com.hw.common.core.domain.R;
import com.hw.common.core.exception.ServiceException;
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.mapper.*;
import com.hw.ems.base.service.IBaseMonitorInfo1Service;
import com.hw.tdengine.api.RemoteTdEngineService;
import com.hw.tdengine.api.domain.TdField;
import com.hw.tdengine.api.domain.TdTableVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.hw.tdengine.api.domain.AlterTagVo;


/**
 * 计量设备信息Service业务层处理
 *
 * @author sf
 * @date 2023-05-05
 */
@Service
public class BaseMonitorInfo1ServiceImpl implements IBaseMonitorInfo1Service {
    @Autowired
    private BaseMonitorInfo1Mapper baseMonitorInfoMapper;

    @Autowired
    private BaseTypeRelationMapper baseTypeRelationMapper;

    @Autowired
    private BaseBusinessTypeMapper baseBusinessTypeMapper;

    @Autowired
    private BaseSubentryTypeMapper baseSubentryTypeMapper;

    @Autowired
    private BaseLineLossMapper baseLineLossMapper;

    @Autowired
    private BaseBuildInfoMapper baseBuildInfoMapper;

    @Autowired
    private RemoteTdEngineService remoteTdEngineService;

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

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

    /**
     * 新增计量设备信息
     *
     * @param baseMonitorInfo 计量设备信息
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    //@DS("#header.poolName")
    public int insertBaseMonitorInfo(BaseMonitorInfo baseMonitorInfo) {
        List<BaseMonitorInfo> baseMonitorInfos = baseMonitorInfoMapper.checkMonitorIdLegal(baseMonitorInfo);
        if (baseMonitorInfos.size() != 0) {
            throw new ServiceException("计量设备编号重复:" + baseMonitorInfo.getMonitorId());
        }
        //todo 新增父级为空判断，父级为空时会导致创建子表与创建计量设备与类型的对应对象失效
        try {
            BaseMonitorInfo monitor = baseMonitorInfoMapper.selectBaseMonitorInfoByObjid(baseMonitorInfo.getParentId());

            if (monitor != null) {
                monitor.setAncestors(monitor.getAncestors() + "," + monitor.getMonitorId());
                String[] split = monitor.getAncestors().split(",");
                monitor.setGrade(split.length);
            }
            this.insertOrUpdateBaseTypeRelation(baseMonitorInfo.getMonitorId(), baseMonitorInfo.getBuildId(),
                    baseMonitorInfo.getBusinessId(), baseMonitorInfo.getSubentryId());
            List<BaseMonitorInfo> subsetList = this.selectMonitorSubsetList(new BaseMonitorInfo());
//            添加线损对象
            this.insertLineLossList(subsetList);

            baseMonitorInfo.setCreateTime(DateUtils.getNowDate());
            baseMonitorInfo.setCreateBy(SecurityUtils.getUsername());
            int result = baseMonitorInfoMapper.insertBaseMonitorInfo(baseMonitorInfo);

            //创建TDEngine子表
            this.createEmsTbale(baseMonitorInfo.getMonitorId(), baseMonitorInfo.getBuildId(), baseMonitorInfo.getMonitorName(), baseMonitorInfo.getObjid());


            return result;
        } catch (Exception e) {
            System.out.println("新增计量设备信息异常1111:" + e.getMessage());
        }
        return 0;


    }

    /**
     * 创建能源子表
     */
    public void createEmsTbale(String monitorId, String buildid, String monitorName, Long objid) {
        //调用tde创建一个子表
        TdTableVo tableVo = new TdTableVo();
        tableVo.setDatabaseName("db_hwmes");
        tableVo.setSuperTableName("st_electricity");
        tableVo.setTableName(TdEngineConstants.getEmsTableName(objid));
        List<TdField> fields = new ArrayList<TdField>();
        TdField field = new TdField();
        TdField field2 = new TdField();
        TdField field3 = new TdField();
        TdField field4 = new TdField();
        field.setFieldName(TdEngineConstants.ST_TAG_EMS_BUILDID);
        field.setFieldValue(buildid);
        field2.setFieldName(TdEngineConstants.ST_TAG_EMS_MONITORNAME);
        field2.setFieldValue(monitorName);
        field3.setFieldName(TdEngineConstants.ST_TAG_EMS_MONITOROBJID);
        field3.setFieldValue(objid);
        field4.setFieldName(TdEngineConstants.ST_TAG_EMS_MONITORID);
        field4.setFieldValue(monitorId);
        fields.add(field);
        fields.add(field2);
        fields.add(field3);
        fields.add(field4);
        tableVo.setTagsFieldValues(fields);
        R<?> tdReturnMsg = remoteTdEngineService.createTable(tableVo, SecurityConstants.INNER);
        if (tdReturnMsg.getCode() != Constants.SUCCESS) {//抛出异常，回滚事务
            throw new RuntimeException(tdReturnMsg.getMsg());
        }
    }

    /**
     * 新增线损对象信息
     *
     * @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);
            }
        }
    }

    /**
     * 修改计量设备信息
     *
     * @param baseMonitorInfo 计量设备信息
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    //@DS("#header.poolName")
    public int updateBaseMonitorInfo(BaseMonitorInfo baseMonitorInfo) {
        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());
            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());
            baseMonitorInfo.setUpdateTime(DateUtils.getNowDate());
            baseMonitorInfo.setUpdateBy(SecurityUtils.getUsername());
            int result = baseMonitorInfoMapper.updateBaseMonitorInfo(baseMonitorInfo);
            this.updateTdEngineTable(baseMonitorInfo, oldDeptMonitorInfo);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 修改子元素关系
     *
     * @param monitorId    被修改的ID
     * @param newAncestors 新的父ID集合
     * @param oldAncestors 旧的父ID集合
     */
    private void updateMonitorChildren(String monitorId, String newAncestors, String oldAncestors) {
        List<BaseMonitorInfo> children = baseMonitorInfoMapper.selectChildrenMonitorById(monitorId);
        for (BaseMonitorInfo child : children) {
            child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
        }
        if (children.size() > 0) {
            baseMonitorInfoMapper.updateMonitorChildren(children);
        }

    }


    /**
     * @param: baseMonitorInfo 前端传的对象
     * @param: dbBaseMonitorInfo 目前数据库的对象
     * @description 更新TdEngine数据库tag
     * @author xins
     * @date 2023-12-30 16:50
     */
    private void updateTdEngineTable(BaseMonitorInfo baseMonitorInfo, BaseMonitorInfo dbBaseMonitorInfo) {
        String databaseName = TdEngineConstants.EMS_DATABASE_NAME;
        String tableName = TdEngineConstants.getEmsTableName(baseMonitorInfo.getObjid());
        List<AlterTagVo> alterTagVos = new ArrayList<AlterTagVo>();

        R<?> tdReturnMsg;
        if (!baseMonitorInfo.getMonitorId().equals(dbBaseMonitorInfo.getMonitorId())) {
            AlterTagVo alterTagVo = new AlterTagVo();
            alterTagVo.setDatabaseName(databaseName);
            alterTagVo.setTableName(tableName);
            alterTagVo.setTagName(TdEngineConstants.ST_TAG_EMS_MONITORID);
            alterTagVo.setTagValue("'" + baseMonitorInfo.getMonitorId() + "'");
            alterTagVos.add(alterTagVo);
        }
        if (!baseMonitorInfo.getMonitorName().equals(dbBaseMonitorInfo.getMonitorName())) {
            AlterTagVo alterTagVo = new AlterTagVo();
            alterTagVo.setDatabaseName(databaseName);
            alterTagVo.setTableName(tableName);
            alterTagVo.setTagName(TdEngineConstants.ST_TAG_EMS_MONITORNAME);
            alterTagVo.setTagValue("'" + baseMonitorInfo.getMonitorName() + "'");
            alterTagVos.add(alterTagVo);
        }

        if (!baseMonitorInfo.getBuildId().equals(dbBaseMonitorInfo.getBuildId())) {
            AlterTagVo alterTagVo = new AlterTagVo();
            alterTagVo.setDatabaseName(databaseName);
            alterTagVo.setTableName(tableName);
            alterTagVo.setTagName(TdEngineConstants.ST_TAG_EMS_BUILDID);
            alterTagVo.setTagValue("'" + baseMonitorInfo.getBuildId() + "'");
            alterTagVos.add(alterTagVo);
        }

        if (!alterTagVos.isEmpty()) {
            tdReturnMsg = this.remoteTdEngineService.alterTableTags(alterTagVos, SecurityConstants.INNER);
            if (tdReturnMsg.getCode() != Constants.SUCCESS) {//抛出异常，回滚事务
                throw new RuntimeException(tdReturnMsg.getMsg());
            }
        }

    }


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

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

    /**
     * 新增或更新计量与类型对应关系
     *
     * @param buildId
     * @param businessId
     * @param subentryId
     */
    private void insertOrUpdateBaseTypeRelation(String monitorId, String buildId, String businessId, String subentryId) {
        BaseTypeRelation typeRelation = new BaseTypeRelation();
        typeRelation.setMonitorId(monitorId);
        List<BaseTypeRelation> baseTypeRelations = baseTypeRelationMapper.selectBaseTypeRelationList(typeRelation);
        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);
            }
        }
    }

    /**
     * 查询计量设备有子集的父级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;
    }

    /**
     * 查询类型园区下第一级
     *
     * @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;
    }


}
