package com.yuchen.saas.park.service.fault.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yuchen.saas.park.api.entity.device.PmgBatSmartEquipment;
import com.yuchen.saas.park.api.entity.fault.*;
import com.yuchen.saas.park.api.vo.fault.DeviceProperty;
import com.yuchen.saas.park.api.vo.fault.EquipmentStatusVo;
import com.yuchen.saas.park.service.fault.mapper.EquipmentStatusMapper;
import com.yuchen.saas.park.service.fault.service.EquipmentBreakdownHistoryService;
import com.yuchen.saas.park.service.service.PmgBatSmartEquipmentService;
import com.yuchen.saas.park.service.fault.service.EquipmentBreakdownRuleService;
import com.yuchen.saas.park.service.fault.service.EquipmentPictureAnalyseService;
import com.yuchen.saas.park.service.fault.service.EquipmentStatusService;
import org.nest.springwrap.core.mp.base.BaseServiceImpl;
import org.nest.springwrap.core.tool.api.R;
import org.nest.springwrap.core.tool.utils.BeanUtil;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;

/**
 * @Author: 肖润飞
 * @CreateTime: 2022/10/18 15:47
 * @Description: 设备状态
 * @Version: 1.0
 */
@Service
public class EquipmentStatusServiceImpl extends BaseServiceImpl<EquipmentStatusMapper, EquipmentStatus> implements EquipmentStatusService {

    @Resource
    private EquipmentBreakdownRuleService ruleService;

    @Resource
    private EquipmentBreakdownHistoryService historyService;

    @Resource
    private EquipmentPictureAnalyseService pictureAnalyseService;

    @Resource
    private EquipmentStatusMapper equipmentStatusMapper;

    @Resource
    private PmgBatSmartEquipmentService pmgBatSmartEquipmentService;

    /**
     * 保存设备的状态
     *
     * @param deviceProperty 设备属性值
     * @param equipment      设备基础信息
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean saveEquipmentStatus(DeviceProperty deviceProperty, PmgBatSmartEquipment equipment) {
        // 1.查询该设备状态是否存在
        LambdaQueryWrapper<EquipmentStatus> query = Wrappers.lambdaQuery();
        query.eq(EquipmentStatus::getProductKey, equipment.getProductKey());
        query.eq(EquipmentStatus::getDeviceName, equipment.getDeviceName());

        EquipmentStatus equipmentStatus = this.getOne(query);
        // 设备设备更新时间
        DateTime deviceTime = DateUtil.date(Long.valueOf(deviceProperty.getDeviceTime()) * 1000);

        if (equipmentStatus == null) {
            equipmentStatus = new EquipmentStatus();
            equipmentStatus.setSmartEquipmentId(equipment.getId());
            equipmentStatus.setProductKey(equipment.getProductKey());
            equipmentStatus.setDeviceName(equipment.getDeviceName());
            equipmentStatus.setCreateTime(deviceTime);
            equipmentStatus.setUpdateTime(deviceTime);//设置设备状态更新时间
            this.save(equipmentStatus);
        }
        equipmentStatus.setUpdateTime(deviceTime);//设置设备状态更新时间
        // 2.判断该设备状态是否故障
        EquipmentBreakdownRule rule = ruleService.checkEquipmentStatus(deviceProperty);
        if (rule != null) {
            if (rule.getId() == null) { //2.1设备正常
                // 2.1.1设备状态正常,存储设备状态信息
                UpdateWrapper<EquipmentStatus> updateWrapper = new UpdateWrapper<>();
                updateWrapper.set("picture_analyse_id", null);
                updateWrapper.set("status", 0);
                updateWrapper.eq("id", equipmentStatus.getId());
                // 设备状态正常,将状态值更新为0,并且画像分析id置为null
                this.update(updateWrapper);
                // 2.1.2如果设备状态正常,检测当前设备异常历史,更新故障恢复时间
                LambdaQueryWrapper<EquipmentBreakdownHistory> historyQuery = Wrappers.lambdaQuery();
                historyQuery
                        .eq(EquipmentBreakdownHistory::getEquipmentStatusId, equipmentStatus.getId())
                        .eq(EquipmentBreakdownHistory::getBreakdownCode, rule.getBreakdownCode())
                        .isNull(EquipmentBreakdownHistory::getRecoverTime)
                        .orderByDesc(EquipmentBreakdownHistory::getCreateTime)
                        .last(" limit 1");
                // 拿到最新的一个故障历史数据
                EquipmentBreakdownHistory history = historyService.getOne(historyQuery);
                if (history != null) {
                    history.setRecoverTime(deviceTime);
                    historyService.updateById(history);
                }
                return true;
            }
            if (rule.getId() != null) { //2.2设备异常
                // 2.2.1设备异常状态
                equipmentStatus.setStatus(1);
                // 设置异常code
                equipmentStatus.setBreakdownCode(rule.getBreakdownCode());
                // 2.2.2保存设备故历史数据
                EquipmentBreakdownHistory history = new EquipmentBreakdownHistory();
                history.setBreakdownCode(rule.getBreakdownCode());
                history.setBreakdownName(rule.getRuleName());// 设置故障规则名称
                history.setEquipmentStatusId(equipmentStatus.getId());
                history.setCreateTime(deviceTime);
                history.setBreakdownValue(deviceProperty.getValue());//设置异常产生时候数据值
                historyService.save(history);
                // 2.2.3保存设备画像数据
                EquipmentPictureAnalyse analyse = pictureAnalyseService.saveAnalyse(equipmentStatus, history);
                if (analyse != null) {
                    equipmentStatus.setPictureAnalyseId(analyse.getId());
                }
                //3.保存设备状态数据
                return this.saveOrUpdate(equipmentStatus);
            }
        }
        return false;
    }

    /**
     * 根据设备离线事件保存离线
     *
     * @param connectEvent 设备离线事件
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public Boolean saveEquipmentEvent(ConnectEvent connectEvent) {
        PmgBatSmartEquipment result = pmgBatSmartEquipmentService.getDetails(connectEvent.getProductKey(),
                connectEvent.getDeviceName());
        DeviceProperty deviceProperty = new DeviceProperty();
        BeanUtil.copyProperties(connectEvent, deviceProperty);
        deviceProperty.setDeviceTime(connectEvent.getTime());
        deviceProperty.setIdentify("isOnline");
        if (connectEvent.getOnline()) {
            deviceProperty.setValue("1");
        } else {
            deviceProperty.setValue("0");
        }
        Boolean save = this.saveEquipmentStatus(deviceProperty, result);
        return save;
    }

    /**
     * 设备状态分页
     *
     * @param page
     * @param vo
     * @return
     */
    @Override
    public R pageStatus(Page page, EquipmentStatusVo vo) {
        IPage<EquipmentStatusVo> statusVoIPage = equipmentStatusMapper.selectEqStatus(page, vo);
        return R.data(statusVoIPage);
    }

    /**
     * 设备状态详情
     *
     * @param id 状态id
     * @return
     */
    @Override
    public R detail(Long id) {
        //获得设备状态基础数据
        EquipmentStatusVo equipmentStatusVo = equipmentStatusMapper.selectEqStatusDetail(id);
        if (equipmentStatusVo != null) {
            LambdaQueryWrapper<EquipmentBreakdownHistory> query = Wrappers.lambdaQuery();
            query.eq(EquipmentBreakdownHistory::getEquipmentStatusId, equipmentStatusVo.getId());
            int count = historyService.count(query);
            equipmentStatusVo.setBreakdownNumber(count);
        }
        return R.data(equipmentStatusVo);
    }
}