package com.mortals.xhx.module.device.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.mortals.framework.common.Rest;
import com.mortals.framework.exception.AppException;
import com.mortals.framework.model.Context;
import com.mortals.framework.model.OrderCol;
import com.mortals.framework.model.PageInfo;
import com.mortals.framework.model.Result;
import com.mortals.framework.service.impl.AbstractCRUDServiceImpl;
import com.mortals.framework.util.DateUtils;
import com.mortals.xhx.common.code.*;
import com.mortals.xhx.common.pdu.site.SitePdu;
import com.mortals.xhx.feign.site.ISiteFeign;
import com.mortals.xhx.module.alarm.model.AlarmSmsSendQuery;
import com.mortals.xhx.module.alarm.service.AlarmSmsSendService;
import com.mortals.xhx.module.device.dao.DeviceStatDao;
import com.mortals.xhx.module.device.model.*;
import com.mortals.xhx.module.device.service.DeviceAlarmInfoService;
import com.mortals.xhx.module.device.service.DeviceLogService;
import com.mortals.xhx.module.device.service.DeviceService;
import com.mortals.xhx.module.device.service.DeviceStatService;
import com.mortals.xhx.module.site.model.SiteEntity;
import com.mortals.xhx.module.site.service.SiteService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.util.*;

import static java.math.BigDecimal.ROUND_HALF_DOWN;

/**
 * DeviceStatService
 * 设备统计 service实现
 *
 * @author zxfei
 * @date 2022-07-05
 */
@Service("deviceStatService")
public class DeviceStatServiceImpl extends AbstractCRUDServiceImpl<DeviceStatDao, DeviceStatEntity, Long> implements DeviceStatService {

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private SiteService siteService;
    @Value("${platform.type:cloud}")
    private String platFormType;//版本，默认云服务版本
    @Autowired
    private DeviceStatService deviceStatService;
    @Autowired
    private DeviceAlarmInfoService deviceAlarmInfoService;
    @Autowired
    private AlarmSmsSendService alarmSmsSendService;
    @Autowired
    private DeviceLogService deviceLogService;

    @Autowired
    private ISiteFeign siteFeign;

    @Override
    public List<DeviceStatEntity> find(DeviceStatEntity params, Context context) throws AppException {
        return super.find(params, context);
    }

    @Override
    public Result<DeviceStatEntity> find(DeviceStatEntity query, PageInfo pageInfo, Context context) throws AppException {
        Result<DeviceStatEntity> deviceStatEntityResult = new Result<>();
        if (!ObjectUtils.isEmpty(query.getSelected())) {
            PageInfo page = new PageInfo();
            List<DeviceStatEntity> billInfos;
            //转换日期
            switch (DaySelectEnum.getByValue(query.getSelected())) {
                case 今天:
                    page.setPrePageResult(1);
                    billInfos = this.getBillInfos(query.getSiteId(), query.getCreateTimeStart(), TimeUnitEnum.DAY.getValue(), page, context);
                    deviceStatEntityResult.setList(billInfos);
                    deviceStatEntityResult.setPageInfo(page);
                    break;
                case 近七天:
                    page.setPrePageResult(7);
                    billInfos = this.getBillInfos(query.getSiteId(), query.getCreateTimeStart(), TimeUnitEnum.DAY.getValue(), page, context);
                    deviceStatEntityResult.setList(billInfos);
                    deviceStatEntityResult.setPageInfo(page);
                    break;
                case 近三十天:
                    page.setPrePageResult(30);
                    billInfos = this.getBillInfos(query.getSiteId(), query.getCreateTimeStart(), TimeUnitEnum.DAY.getValue(), page, context);
                    deviceStatEntityResult.setList(billInfos);
                    deviceStatEntityResult.setPageInfo(page);
                    break;
                case 近三月:
                    page.setPrePageResult(3);
                    billInfos = this.getBillInfos(query.getSiteId(), query.getCreateTimeStart(), TimeUnitEnum.MONTH.getValue(), page, context);
                    deviceStatEntityResult.setList(billInfos);
                    deviceStatEntityResult.setPageInfo(page);

                    updateDeviceOnlineStats(query, context, page, billInfos);
                    break;
                case 今年:
                    page.setPrePageResult(1);
                    billInfos = this.getBillInfos(query.getSiteId(), query.getCreateTimeStart(), TimeUnitEnum.YEAR.getValue(), page, context);
                    deviceStatEntityResult.setList(billInfos);
                    deviceStatEntityResult.setPageInfo(page);
                    updateDeviceOnlineStats(query, context, page, billInfos);
                    break;
                default:
                    break;
            }
            return deviceStatEntityResult;
        } else {
            return super.find(query, pageInfo, context);
        }
    }

    private void updateDeviceOnlineStats(DeviceStatEntity query, Context context, PageInfo page, List<DeviceStatEntity> billInfos) {
        //统计在线离线未激活的数据用当天
        DeviceStatQuery deviceStatQuery = new DeviceStatQuery();
        deviceStatQuery.setSiteId(query.getSiteId());
        deviceStatQuery.setSelected(DaySelectEnum.今天.getValue());
        deviceStatQuery.setCreateTimeStart(DateUtil.today());
        PageInfo page1 = new PageInfo();
        page.setPrePageResult(1);
        List<DeviceStatEntity> infos = this.getBillInfos(deviceStatQuery.getSiteId(), deviceStatQuery.getCreateTimeStart(), TimeUnitEnum.DAY.getValue(), page1, context);
        if(!ObjectUtils.isEmpty(infos)){
            DeviceStatEntity deviceStatEntity = infos.get(0);
            billInfos.forEach(item->{
                item.setDeviceOnlineCount(deviceStatEntity.getDeviceOnlineCount());
                item.setDeviceOfflineCount(deviceStatEntity.getDeviceOfflineCount());
                item.setDeviceUnActiveCount(deviceStatEntity.getDeviceUnActiveCount());
            });
        }
    }

    @Override
    public List<DeviceStatEntity> getBillInfos(Long siteId, String createTimeStart, Integer datePattern, PageInfo pageInfo, Context context) {
        List<DeviceStatEntity> statList = new ArrayList<>();
        DeviceStatQuery query = new DeviceStatQuery();
        query.setSiteId(siteId);
        query.setCreateTimeStart(createTimeStart);
        if (datePattern == TimeUnitEnum.DAY.getValue()) {
            query.setGroupList(Arrays.asList("day"));
            query.setOrderColList(Arrays.asList(new OrderCol("year", OrderCol.DESCENDING), new OrderCol("month", OrderCol.DESCENDING), new OrderCol("day", OrderCol.DESCENDING), new OrderCol("createTime")));
            statList = this.getDao().getStatList(query, pageInfo);
        } else if (datePattern == TimeUnitEnum.MONTH.getValue()) {
            query.setGroupList(Arrays.asList("month"));
            query.setOrderColList(Arrays.asList(new OrderCol("year", OrderCol.DESCENDING), new OrderCol("month", OrderCol.DESCENDING), new OrderCol("createTime")));
            statList = this.getDao().getStatList(query, pageInfo);
        } else if (datePattern == TimeUnitEnum.YEAR.getValue()) {
            query.setGroupList(Arrays.asList("year"));
            query.setOrderColList(Arrays.asList(new OrderCol("year", OrderCol.DESCENDING), new OrderCol("createTime")));
            statList = this.getDao().getStatList(query, pageInfo);
        } else {
            throw new AppException("不支持当前日期格式查询统计！");
        }
        return statList;
    }


    /**
     * 全部设备-》激活设备与未激活-》启用与停用设备-》离线与在线设备
     *
     * @param context
     */
    @Override
    public void deviceStat(Long siteId, Context context) {
        //查询当天统计，如果有 则更新统计结果，否则新增
        Calendar calendar = Calendar.getInstance();
        DeviceStatEntity deviceStatEntity = this.selectOne(new DeviceStatQuery()
                .siteId(siteId)
                .year(calendar.get(Calendar.YEAR))
                .month(calendar.get(Calendar.MONTH) + 1)
                .day(calendar.get(Calendar.DAY_OF_MONTH)));
        if (ObjectUtils.isEmpty(deviceStatEntity)) {
            deviceStatEntity = new DeviceStatEntity();
            deviceStatEntity.initAttrValue();
            deviceStatEntity.setSiteId(siteId);
            deviceStatEntity.setCreateTime(new Date());

            deviceStatEntity.setYear(calendar.get(Calendar.YEAR));
            deviceStatEntity.setMonth(calendar.get(Calendar.MONTH) + 1);
            deviceStatEntity.setDay(calendar.get(Calendar.DAY_OF_MONTH));
        }
        //获取昨天统计数据
        DeviceStatEntity yesterdayDeviceStat = this.selectOne(new DeviceStatQuery()
                .siteId(siteId)
                .year(DateUtil.year(new Date()))
                .month(DateUtil.month(new Date()) + 1)
                .day(DateUtil.dayOfMonth(new Date())));
        if (ObjectUtils.isEmpty(yesterdayDeviceStat)) {
            yesterdayDeviceStat = new DeviceStatEntity();
            yesterdayDeviceStat.initAttrValue();
            yesterdayDeviceStat.setSiteId(siteId);
            // yesterdayDeviceStat.setYear(DateUtil.year(DateUtil.yesterday()));
            yesterdayDeviceStat.setYear(DateUtil.year(new Date()));
        }
        try {
            //获取设备总数
            List<DeviceEntity> deviceList = deviceService.find(new DeviceQuery().siteId(siteId));
            Integer deviceTotalCount = deviceList.size();
            if (deviceTotalCount > 0) {
                log.info("设备总数大于0，可统计");
                //未激活数量
                Long deviceUnActiveCount = deviceList.parallelStream()
                        .filter(f -> f.getDeviceStatus() == DeviceStatusEnum.未激活.getValue())
                        .count();
                //激活设备
                Integer deviceActiveCount = deviceList.size() - deviceUnActiveCount.intValue();

                deviceStatEntity.setDeviceTotalCount(deviceTotalCount);
                deviceStatEntity.setDeviceAddCount(deviceTotalCount - yesterdayDeviceStat.getDeviceTotalCount());

                ///统计按当前站点归集 // TODO: 2022/8/22
                if (platFormType.equalsIgnoreCase(PlatformTypeEnum.STANDALONE.getValue())) {
                    List<SiteEntity> list = siteService.getFlatSitesBySiteId(siteId, context);
                    deviceStatEntity.setSiteTotalCount(list.size());
                    deviceStatEntity.setSiteAddCount(list.size() - yesterdayDeviceStat.getSiteTotalCount());
                } else {
                    SitePdu sitePdu = new SitePdu();
                    sitePdu.setId(siteId);
                    Rest<List<SitePdu>> resp = siteFeign.getFlatSitesBySiteId(sitePdu);
                    if (resp.getCode() == 1) {
                        List<SitePdu> sitePduList = resp.getData();
                        deviceStatEntity.setSiteTotalCount(sitePduList.size());
                        deviceStatEntity.setSiteAddCount(sitePduList.size() - yesterdayDeviceStat.getSiteTotalCount());
                    }
                }

                //在线数量
                Long deviceOnlineCount = deviceList.parallelStream()
                        .filter(f -> f.getDeviceStatus() > DeviceStatusEnum.未激活.getValue())
                        .filter(f -> f.getEnabled() == EnabledEnum.启用.getValue())
                        .filter(f -> f.getDeviceStatus() == DeviceStatusEnum.在线.getValue())
                        .count();
                deviceStatEntity.setDeviceOnlineCount(deviceOnlineCount.intValue());
                //在线率=在线设备/所有激活设备
                if (deviceActiveCount > 0) {
                    deviceStatEntity.setDeviceOnlineRatio(new BigDecimal(deviceOnlineCount).divide(new BigDecimal(deviceActiveCount), 4, ROUND_HALF_DOWN));
                }

                //离线数量
                Long deviceOfflineCount = deviceList.parallelStream()
                        .filter(f -> f.getDeviceStatus() > DeviceStatusEnum.未激活.getValue())
                        .filter(f -> f.getEnabled() == EnabledEnum.启用.getValue())
                        .filter(f -> f.getDeviceStatus() == DeviceStatusEnum.离线.getValue())
                        .count();
                deviceStatEntity.setDeviceOfflineCount(deviceOfflineCount.intValue());
                if (deviceActiveCount > 0) {
                    deviceStatEntity.setDeviceOfflineRatio(new BigDecimal(deviceOfflineCount).divide(new BigDecimal(deviceActiveCount), 4, ROUND_HALF_DOWN));
                }
                //停用数量
                Long deviceStopCount = deviceList.parallelStream()
                        .filter(f -> f.getDeviceStatus() > DeviceStatusEnum.未激活.getValue())
                        .filter(f -> f.getEnabled() == YesNoEnum.NO.getValue())
                        .count();
                deviceStatEntity.setDeviceStopCount(deviceStopCount.intValue());
                if (deviceActiveCount > 0) {
                    deviceStatEntity.setDeviceStopRatio(new BigDecimal(deviceStopCount).divide(new BigDecimal(deviceActiveCount), 4, ROUND_HALF_DOWN));
                }


                deviceStatEntity.setDeviceUnActiveCount(deviceUnActiveCount.intValue());
                if (deviceActiveCount > 0) {
                    deviceStatEntity.setDeviceUnActiveRatio(new BigDecimal(deviceUnActiveCount).divide(new BigDecimal(deviceActiveCount), 4, ROUND_HALF_DOWN));
                }

                //今日告警数量
                DeviceAlarmInfoQuery deviceAlarmInfoQuery = new DeviceAlarmInfoQuery();
                deviceAlarmInfoQuery.setSiteId(siteId);
                deviceAlarmInfoQuery.setCreateTimeStart(DateUtils.getCurrStrDate());
                deviceAlarmInfoQuery.setCreateTimeEnd(DateUtils.getCurrStrDate());

                int alarmTotalCount = deviceAlarmInfoService.count(deviceAlarmInfoQuery, null);
                deviceStatEntity.setAlarmTotalCount(alarmTotalCount);
                deviceStatEntity.setAlarmAddCount(alarmTotalCount - yesterdayDeviceStat.getAlarmTotalCount());

                //推送数量
                AlarmSmsSendQuery alarmSmsSendQuery = new AlarmSmsSendQuery();
                alarmSmsSendQuery.setSiteId(siteId);
                alarmSmsSendQuery.setSendTimeStart(DateUtils.getCurrStrDate());
                alarmSmsSendQuery.setSendTimeEnd(DateUtils.getCurrStrDate());
                alarmSmsSendQuery.setSendStatus(SendStatusEnum.发送成功.getValue());

                int pushTotalCount = alarmSmsSendService.count(alarmSmsSendQuery, null);
                deviceStatEntity.setPushTotalCount(pushTotalCount);
                deviceStatEntity.setPushAddCount(pushTotalCount - yesterdayDeviceStat.getPushTotalCount());

                //上行下行数量
                DeviceLogQuery deviceLogQuery = new DeviceLogQuery();
                deviceLogQuery.setSiteId(siteId);
                deviceLogQuery.setCreateTimeStart(DateUtils.getCurrStrDate());
                deviceLogQuery.setCreateTimeEnd(DateUtils.getCurrStrDate());
                deviceLogQuery.setLogType(LogTypeEnum.上报事件.getValue());
                int uploadMessageTotalCount = deviceLogService.count(deviceLogQuery, null);
                deviceLogQuery.setLogType(LogTypeEnum.下发服务.getValue());
                int downloadMessageTotalCount = deviceLogService.count(deviceLogQuery, null);
                deviceStatEntity.setUploadMessageTotalCount(uploadMessageTotalCount);
                deviceStatEntity.setDownloadMessageTotalCount(downloadMessageTotalCount);
                deviceStatEntity.setSiteId(siteId);
            }
            if (deviceStatEntity.newEntity()) {
                deviceStatEntity.setCreateTime(new Date());
                deviceStatService.save(deviceStatEntity);
            } else {
                deviceStatEntity.setUpdateTime(new Date());
                deviceStatService.update(deviceStatEntity);
            }

        } catch (Exception e) {
            log.error("统计异常", e);
            throw new AppException("统计异常!");
        }
    }

    @Override
    public void deviceStatByDay(String dateStr, Context context) {
        DateTime dateTime = DateUtil.parseDate(dateStr);
        int day = dateTime.dayOfMonth();
        int month = dateTime.month()+1;
        int year = dateTime.year();





    }

}