package com.ruoyi.ems.service.impl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.BiFunction;

import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.ruoyi.common.core.enums.FacTypes;
import com.ruoyi.common.core.utils.DateTimeUtil;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.core.utils.ExpressUtil;
import com.ruoyi.common.core.utils.StreamUtils;
import com.ruoyi.ems.domain.EmsFacs;
import com.ruoyi.ems.domain.EmsFacsAbility;
import com.ruoyi.ems.domain.EmsFacsAttr;
import com.ruoyi.ems.domain.EmsFacsEvent;
import com.ruoyi.ems.mapper.AdmEmsElecPgIndexMapper;
import com.ruoyi.ems.mapper.AdmEmsIndexRangeMapper;
import com.ruoyi.ems.mapper.EmsFacsMapper;
import com.ruoyi.ems.service.IAdmEmsIndexRangeService;
import com.ruoyi.ems.service.IEmsFacsAbilityService;
import com.ruoyi.ems.service.IEmsFacsAttrService;
import com.ruoyi.ems.service.IEmsFacsEventService;
import com.ruoyi.ems.service.IEmsFacsService;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;

/**
 * 能源设施/系统Service业务层处理
 *
 * @author ruoyi
 * @date 2024-07-10
 */
@Service
public class EmsFacsServiceImpl implements IEmsFacsService {
    @Autowired
    private EmsFacsMapper emsFacsMapper;

    @Autowired
    private AdmEmsIndexRangeMapper admEmsIndexRangeMapper;

    @Autowired
    private AdmEmsElecPgIndexMapper admEmsElecPgIndexMapper;

    @Autowired
    private IEmsFacsAttrService facsAttrService;

    @Autowired
    private IEmsFacsAbilityService facsAbilityService;

    @Autowired
    private IEmsFacsEventService facsEventService;

    @Autowired
    private IAdmEmsIndexRangeService admEmsIndexRangeService;

    /**
     * 查询能源设施
     *
     * @param id 能源设施主键
     * @return 能源设施
     */
    @Override
    public EmsFacs selectEmsFacsById(Long id) {
        // 查询设施对象
        EmsFacs emsFacs = emsFacsMapper.selectEmsFacsById(id);

        // 查询扩展属性
        if (null != emsFacs) {
            emsFacs.setFacsAttrs(getFacsAttrs(emsFacs));
            emsFacs.setFacsAbilities(getFacsAbilitys(emsFacs));
            emsFacs.setFacsEvents(getFacsEvents(emsFacs));
        }

        return emsFacs;
    }

    @Override
    public EmsFacs selectEmsFacsByCode(String code) {
        // 查询设施对象
        EmsFacs emsFacs = emsFacsMapper.selectEmsFacsByCode(code);

        // 查询扩展属性
        if (null != emsFacs) {
            emsFacs.setFacsAttrs(getFacsAttrs(emsFacs));
            emsFacs.setFacsAbilities(getFacsAbilitys(emsFacs));
            emsFacs.setFacsEvents(getFacsEvents(emsFacs));
        }

        return emsFacs;
    }

    @Override
    public List<EmsFacs> selectFacsByArea(String areaCode) {
        EmsFacs param = new EmsFacs();
        param.setRefArea(areaCode);

        // 查询设施对象
        List<EmsFacs> list = emsFacsMapper.selectEmsFacsList(param);

        // 查询扩展属性
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(facsObj -> {
                facsObj.setFacsAttrs(getFacsAttrs(facsObj));
                facsObj.setFacsAbilities(getFacsAbilitys(facsObj));
                facsObj.setFacsEvents(getFacsEvents(facsObj));
            });
        }

        return list;
    }

    /**
     * 查询能源设施列表
     *
     * @param emsFacs 能源设施
     * @return 能源设施
     */
    @Override
    public List<EmsFacs> selectEmsFacsList(EmsFacs emsFacs) {
        // 查询设施对象
        List<EmsFacs> list = emsFacsMapper.selectEmsFacsList(emsFacs);

        // 查询扩展属性
        if (CollectionUtils.isNotEmpty(list)) {
            list.forEach(facsObj -> {
                facsObj.setFacsAttrs(getFacsAttrs(facsObj));
                facsObj.setFacsAbilities(getFacsAbilitys(facsObj));
                facsObj.setFacsEvents(getFacsEvents(facsObj));
            });
        }

        return list;
    }

    /**
     * 新增能源设施/系统
     *
     * @param emsFacs 能源设施/系统
     * @return 结果
     */
    @Override
    public int insertEmsFacs(EmsFacs emsFacs) {
        emsFacs.setCreateTime(DateUtils.getNowDate());
        return emsFacsMapper.insertEmsFacs(emsFacs);
    }

    /**
     * 修改能源设施/系统
     *
     * @param emsFacs 能源设施/系统
     * @return 结果
     */
    @Override
    public int updateEmsFacs(EmsFacs emsFacs) {
        emsFacs.setUpdateTime(DateUtils.getNowDate());
        return emsFacsMapper.updateEmsFacs(emsFacs);
    }

    /**
     * 批量删除能源设施
     *
     * @param ids 需要删除的能源设施主键
     * @return 结果
     */
    @Override
    public int deleteEmsFacsByIds(Long[] ids) {
        for (Long id : ids) {
            EmsFacs emsFacs = emsFacsMapper.selectEmsFacsById(id);

            // 查询扩展属性
            if (null != emsFacs) {
                facsAttrService.deleteAttrByFacsCode(emsFacs.getFacsCode());
                facsAbilityService.deleteAbilityByFacsCode(emsFacs.getFacsCode());
                facsEventService.deleteEventByFacsCode(emsFacs.getFacsCode());
            }
        }

        return emsFacsMapper.deleteEmsFacsByIds(ids);
    }

    /**
     * 删除能源设施/系统信息
     *
     * @param id 能源设施/系统主键
     * @return 结果
     */
    @Override
    public int deleteEmsFacsById(Long id) {
        EmsFacs emsFacs = emsFacsMapper.selectEmsFacsById(id);

        // 查询扩展属性
        if (null != emsFacs) {
            facsAttrService.deleteAttrByFacsCode(emsFacs.getFacsCode());
            facsAbilityService.deleteAbilityByFacsCode(emsFacs.getFacsCode());
            facsEventService.deleteEventByFacsCode(emsFacs.getFacsCode());
        }

        return emsFacsMapper.deleteEmsFacsById(id);
    }

    @Override
    public List<String> inspectFacIndex() {
        List<Map<String, Object>> admEmsIndexRanges = admEmsIndexRangeMapper.selectAdmEmsIndexRange();
        Map<String, List<Map<String, Object>>> facTypeRangeMap = StreamUtils.groupByKey(admEmsIndexRanges,
            stringObjectMap -> MapUtil.getStr(stringObjectMap, "facsType"));
        List<String> errorReport = Collections.synchronizedList(new ArrayList<String>());
        Map<String, BiFunction<List<String>, Map.Entry<String, List<Map<String, Object>>>, Void>> handlers = new HashMap<String, BiFunction<List<String>, Map.Entry<String, List<Map<String, Object>>>, Void>>() {
            {
                put(FacTypes.TRANSMIT.getCode(), (strings, stringListEntry) -> {
                    pgIndexInspection(errorReport, stringListEntry);
                    return null;
                });
            }
        };
        for (Map.Entry<String, List<Map<String, Object>>> facTypeRange : facTypeRangeMap.entrySet()) {
            String key = facTypeRange.getKey();
            if (!handlers.containsKey(key)) {
                continue;
            }
            handlers.get(key).apply(errorReport, facTypeRange);
        }
        return errorReport;
    }

    @Override
    public Map<String, Map<String, Object>> qryAreaDayPowerIndex(String areaCode) {
        String firstDayOfRecentMonth = DateTimeUtil.getFirstDayOfRecentMonth();
        return admEmsElecPgIndexMapper.qryAreaDayPowerIndex(areaCode, firstDayOfRecentMonth);
    }
    private void pgIndexInspection(List<String> errorReport,
        Map.Entry<String, List<Map<String, Object>>> facTypeRange) {
        Map<String, List<Map<String, Object>>> objCodeRangeMap = StreamUtils.groupByKey(facTypeRange.getValue(),
            stringObjectMap -> MapUtil.getStr(stringObjectMap, "objCode"));
        Set<String> objCodes = objCodeRangeMap.keySet();
        List<List<String>> splitObjCodes = StreamUtils.splitSet(objCodes, 100);
        for (List<String> splitObjCode : splitObjCodes) {
            Map<String, Map<String, Object>> objCodePgIndexes = admEmsElecPgIndexMapper.qryLatestObjIndex(splitObjCode);
            for (Map.Entry<String, Map<String, Object>> objCodePgIndex : objCodePgIndexes.entrySet()) {
                if (!objCodeRangeMap.containsKey(objCodePgIndex.getKey())) {
                    continue;
                }
                Date time = MapUtil.getDate(objCodePgIndex.getValue(), "time");
                long between = DateUtil.between(time, new Date(), DateUnit.DAY);
                List<Map<String, Object>> ranges = objCodeRangeMap.get(objCodePgIndex.getKey());
                String objTypeName = MapUtil.getStr(ranges.get(0), "facsName");
                if (between > 1) {
                    errorReport.add(String.format("%s(%s)已经离线", objCodePgIndex.getKey(), objTypeName));
                    continue;
                }
                List<Map<String, Object>> errors = ExpressUtil.hitExpress(objCodePgIndex.getValue(),
                    objCodeRangeMap.get(objCodePgIndex.getKey()));
                if (CollectionUtils.isEmpty(errors)) {
                    continue;
                }
                for (Map<String, Object> error : errors) {
                    errorReport.add(String.format("%s(%s)超出%s", objCodePgIndex.getKey(), objTypeName,
                        MapUtil.getStr(error, "indexDesc")));
                }
            }
        }
    }


    private List<EmsFacsAttr> getFacsAttrs(EmsFacs emsFacs) {
        EmsFacsAttr param = new EmsFacsAttr(emsFacs.getFacsCode());
        return facsAttrService.selectEmsFacsAttrList(param);
    }

    private List<EmsFacsAbility> getFacsAbilitys(EmsFacs emsFacs) {
        EmsFacsAbility param = new EmsFacsAbility(emsFacs.getFacsCode());
        return facsAbilityService.selectEmsFacsAbilityList(param);
    }

    private List<EmsFacsEvent> getFacsEvents(EmsFacs emsFacs) {
        EmsFacsEvent param = new EmsFacsEvent(emsFacs.getFacsCode());
        return facsEventService.selectEmsFacsEventList(param);
    }
}
