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

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);
                    break;
                case 今年:
                    page.setPrePageResult(1);
                    billInfos = this.getBillInfos(query.getSiteId(), query.getCreateTimeStart(), TimeUnitEnum.YEAR.getValue(), page, context);
                    deviceStatEntityResult.setList(billInfos);
                    deviceStatEntityResult.setPageInfo(page);
                    break;
                default:
                    break;
            }
            return deviceStatEntityResult;
        } else {
            return super.find(query, pageInfo, context);
        }
    }

    @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(calendar.get(Calendar.YEAR))
                .month(calendar.get(Calendar.MONTH) + 1)
                .day(calendar.get(Calendar.DAY_OF_MONTH)));
        if (ObjectUtils.isEmpty(yesterdayDeviceStat)) {
            yesterdayDeviceStat = new DeviceStatEntity();
            yesterdayDeviceStat.initAttrValue();
            yesterdayDeviceStat.setSiteId(siteId);
            // yesterdayDeviceStat.setYear(DateUtil.year(DateUtil.yesterday()));
            yesterdayDeviceStat.setYear(calendar.get(Calendar.YEAR));
        }
        try {
            //获取设备总数
            List<DeviceEntity> deviceList = deviceService.find(new DeviceQuery().siteId(siteId));
            Integer deviceTotalCount = deviceList.size();

            //未激活数量
            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 {
                Rest<List<SitePdu>> resp = siteFeign.getFlatSitesBySiteId(new SitePdu().id(siteId));
                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.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.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.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("统计异常!");
        }
    }

}