package com.gyee.wisdom.alarm.sharding.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gyee.wisdom.alarm.sharding.entity.AlarmHistory;
import com.gyee.wisdom.alarm.sharding.entity.AlarmSnap;
import com.gyee.wisdom.alarm.sharding.entity.FaultHistory;
import com.gyee.wisdom.alarm.sharding.entity.FaultSnap;
import com.gyee.wisdom.alarm.sharding.mapper.AlarmHisotryMapper;
import com.gyee.wisdom.alarm.sharding.mapper.AlarmSnapMapper;
import com.gyee.wisdom.alarm.sharding.mapper.FaultHisotryMapper;
import com.gyee.wisdom.alarm.sharding.mapper.FaultSnapMapper;
import com.gyee.wisdom.alarm.sharding.util.SnowflakeGenerator;
import com.gyee.wisdom.common.utils.DateUtil;
import com.gyee.wisdom.common.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.annotations.Param;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;


@Service
@Slf4j
public class AlarmSnapService extends ServiceImpl<AlarmSnapMapper, AlarmSnap> {

    @Autowired
    private AlarmSnapMapper alarmSnapMapper;

    @Autowired
    private AlarmHisotryMapper alarmHisotryMapper;

    @Autowired
    private TableNameService tableNameService;

    @Autowired
    private FaultSnapMapper faultSnapMapper;

    @Autowired
    private FaultHisotryMapper faultHisotryMapper;

    public AlarmSnap queryById(long snapId) {
        return alarmSnapMapper.selectById(snapId);
    }

    public List<AlarmSnap> queryAll(String stationId,
                                    String windturbineId,
                                    String category1,
                                    String category2,
                                    String rank,
                                    String modelid,
                                    Integer isopened,
                                    String keyword,
                                    String startTime,
                                    String endTime) throws Exception {
        if (keyword != null && keyword.trim() != "")
            keyword = "%" + keyword.trim() + "%";
        Date dtStart = null;
        Date dtEnd = null;
        if (startTime != null && startTime.trim() != "")
            dtStart = DateUtil.parseDate1(startTime);
        if (endTime != null && endTime.trim() != "")
            dtEnd = DateUtil.parseDate1(endTime);

        return alarmSnapMapper.queryAll(stationId, windturbineId, category1, category2, rank,
                modelid, isopened, keyword, dtStart, dtEnd);
    }

    public IPage<AlarmSnap> pageQueryAll(Page page,
                                         String stationId,
                                         String windturbineId,
                                         String category1,
                                         String category2,
                                         String rank,
                                         String modelid,
                                         Integer isopened,
                                         String keyword,
                                         String startTime,
                                         String endTime) throws Exception{
        if (keyword != null && keyword.trim() != "")
            keyword = "%" + keyword.trim() + "%";
        Date dtStart = null;
        Date dtEnd = null;
        if (startTime != null && startTime.trim() != "")
            dtStart = DateUtil.parseDate1(startTime);
        if (endTime != null && endTime.trim() != "")
            dtEnd = DateUtil.parseDate1(endTime);

        return alarmSnapMapper.pageQueryAll(page, stationId, windturbineId, category1, category2, rank,
                modelid, isopened, keyword, dtStart, dtEnd);

    }

    public void saveAlarmSnap(AlarmSnap alarmSnap) throws Exception{
        if (alarmSnap.getId() == null || alarmSnap.getId() <= 0) {
            alarmSnap.setId(SnowflakeGenerator.generateId());
            alarmSnapMapper.insert(alarmSnap);
        } else
            alarmSnapMapper.updateById(alarmSnap);

        AlarmHistory his = createAlarmHistory(alarmSnap);
        String tableName = tableNameService.getAlarmHistoryTableName(alarmSnap.getStationId());
        alarmHisotryMapper.singleInsert(tableName, his);

        //5级报警写入到故障表
        if (alarmSnap.getRank().equals("5")) {
            FaultSnap faultSnap = faultSnapMapper.findByAlarmSnapId(alarmSnap.getId());
            if (faultSnap != null) {
                faultSnap.setIsOpened(alarmSnap.getIsOpened());
                faultSnap.setLastUpdateTime(alarmSnap.getLastUpdateTime());
                faultSnapMapper.updateById(faultSnap);
            } else {
                faultSnap = createFaultSnap(alarmSnap);
                faultSnapMapper.insert(faultSnap);
            }

            //写故障流水
            FaultHistory faultHistory = createFaultHistory(faultSnap);
            faultHisotryMapper.insert(faultHistory);
        }
    }

    public int saveAlarmSnaps(List<AlarmSnap> alarmSnaps) throws Exception{
        if (alarmSnaps == null || alarmSnaps.size() == 0)
            return 0;
        List<AlarmSnap> insertSnaps = new ArrayList<>();
        List<AlarmSnap> updateSnaps = new ArrayList<>();
        HashMap<String, List<AlarmHistory>> hisMap = new HashMap<>();

        for (AlarmSnap snap : alarmSnaps) {
            if (snap.getId() == null || snap.getId() <= 0) {
                snap.setId(SnowflakeGenerator.generateId());
                insertSnaps.add(snap);
            } else {
                if ("1".equals(snap.getCategory3())) {
                    insertSnaps.add(snap);
                } else
                    updateSnaps.add(snap);
            }

            AlarmHistory his = createAlarmHistory(snap);

            //region 如果报警为升压站类报警,则根据alarmSnap 中的dataInfo(测点值0,或1)
            if (snap.getCategory1().contains("SYZ")) {
                if (snap.getAlertText().contains("地刀") || snap.getAlertText().contains("刀闸") || snap.getAlertText().contains("分位") || snap.getAlertText().contains("合位") ||
                        snap.getAlertText().contains("手车") || snap.getAlertText().contains("断路器") || snap.getAlertText().contains("开关")) {
                    if (StringUtil.isNotBlank(snap.getDataInfo())) {
                        //测点值为0
                        if (snap.getDataInfo().equals("0")) {
                            his.setAlertTextLast("--分位状态");
                        } else if (snap.getDataInfo().equals("1")) {
                            his.setAlertTextLast("--合位状态");
                        }
                    }
                }

            }
            //endregion

            if (hisMap.containsKey(snap.getStationId()) == false) {
                hisMap.put(snap.getStationId(), new ArrayList<>());
            }
            List<AlarmHistory> lst = hisMap.get(snap.getStationId());
            lst.add(his);
        }

        if (insertSnaps.size() > 0)
            alarmSnapMapper.batchInsert(insertSnaps);

        if (updateSnaps.size() > 0){
            alarmSnapMapper.batchUpdate(updateSnaps);

        }

        for (Map.Entry<String, List<AlarmHistory>> entry : hisMap.entrySet()) {
            //System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
            String tableName = tableNameService.getAlarmHistoryTableName(entry.getKey());
            if (entry.getValue() != null && entry.getValue().size() > 0)
                alarmHisotryMapper.batchInsert(tableName, entry.getValue());
        }

        //5级报警写入故障表
        List<FaultSnap> insertFaultSnaps = new ArrayList<>();
        List<FaultSnap> updateFaultSnaps = new ArrayList<>();
        List<FaultHistory> insertfaultHistories = new ArrayList<>();
        if (insertSnaps.size() > 0) {
            for (AlarmSnap as : insertSnaps) {
                if (as.getRank().equals("5")) {
                    FaultSnap fs = createFaultSnap(as);
                    insertFaultSnaps.add(fs);
//                    FaultHistory fh = createFaultHistory(fs);
//                    insertfaultHistories.add(fh);
                }
            }
        }

        if (updateSnaps.size() > 0) {
            for (AlarmSnap as : updateSnaps) {
                if (as.getRank().equals("5")) {
                    FaultSnap fs = faultSnapMapper.findByAlarmSnapId(as.getId());
                    if (fs != null) {
                        fs.setIsOpened(as.getIsOpened());
                        fs.setLastUpdateTime(as.getLastUpdateTime());
                        //将alarmSnap中dataInfo(测点值传递)赋值faultsnap
                        fs.setDataInfo(as.getDataInfo());
                        updateFaultSnaps.add(fs);
                    } else {
                        fs = createFaultSnap(as);
                        //将alarmSnap中dataInfo(测点值传递)赋值faultsnap
                        fs.setDataInfo(as.getDataInfo());
                        insertFaultSnaps.add(fs);
                    }

//                    FaultHistory fh = createFaultHistory(fs);
//                    insertfaultHistories.add(fh);
                }
            }
        }

        if (insertFaultSnaps.size() > 0){
            //insertFaultSnaps = checkGroupSnap(insertFaultSnaps);
            for (Iterator it = insertFaultSnaps.iterator(); it.hasNext(); ) {
                FaultSnap snap = (FaultSnap) it.next();
                if ("GROUP".equals(snap.getCategory3())) {
                    updateFaultSnaps.add(snap);
                    insertFaultSnaps.remove(snap);
                }
            }
            faultSnapMapper.batchInsert(insertFaultSnaps);
            for (FaultSnap snap : insertFaultSnaps) {
                FaultHistory fh =  createFaultHistory(snap);

                //region 如果报警未升压站类报警,则根据alarmSnap 中的dataInfo(测点值0,或1)
                if (snap.getCategory1().contains("SYZ")) {
                    if (snap.getAlertText().contains("地刀") || snap.getAlertText().contains("刀闸") || snap.getAlertText().contains("分位") || snap.getAlertText().contains("合位") ||
                            snap.getAlertText().contains("手车") || snap.getAlertText().contains("断路器") || snap.getAlertText().contains("开关")) {
                        if (StringUtil.isNotBlank(snap.getDataInfo())) {
                            //测点值为0
                            if (snap.getDataInfo().equals("0")) {
                                fh.setAlertTextLast("--分位状态");
                            } else if (snap.getDataInfo().equals("1")) {
                                fh.setAlertTextLast("--合位状态");
                            }
                        }
                    }

                }
                //endregion

                insertfaultHistories.add(fh);
            }
        }


        if (updateFaultSnaps.size() > 0){
            //updateFaultSnaps = checkGroupSnap(updateFaultSnaps);
            faultSnapMapper.batchUpdate(updateFaultSnaps);
            for (FaultSnap snap : updateFaultSnaps) {
                FaultHistory fh =  createFaultHistory(snap);
                //region 如果报警未升压站类报警,则根据alarmSnap 中的dataInfo(测点值0,或1)
                if (snap.getCategory1().contains("SYZ")) {
                    if (snap.getAlertText().contains("地刀") || snap.getAlertText().contains("刀闸") || snap.getAlertText().contains("分位") || snap.getAlertText().contains("合位") ||
                            snap.getAlertText().contains("手车") || snap.getAlertText().contains("断路器") || snap.getAlertText().contains("开关")) {
                        if (StringUtil.isNotBlank(snap.getDataInfo())) {
                            //测点值为0
                            if (snap.getDataInfo().equals("0")) {
                                fh.setAlertTextLast("--分位状态");
                            } else if (snap.getDataInfo().equals("1")) {
                                fh.setAlertTextLast("--合位状态");
                            }
                        }
                    }

                }
                //endregion

                insertfaultHistories.add(fh);
            }
        }

        if (insertfaultHistories.size() > 0)
            faultHisotryMapper.batchInsert(insertfaultHistories);

        return 1;
    }

    public AlarmHistory createAlarmHistory(AlarmSnap snap) {
        AlarmHistory result = new AlarmHistory();
        result.setId(SnowflakeGenerator.generateId());
        result.setSnapId(snap.getId());
        result.setAlertTime(snap.getLastUpdateTime());
        result.setDataInfo(snap.getDataInfo());

        if (snap.getIsOpened() != 0)
            result.setMessageType(1);
        else
            result.setMessageType(3);

        return result;
    }

    public FaultSnap createFaultSnap(AlarmSnap snap) {
        FaultSnap result = new FaultSnap();
        result.setId(SnowflakeGenerator.generateId());
        result.setAlarmSnapId(snap.getId());
        result.setAlertText(snap.getAlertText());
        result.setAlertValue(snap.getAlertValue());
        if ("custom".equals(snap.getCategory1())) {
            if ("1".equals(snap.getCategory2()))
                result.setCategory1("FJ");
            else
                result.setCategory1("STATION");
            result.setCategory2("custom");
        } else if ("windturbine".equals(snap.getCategory1())) {
            result.setCategory1("FJ");
            result.setCategory2(snap.getCategory2());
        } else {
            result.setCategory1(snap.getCategory1());
            result.setCategory2(snap.getCategory2());
        }

        result.setCategory3(snap.getCategory3());
        result.setStationId(snap.getStationId());
        result.setProjectId(snap.getProjectId());
        result.setLineId(snap.getLineId());
        result.setWindturbineId(snap.getWindturbineId());
        result.setStationName(snap.getStationName());
        result.setProjectName(snap.getProjectName());
        result.setLineName(snap.getLineName());
        result.setWindturbineName(snap.getWindturbineName());
        result.setTestingpointKey(snap.getTestingpointKey());
        result.setRank(snap.getRank());
        result.setIsOpened(snap.getIsOpened());
        result.setLastUpdateTime(snap.getLastUpdateTime());

        return result;
    }

    public FaultHistory createFaultHistory(FaultSnap snap) {
        FaultHistory result = new FaultHistory();
        result.setId(SnowflakeGenerator.generateId());
        result.setSnapId(snap.getId());
        result.setFaultTime(snap.getLastUpdateTime());
        result.setConfirmType(0);

        if (snap.getIsOpened() != 0)
            result.setMessageType(1);
        else
            result.setMessageType(3);

        return result;
    }

    private void testSaveHistory() {
        AlarmSnap snap = alarmSnapMapper.selectById(1010);
        AlarmHistory his = createAlarmHistory(snap);

        alarmHisotryMapper.singleInsert("alarmhistory_dwk_201906", his);

    }

    private void testSaveSnap() throws Exception{
        List<AlarmSnap> lst = new ArrayList<>();
        for (int i = 1; i < 1011; i++) {
            AlarmSnap snap = alarmSnapMapper.selectById(i);
            snap.setIsOpened(1);
            snap.setLastUpdateTime(new Date());
            snap.setDataInfo(i + "");
            lst.add(snap);
        }

        this.saveAlarmSnaps(lst);


    }

    public AlarmSnap findByWindturbineIdAndAlertValue(String windturbineid, int alertvalue) {
        return alarmSnapMapper.findByWindturbineIdAndAlertValue(windturbineid, alertvalue);
    }

    public AlarmSnap findByStationIdAndAlertValue(String stationId, int alertvalue) {
        return alarmSnapMapper.findByStationIdAndAlertValue(stationId, alertvalue);
    }

    public AlarmSnap findByTestingpointkey(String testingpointkey) {
        return alarmSnapMapper.findByTestingpointkey(testingpointkey);
    }

    public List<AlarmSnap> getTopNumAlarm(String category1, String topNum) throws Exception {
        topNum = topNum.trim();

        int num = Integer.parseInt(topNum);
        if (num < 1)
            return null;
        if (num > 2000)
            num = 2000;

        return alarmSnapMapper.getTopNumAlarm(category1, num);
    }

    public List<AlarmSnap>  getRecentAlarm(String category1,
                                           Date lastUpdateTime) {
        return  alarmSnapMapper.getRecentAlarm(category1, lastUpdateTime);
    }

}
