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.cache.WindturbineCache;
import com.gyee.wisdom.alarm.sharding.entity.*;
import com.gyee.wisdom.alarm.sharding.mapper.AlarmCountMapper;
import com.gyee.wisdom.alarm.sharding.mapper.AlarmHisotryMapper;
import com.gyee.wisdom.alarm.sharding.model.AlarmHistoryInfo;
import com.gyee.wisdom.alarm.sharding.model.CodeValue;
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.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestParam;

import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;


@Service
@Slf4j
@EnableScheduling
public class AlarmCountService extends ServiceImpl<AlarmCountMapper, AlarmCount> {

    @Autowired
    private AlarmCountMapper alarmCountMapper;

    @Autowired
    private TableNameService tableNameService;

    @Autowired
    private AlarmSnapService alarmSnapService;

    @Autowired
    private AlarmHistoryService alarmHistoryService;

    @Autowired
    private WindturbineCache windturbineCache;

    @Autowired
    private WindturbineService windturbineService;
    @Autowired
    private AlarmCountService alarmCountService;

    @Value("${count.custom}")
    public boolean custom;

    public boolean startCount(String strDate) {
        try {
            List<AlarmSnap> snapList = alarmSnapService.queryAll(null, null, "custom", null, null, null, null, null, null, null);

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date dtStart = sdf.parse(strDate);
            Date dtEnd = DateUtil.addDays(dtStart, 1);
            List<AlarmCount> acList = new ArrayList<>();
            for (AlarmSnap snap : snapList) {
                String tbName = tableNameService.getAlarmHistoryTableName(snap.getStationId(), dtStart);
                int count = alarmHistoryService.selectSnapCount(tbName, snap.getId(), dtStart, dtEnd);
                AlarmCount ac = new AlarmCount();
                ac.setId(SnowflakeGenerator.generateId());
                ac.setAlarmDate(dtStart);
                ac.setSnapId(snap.getId());
                ac.setCount(count);

                acList.add(ac);
            }

            //alarmCountMapper.batchInsert(acList);

        } catch (Exception ex) {
            log.error(ex.getMessage());
            log.error(ex.getStackTrace().toString());
            return false;
        }
        return true;
    }


    public Map<Long, AlarmStat1> statAlarmCount5(String stationId, String windturbineid, String startDate, String endDate) {
        try {
            Map<Long, AlarmStat1> stringIntegerMap = new HashMap<>();
            Map<Long, AlarmStat1> stringIntegerMap2 = new HashMap<>();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date dtStart = sdf.parse(startDate);
            Date dtEnd = sdf.parse(endDate);
            if (StringUtil.isNotBlank(stationId) && dtEnd.after(dtStart)) {
                List<AlarmStat1> alarmStat1s = alarmCountMapper.statAlarmCount5(stationId, windturbineid, dtStart, dtEnd);
                for (int i = 0; i < alarmStat1s.size(); i++) {
                    stringIntegerMap.put(alarmStat1s.get(i).getSnapId(), alarmStat1s.get(i));
                }
            }
            for (Long key : stringIntegerMap.keySet()) {
                if (!stringIntegerMap2.containsKey(stringIntegerMap.get(key))) {
                    stringIntegerMap2.put(key, stringIntegerMap.get(key));
                }
            }
            return stringIntegerMap2;

        } catch (Exception ex) {
            log.error(ex.getMessage());
            log.error(ex.getStackTrace().toString());
            return null;
        }
    }

    public List<AlarmStat1> statAlarmCount1(String stationId, String startDate, String endDate) {
        try {

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date dtStart = sdf.parse(startDate);
            Date dtEnd = sdf.parse(endDate);

            if (StringUtil.isNotBlank(stationId) && dtEnd.after(dtStart))
                return alarmCountMapper.statAlarmCount1(stationId, dtStart, dtEnd);

        } catch (Exception ex) {
            log.error(ex.getMessage());
            log.error(ex.getStackTrace().toString());
            return null;
        }
        return null;
    }

    public List<AlarmStat1> statAlarmCount2(String stationId, Date currentDate) throws Exception {
        return alarmCountMapper.statAlarmCount2(stationId, currentDate);
    }

    public List<AlarmStatLine> lineandproject(String stId, String startDate, String endDate, String name) throws ParseException {
        String startDatetmp = startDate;
        String endDatetmp = endDate;


        List<Windturbine> windturbines = windturbineService.windturbineList();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date begindate = sdf.parse(startDate);
        Date enddate = sdf.parse(endDate);
        List<AlarmStat> alarmStatss = new ArrayList<>();
        for (; ; ) {

            if (sdf.parse(startDate).getTime() > enddate.getTime()) {
                break;
            }

            List<AlarmStat> alarmStats = alarmCountService.statAlarmCount(stId, startDate, startDate);
            for (AlarmStat alarmStat : alarmStats) {
                for (Windturbine windturbine : windturbines) {
                    String str = windturbine.getId();
                    if (str.equalsIgnoreCase(alarmStat.getWtnum())) {
                        alarmStat.setWtnumobj(windturbine);
                        break;
                    }
                }


            }
            alarmStatss.addAll(alarmStats);
            startDate = sdf.format(sdf.parse(startDate).getTime() + 24 * 60 * 60 * 1000);
        }
        AlarmInformation alarmInformation = new AlarmInformation();
        Map<String, AlarmInformation> stringIntegerMap = new HashMap<>();
        Map<String, AlarmInformation> stringIntegerMapfinal = new HashMap<>();
        for (AlarmStat alarmStat : alarmStatss) {
            Integer sum = alarmStat.getSum();
            if (stringIntegerMap.get(alarmStat.getText()) == null) {
                alarmInformation = new AlarmInformation();
                alarmInformation.setSnapId(alarmStat.getSnapid());
                alarmInformation.setSum(sum);
                alarmInformation.setAlarmtext(alarmStat.getText());
            } else {
                int tmp = stringIntegerMap.get(alarmStat.getText()).getSum();
                sum = sum + tmp;
                alarmInformation = new AlarmInformation();
                alarmInformation.setSnapId(alarmStat.getSnapid());
                alarmInformation.setSum(sum);
                alarmInformation.setAlarmtext(alarmStat.getText());
            }
            stringIntegerMap.put(alarmStat.getText(), alarmInformation);
            for (Map.Entry set : stringIntegerMap.entrySet()) {
                AlarmInformation value = (AlarmInformation) set.getValue();
                Long tmpkey = value.getSnapId();
                stringIntegerMapfinal.put(tmpkey + "", value);
            }
        }


        alarmStatss = new ArrayList<>();

        for (; ; ) {

            if (sdf.parse(startDatetmp).getTime() > enddate.getTime()) {
                break;
            }

            List<AlarmStat> alarmStats = alarmCountService.statAlarmCountByname(stId, startDatetmp, startDatetmp, stringIntegerMapfinal.get(name).getAlarmtext());
            for (AlarmStat alarmStat : alarmStats) {
                for (Windturbine windturbine : windturbines) {
                    String str = windturbine.getId();
                    if (str.equalsIgnoreCase(alarmStat.getWtnum())) {
                        alarmStat.setWtnumobj(windturbine);
                        break;
                    }
                }


            }
            alarmStatss.addAll(alarmStats);
            startDatetmp = sdf.format(sdf.parse(startDatetmp).getTime() + 24 * 60 * 60 * 1000);
        }
        List<AlarmStatLine> alarmStatLines = new ArrayList<>();
        Map<String, Map<String, List<Windturbine>>> windturbinemap = new HashMap<>();
        List<Windturbine> windturbineList = windturbineService.windturbineList();
        for (int i = 0; i < windturbineList.size(); i++) {
            if (!windturbineList.get(i).getWindpowerstationid().equalsIgnoreCase(stId)) {
                windturbineList.remove(i);
                i--;
            }
        }
        Map<String, List<Windturbine>> pointProject = windturbineList.stream().collect(Collectors.groupingBy(Windturbine::getProjectid));
        Set set = pointProject.keySet();
        Iterator<String> it = set.iterator();
        while (it.hasNext()) {
            String key = it.next();
            List<Windturbine> windturbineList1 = pointProject.get(key);
            Map<String, List<Windturbine>> pointLine = windturbineList1.stream().collect(Collectors.groupingBy(Windturbine::getLineid));
            Set setline = pointLine.keySet();
            Iterator<String> itline = setline.iterator();
            while (itline.hasNext()) {
                String keyline = itline.next();
                List<Windturbine> windturbineList2 = pointLine.get(keyline);
                AlarmStatLine alarmStatLine = new AlarmStatLine();
                alarmStatLine.setLinenum(keyline);
                alarmStatLine.setProjectnum(windturbineList2.get(0).getProjectid());
                alarmStatLine.setSum(windturbineList2.size());
                alarmStatLine.setHappendsum(0);
                alarmStatLines.add(alarmStatLine);
            }
        }
        Map<String, String> map = new HashMap();
        for (AlarmStat alarmStat : alarmStatss) {
            for (AlarmStatLine alarmStatLine : alarmStatLines) {
                if (alarmStatLine.getLinenum().equalsIgnoreCase(alarmStat.getWtnumobj().getLineid()) && map.get(alarmStat.getWtnumobj().getId()) == null) {
                    map.put(alarmStat.getWtnumobj().getId(), "1");
                    alarmStatLine.setHappendsum(alarmStatLine.getHappendsum() + 1);
                }
            }


        }
        return alarmStatLines;
    }


    public Map<String, AlarmStat> querybyname(String stId, String startDate, String endDate, String snapId) throws ParseException {
        String startDatetmp = startDate;
        String endDatetmp = endDate;
        List<Windturbine> windturbines = windturbineCache.getWindturbineList();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date begindate = sdf.parse(startDate);
        Date enddate = sdf.parse(endDate);
        AlarmSnap alarmSnap = alarmSnapService.getById(snapId);
        if (alarmSnap == null)
            return new HashMap<>();

        List<AlarmStat> alarmStatss = new ArrayList<>();
        for (; ; ) {

            if (sdf.parse(startDatetmp).getTime() >= enddate.getTime()) {
                break;
            }

            List<AlarmStat> alarmStats = alarmCountService.statAlarmCountByname(stId, startDatetmp, startDatetmp, alarmSnap.getAlertText());
            for (AlarmStat alarmStat : alarmStats) {
                for (Windturbine windturbine : windturbines) {
                    String str = windturbine.getId();
                    if (str.equalsIgnoreCase(alarmStat.getWtnum())) {
                        alarmStat.setWtnumobj(windturbine);
                        break;
                    }
                }
            }
            alarmStatss.addAll(alarmStats);
            startDatetmp = sdf.format(sdf.parse(startDatetmp).getTime() + 24 * 60 * 60 * 1000);
        }

        Map<String, AlarmStat> alarmStatMap = new HashMap<>();
        for (AlarmStat alarmStat : alarmStatss) {

            if (alarmStatMap.get(alarmStat.getWtnum()) == null) {

            } else {
                Integer sum = alarmStat.getSum();
                Double times=alarmStat.getTimes();
                int tmpSum = alarmStatMap.get(alarmStat.getWtnum()).getSum();
                Double tmpTimes = alarmStatMap.get(alarmStat.getWtnum()).getTimes();
                sum = sum + tmpSum;
                times=times+tmpTimes;
                alarmStat.setSum(sum);
                alarmStat.setTimes(times);
            }
            alarmStatMap.put(alarmStat.getWtnum(), alarmStat);

        }
        return alarmStatMap;
    }


    public Map<String, AlarmInformation> query1(String stationid, String startDate, String endDate, String windturbineid) throws ParseException {
        List<Windturbine> windturbines = windturbineService.windturbineList();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Date begindate = sdf.parse(startDate);
        Date enddate = sdf.parse(endDate);
        List<AlarmStat> alarmStatss = new ArrayList<>();
        for (; ; ) {

            if (sdf.parse(startDate).getTime() >= enddate.getTime()) {
                break;
            }

            List<AlarmStat> alarmStats = alarmCountService.statAlarmCount1(stationid, startDate, startDate, windturbineid);
            for (AlarmStat alarmStat : alarmStats) {
                for (Windturbine windturbine : windturbines) {
                    String str = windturbine.getId();
                    if (str.equalsIgnoreCase(alarmStat.getWtnum())) {
                        alarmStat.setWtnumobj(windturbine);
                        break;
                    }
                }


            }
            alarmStatss.addAll(alarmStats);
            startDate = sdf.format(sdf.parse(startDate).getTime() + 24 * 60 * 60 * 1000);
        }
        AlarmInformation alarmInformation = new AlarmInformation();
        Map<String, AlarmInformation> informationMap = new HashMap<>();
        Map<String, AlarmInformation> informationMapFinal = new HashMap<>();
        for (AlarmStat alarmStat : alarmStatss) {
            Integer sum = alarmStat.getSum();
           double times=alarmStat.getTimes();
            if (informationMap.get(alarmStat.getText()) == null) {
                alarmInformation = new AlarmInformation();
                alarmInformation.setSnapId(alarmStat.getSnapid());
                alarmInformation.setSum(sum);
                alarmInformation.setAlarmtext(alarmStat.getText());
                alarmInformation.setTimes(alarmStat.getTimes());
            } else {
                int sumTmp = informationMap.get(alarmStat.getText()).getSum();
                double timeTmp = informationMap.get(alarmStat.getText()).getTimes();
                sum = sum + sumTmp;
                times   =times  +timeTmp;
                alarmInformation = new AlarmInformation();
                alarmInformation.setSnapId(alarmStat.getSnapid());
                alarmInformation.setSum(sum);
                alarmInformation.setAlarmtext(alarmStat.getText());
                alarmInformation.setTimes(times );
            }
            informationMap.put(alarmStat.getText(), alarmInformation);
        }
        for (Map.Entry set : informationMap.entrySet()) {
            AlarmInformation value = (AlarmInformation) set.getValue();
            informationMapFinal.put(value.getSnapId().toString(), value);
        }
        return informationMapFinal;
    }


    public boolean startCount() {
        try {
            List<AlarmSnap> snapList = alarmSnapService.queryAll(null, null, "custom", null, null, null, null, null, null, null);
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String strDate = sdf.format(DateUtil.addDays(new Date(), -1));
            Date dtStart = sdf.parse(strDate);
            Date dtEnd = DateUtil.addDays(dtStart, 1);
            Date dtNow = new Date();

            while (dtEnd.getTime() < dtNow.getTime()) {
                List<AlarmCount> acList = new ArrayList<>();
                for (AlarmSnap snap : snapList) {
                    String tbName = tableNameService.getAlarmHistoryTableName(snap.getStationId(), dtStart);
                    int count = alarmHistoryService.selectSnapCount(tbName, snap.getId(), dtStart, dtEnd);
                    if (count > 0) {
                        AlarmCount ac = new AlarmCount();
                        ac.setId(SnowflakeGenerator.generateId());
                        ac.setAlarmDate(dtStart);
                        ac.setSnapId(snap.getId());
                        ac.setCount(count);

                        //此代码块为累加时间代码
                        List<AlarmHistory> alarmHistories = alarmCountMapper.selectAlarmHistoryBySnapid(tbName, snap.getId(), dtStart, dtEnd);
                        boolean bool = true;
                        Date alertTimebegin = null;
                        Date alertTimeend = null;
                        Double minall = 0.0;
                        for (AlarmHistory alarmHistory : alarmHistories) {
                            int messageType = alarmHistory.getMessageType();
                            if (!(messageType == 1 ^ bool)) {
                                if (bool) {
                                    alertTimebegin = alarmHistory.getAlertTime();
                                }
                                if (!bool) {
                                    alertTimeend = alarmHistory.getAlertTime();
                                    Double min = Double.parseDouble((alertTimeend.getTime() - alertTimebegin.getTime()) + "") / 1000 / 60;
                                    minall = minall + min;
                                    bool = true;
                                } else {
                                    bool = false;
                                }
                            }
                        }
                        DecimalFormat df = new DecimalFormat("0.000");
                        ac.setTime(Double.parseDouble(df.format(minall + 1)));
                        acList.add(ac);
                    }
                }

                if (acList.size() > 0)
                    alarmCountMapper.batchInsert(acList);
                dtStart = dtEnd;
                dtEnd = DateUtil.addDays(dtStart, 1);
            }

        } catch (Exception ex) {
            log.error(ex.getMessage());
            log.error(ex.getStackTrace().toString());
            return false;
        }

        return true;
    }

    public List<AlarmStat> statAlarmCount(String stationId, String startDate, String endDate) {
        try {

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date dtStart = sdf.parse(startDate);
            Date dtEnd = DateUtil.addDays(sdf.parse(endDate), 1);
            return alarmCountMapper.statAlarmCount(stationId, dtStart, dtEnd);
        } catch (Exception ex) {
            log.error(ex.getMessage());
            log.error(ex.getStackTrace().toString());
            return null;
        }

    }

    public List<AlarmStat> statAlarmCount1(String stationid, String startDate, String endDate, String windturbineid) {
        try {

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date dtStart = sdf.parse(startDate);
            Date dtEnd = DateUtil.addDays(sdf.parse(endDate), 1);
            return alarmCountMapper.statAlarmCount3(stationid, dtStart, dtEnd, windturbineid);
        } catch (Exception ex) {
            log.error(ex.getMessage());
            log.error(ex.getStackTrace().toString());
            return null;
        }

    }


    public List<AlarmStat> statAlarmCountByname(String stationId, String startDate, String endDate, String name) {
        try {

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date dtStart = sdf.parse(startDate);
            Date dtEnd = DateUtil.addDays(sdf.parse(endDate), 1);
            return alarmCountMapper.statAlarmCountByName(stationId, dtStart, dtEnd, name);
        } catch (Exception ex) {
            log.error(ex.getMessage());
            log.error(ex.getStackTrace().toString());
            return null;
        }

    }


    public List<CodeValue> selectAlertRuleNames() {

        return alarmCountMapper.selectAlertRuleNames();
    }


}
