package com.aucma.base.service.impl;

import com.aucma.base.domain.BaseDeviceParam;
import com.aucma.base.domain.BaseDeviceParamVal;
import com.aucma.base.domain.ProcessAlert;
import com.aucma.base.mapper.BaseDeviceParamMapper;
import com.aucma.base.mapper.ProcessAlertMapper;
import com.aucma.base.service.IDeviceParamReadFacade;
import com.aucma.base.service.IProcessAlertService;
import com.aucma.common.utils.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * 工艺预警Service业务层处理
 *
 * @author Yinq
 * @date 2025-12-30
 */
@Service
public class ProcessAlertServiceImpl implements IProcessAlertService {
    private static final Logger log = LoggerFactory.getLogger(ProcessAlertServiceImpl.class);
    
    @Autowired
    private ProcessAlertMapper processAlertMapper;
    
    @Autowired
    private BaseDeviceParamMapper baseDeviceParamMapper;

    @Autowired
    private IDeviceParamReadFacade deviceParamReadFacade;

    @Override
    public ProcessAlert selectProcessAlertByAlertId(Long alertId) {
        return processAlertMapper.selectProcessAlertByAlertId(alertId);
    }

    @Override
    public List<ProcessAlert> selectProcessAlertList(ProcessAlert processAlert) {
        return processAlertMapper.selectProcessAlertList(processAlert);
    }

    @Override
    public int insertProcessAlert(ProcessAlert processAlert) {
        processAlert.setCreateTime(DateUtils.getNowDate());
        if (processAlert.getAlertTime() == null) {
            processAlert.setAlertTime(DateUtils.getNowDate());
        }
        if (processAlert.getAlertStatus() == null || processAlert.getAlertStatus().isEmpty()) {
            processAlert.setAlertStatus("0");
        }
        if (processAlert.getIsFlag() == null || processAlert.getIsFlag().isEmpty()) {
            processAlert.setIsFlag("1");
        }
        return processAlertMapper.insertProcessAlert(processAlert);
    }

    @Override
    public int updateProcessAlert(ProcessAlert processAlert) {
        processAlert.setUpdateTime(DateUtils.getNowDate());
        return processAlertMapper.updateProcessAlert(processAlert);
    }

    @Override
    public int deleteProcessAlertByAlertIds(Long[] alertIds) {
        return processAlertMapper.deleteProcessAlertByAlertIds(alertIds);
    }

    @Override
    public int deleteProcessAlertByAlertId(Long alertId) {
        return processAlertMapper.deleteProcessAlertByAlertId(alertId);
    }
    
    @Override
    public int checkThresholdAlerts() {
        int alertCount = 0;
        BaseDeviceParam queryParam = new BaseDeviceParam();
        queryParam.setAlertEnabled("1");
        queryParam.setIsFlag(1L);
        List<BaseDeviceParam> paramList = baseDeviceParamMapper.selectBaseDeviceParamList(queryParam);

        if (paramList == null || paramList.isEmpty()) {
            log.info("没有启用预警的参数配置");
            return 0;
        }

        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        Date now = DateUtils.getNowDate();

        for (BaseDeviceParam param : paramList) {
            if (param.getUpperLimit() == null && param.getLowerLimit() == null) {
                continue;
            }

            // 为什么这样做：预警必须基于统一 latest 口径判断，
            // 否则 NEW 设备月表数据和跨月数据都会被旧逻辑直接漏掉。
            BaseDeviceParamVal latestVal = deviceParamReadFacade.getLatestParamValue(
                    param.getDeviceCode(), param.getParamCode(), param.getParamName());
            if (latestVal == null || latestVal.getParamValue() == null || latestVal.getParamValue().isEmpty()) {
                continue;
            }

            String paramValueStr = latestVal.getParamValue();
            try {
                double paramValue = Double.parseDouble(paramValueStr);
                String alertType = null;
                String thresholdValue = null;

                if (param.getUpperLimit() != null && paramValue > param.getUpperLimit()) {
                    alertType = "超上限";
                    thresholdValue = String.valueOf(param.getUpperLimit());
                } else if (param.getLowerLimit() != null && paramValue < param.getLowerLimit()) {
                    alertType = "低于下限";
                    thresholdValue = String.valueOf(param.getLowerLimit());
                }

                if (alertType == null) {
                    continue;
                }

                ProcessAlert existingAlert = processAlertMapper.selectUnhandledAlert(
                        param.getDeviceCode(),
                        param.getParamCode()
                );

                if (existingAlert != null) {
                    existingAlert.setAlertValue(paramValueStr);
                    existingAlert.setAlertTime(latestVal.getCollectTime() != null ? latestVal.getCollectTime() : now);
                    existingAlert.setAlertContent(param.getParamName() + alertType + "，当前值：" + paramValueStr + "，阈值：" + thresholdValue);
                    updateProcessAlert(existingAlert);
                    log.info("更新未处理预警: {}", existingAlert.getAlertContent());
                    continue;
                }

                ProcessAlert latestAlert = processAlertMapper.selectLatestAlert(
                        param.getDeviceCode(),
                        param.getParamCode()
                );

                if (latestAlert != null && "2".equals(latestAlert.getAlertStatus())) {
                    long timeDiff = now.getTime() - latestAlert.getAlertTime().getTime();
                    long cooldownMinutes = 5;
                    if (timeDiff < cooldownMinutes * 60 * 1000) {
                        log.debug("预警冷却期内，跳过: deviceCode={}, paramCode={}",
                                param.getDeviceCode(), param.getParamCode());
                        continue;
                    }
                }

                ProcessAlert alert = new ProcessAlert();
                alert.setAlertCode("ALERT-" + sdf.format(now) + "-" + (alertCount + 1));
                alert.setAlertType("参数超限");
                alert.setAlertLevel(param.getAlertLevel() != null ? param.getAlertLevel() : "1");
                alert.setDeviceCode(param.getDeviceCode());
                alert.setDeviceName(param.getDeviceName());
                alert.setParamCode(param.getParamCode());
                alert.setParamName(param.getParamName());
                alert.setAlertContent(param.getParamName() + alertType + "，当前值：" + paramValueStr + "，阈值：" + thresholdValue);
                alert.setAlertValue(paramValueStr);
                alert.setThresholdValue(thresholdValue);
                alert.setAlertTime(latestVal.getCollectTime() != null ? latestVal.getCollectTime() : now);
                alert.setAlertStatus("0");
                alert.setIsFlag("1");
                alert.setCreateTime(now);

                insertProcessAlert(alert);
                alertCount++;
                log.info("生成新预警: {}", alert.getAlertContent());
            } catch (NumberFormatException e) {
                log.warn("参数值无法转换为数字: paramCode={}, value={}", param.getParamCode(), paramValueStr);
            }
        }

        return alertCount;
    }

    @Override
    @Transactional
    public int batchMarkAsProcessed(Long[] alertIds, String handleUser) {
        if (alertIds == null || alertIds.length == 0) {
            return 0;
        }
        
        int count = 0;
        Date now = DateUtils.getNowDate();
        
        for (Long alertId : alertIds) {
            try {
                ProcessAlert alert = processAlertMapper.selectProcessAlertByAlertId(alertId);
                if (alert != null && !"2".equals(alert.getAlertStatus())) {
                    alert.setAlertStatus("2"); // 已处理
                    alert.setHandleUser(handleUser);
                    alert.setHandleTime(now);
                    alert.setHandleResult("批量标记为已处理");
                    processAlertMapper.updateProcessAlert(alert);
                    count++;
                    log.info("批量标记预警已处理: alertId={}, alertCode={}", alertId, alert.getAlertCode());
                }
            } catch (Exception e) {
                log.error("标记预警已处理失败: alertId={}", alertId, e);
            }
        }
        
        return count;
    }
}
