package com.zsc.edu.gateway.modules.iot.record.service.impl;

import com.alibaba.fastjson2.JSONException;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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.zsc.edu.gateway.modules.iot.device.entity.Device;
import com.zsc.edu.gateway.modules.iot.device.repo.DeviceRepository;
import com.zsc.edu.gateway.modules.iot.record.entity.DataWarningVo;
import com.zsc.edu.gateway.modules.iot.record.entity.RecordData;
import com.zsc.edu.gateway.modules.iot.record.entity.RecordDataStatusVo;
import com.zsc.edu.gateway.framework.springEvent.TemperatureExceededEvent;
import com.zsc.edu.gateway.modules.iot.record.repo.RecordDataRepository;
import com.zsc.edu.gateway.modules.iot.record.service.RecordDataService;
import com.zsc.edu.gateway.modules.iot.tsl.entity.Event;
import com.zsc.edu.gateway.modules.iot.tsl.entity.Param;
import com.zsc.edu.gateway.modules.iot.tsl.repo.EventRepository;
import jakarta.annotation.Resource;
import lombok.AllArgsConstructor;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;

/**
 * @author zhuang
 */
@AllArgsConstructor
@Service
public class RecordDataServiceImpl extends ServiceImpl<RecordDataRepository, RecordData> implements RecordDataService {

    @Resource
    private final ApplicationEventPublisher eventPublisher;
    @Resource
    private final DeviceRepository deviceRepository;
    @Resource
    private final EventRepository eventRepository;
    @Override
    public RecordData recordData(String clientId, JSONObject data) {
        RecordData recordData = new RecordData();
        recordData.setClientId(clientId);
        recordData.setContent(data);
        recordData.setRecordTime(LocalDateTime.now());
        this.save(recordData);
        processRecordData(recordData);
        return recordData;
    }

    @Override
    public RecordDataStatusVo recordDataStatus() {
        RecordDataStatusVo recordDataStatusVo = new RecordDataStatusVo();
        recordDataStatusVo.setRecordCount(baseMapper.selectCount(new LambdaQueryWrapper<RecordData>()));
        recordDataStatusVo.setDataCount(baseMapper.selectCount(new LambdaQueryWrapper<RecordData>().isNotNull(RecordData::getContent)));
        return recordDataStatusVo;
    }

    @Override
    public DataWarningVo dataWarning() {
        DataWarningVo dataWarningVo = new DataWarningVo();
        LocalDateTime todayStart = LocalDateTime.now().withHour(0).withMinute(0).withSecond(0);
        long warningCount = baseMapper.countWarnings();
        long todayWarningCount = baseMapper.countTodayWarnings(todayStart);
        long firstWarningCount = baseMapper.countWarningsByBit(1);
        long secondWarningCount = baseMapper.countWarningsByBit(2);
        long thirdWarningCount = baseMapper.countWarningsByBit(4);
        dataWarningVo.setWarningCount(warningCount);
        dataWarningVo.setTodayWarningCount(todayWarningCount);
        dataWarningVo.setFirstWarningCount(firstWarningCount);
        dataWarningVo.setSecondWarningCount(secondWarningCount);
        dataWarningVo.setThirdWarningCount(thirdWarningCount);
        return dataWarningVo;
    }

    @Override
    public IPage<RecordData> query(Page<RecordData> page, String clientId) {
        LambdaQueryWrapper<RecordData> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RecordData::getClientId, clientId);
        return baseMapper.selectPage(page, queryWrapper);
    }

    public void processRecordData(RecordData recordData) {
        // 根据 clientId 查询设备信息
        Device device = deviceRepository.findByClientId(recordData.getClientId());

        // 获取产品下的所有事件
        List<Event> events = eventRepository.selectByProductId(device.getProductId());

        // 遍历每个事件
        for (Event event : events) {
            // 遍历事件的 outputs 列表中的每个参数
            event.getOutputs().forEach(param -> {
                processParam(recordData, param, event);
            });
        }
    }

    private void processParam(RecordData recordData, Param param, Event event) {
        // 获取参数的默认值和比较类型
        Double defaultValue = param.getDefaultValue();
        String identifier = param.getIdentifier();

        // 检查 recordData 的内容中是否包含该参数的标识符
        if (recordData.getContent().get(identifier) != null) {
            // 获取参数的实际值
            double value = Double.parseDouble(recordData.getContent().get(identifier).toString());
            Param.CompareType compareType = param.getCompareType();

            // 根据比较类型进行不同的处理
            switch (compareType) {
                case GT:
                    if (value > defaultValue) {
                        eventPublisher.publishEvent(new TemperatureExceededEvent(this, recordData, value, event.getName()));
                    }
                    break;
                case LT:
                    if (value < defaultValue) {
                        eventPublisher.publishEvent(new TemperatureExceededEvent(this, recordData, value, event.getName()));
                    }
                    break;
                case EQ:
                    if (value == defaultValue) {
                        eventPublisher.publishEvent(new TemperatureExceededEvent(this, recordData, value, event.getName()));
                    }
                    break;
                default:
                    // 处理未知的比较类型
                    throw new JSONException("Unknown compare type: " + compareType);
            }
        }
    }


}
