/*
 * 文 件 名:  InspectionAlarmAdapter
 * 版    权:  华设设计集团股份有限公司
 * 描    述:  巡检与告警集成适配器 - 完整实现版
 * 修 改 人:  lvwenbin
 * 修改时间:  2026/2/3
 */
package com.ruoyi.ems.service.alarm;

import com.ruoyi.ems.domain.Alarm;
import com.ruoyi.ems.domain.AlarmRule;
import com.ruoyi.ems.domain.CheckItemResult;
import com.ruoyi.ems.domain.EmsDevice;
import com.ruoyi.ems.domain.EmsObjAttrValue;
import com.ruoyi.ems.domain.InspectionReport;
import com.ruoyi.ems.domain.InspectionReportDetail;
import com.ruoyi.ems.domain.InspectionRule;
import com.ruoyi.ems.service.IEmsObjAttrValueService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 巡检与告警集成适配器
 *
 * 【功能说明】
 * 1. 将自动巡检的异常结果转换为告警
 * 2. 复用告警规则引擎进行检查
 * 3. 实现巡检和告警的联动
 *
 * 【调用时机】
 * 在 InspectionPlanServiceImpl.executeAutoInspection() 执行完成后调用
 *
 * 【告警来源】
 * - Alarm.SOURCE_INSPECTION (2): 自动巡检产生的告警
 */
@Slf4j
@Component
public class InspectionAlarmAdapter {

    @Autowired
    private AlarmProcessService alarmProcessService;

    @Autowired
    private IEmsObjAttrValueService attrValueService;

    /**
     * 处理巡检结果，生成告警
     *
     * 【核心入口方法】
     * 在巡检执行完成后调用，将异常设备生成告警
     *
     * @param report 巡检报告
     * @param details 巡检明细列表
     * @return 生成的告警列表
     */
    public List<Alarm> processInspectionResult(InspectionReport report, List<InspectionReportDetail> details) {
        List<Alarm> alarms = new ArrayList<>();

        if (report == null || CollectionUtils.isEmpty(details)) {
            log.debug("巡检报告或明细为空，跳过告警生成");
            return alarms;
        }

        log.info("开始处理巡检结果生成告警: reportCode={}, detailCount={}",
            report.getReportCode(), details.size());

        int processedCount = 0;
        int alarmCount = 0;

        for (InspectionReportDetail detail : details) {
            // 只处理异常的设备
            if (detail.getResultStatus() == null || detail.getResultStatus() == 0) {
                continue;
            }

            processedCount++;

            try {
                List<Alarm> deviceAlarms = processDeviceDetail(detail, report.getReportCode());
                if (CollectionUtils.isNotEmpty(deviceAlarms)) {
                    alarms.addAll(deviceAlarms);
                    alarmCount += deviceAlarms.size();
                }
            } catch (Exception e) {
                log.error("处理设备巡检结果异常: deviceCode={}, error={}",
                    detail.getDeviceCode(), e.getMessage(), e);
            }
        }

        log.info("巡检结果告警生成完成: reportCode={}, 处理异常设备数={}, 生成告警数={}",
            report.getReportCode(), processedCount, alarmCount);

        return alarms;
    }

    /**
     * 处理单个设备的巡检明细，生成告警
     */
    private List<Alarm> processDeviceDetail(InspectionReportDetail detail, String reportCode) {
        List<Alarm> alarms = new ArrayList<>();

        // 构建设备信息对象
        EmsDevice device = buildDeviceFromDetail(detail);

        // 获取设备属性值（从检查项结果或数据库）
        Map<String, String> attrValues = getDeviceAttrValues(detail);

        if (attrValues.isEmpty()) {
            log.warn("设备属性值为空，无法生成告警: deviceCode={}", detail.getDeviceCode());
            return alarms;
        }

        // 调用告警处理服务进行规则检查和告警生成
        try {
            List<Alarm> generatedAlarms = alarmProcessService.processInspection(
                device, attrValues, reportCode);

            if (CollectionUtils.isNotEmpty(generatedAlarms)) {
                alarms.addAll(generatedAlarms);
                log.debug("设备[{}]生成告警数量: {}", detail.getDeviceCode(), generatedAlarms.size());
            }
        } catch (Exception e) {
            log.error("调用告警处理服务异常: deviceCode={}, error={}",
                detail.getDeviceCode(), e.getMessage());
        }

        return alarms;
    }

    /**
     * 从巡检明细构建设备对象
     */
    private EmsDevice buildDeviceFromDetail(InspectionReportDetail detail) {
        EmsDevice device = new EmsDevice();
        device.setDeviceCode(detail.getDeviceCode());
        device.setDeviceName(detail.getDeviceName());
        device.setDeviceModel(detail.getDeviceModel());
        device.setDeviceModelName(detail.getDeviceModelName());
        device.setLocation(detail.getLocation());
        device.setAreaPath(detail.getAreaPath());

        // 从areaPath解析areaCode（取最后一个）
        if (StringUtils.isNotBlank(detail.getAreaPath())) {
            String[] paths = detail.getAreaPath().split(",");
            if (paths.length > 0) {
                device.setAreaCode(paths[paths.length - 1].trim());
            }
        }

        // 从检查项中提取设备状态
        List<CheckItemResult> checkItems = detail.getCheckItemList();
        if (CollectionUtils.isNotEmpty(checkItems)) {
            for (CheckItemResult item : checkItems) {
                if ("deviceStatus".equals(item.getAttrKey()) && item.getActualValue() != null) {
                    try {
                        device.setDeviceStatus(Integer.parseInt(item.getActualValue()));
                    } catch (NumberFormatException ignored) {
                    }
                    break;
                }
            }
        }

        return device;
    }

    /**
     * 从巡检明细中提取属性值
     * 优先从检查项结果获取，否则从数据库获取
     */
    private Map<String, String> getDeviceAttrValues(InspectionReportDetail detail) {
        Map<String, String> attrValues = new HashMap<>();

        // 1. 优先从checkItems中提取（已有的检查结果）
        List<CheckItemResult> checkItems = detail.getCheckItemList();
        if (CollectionUtils.isNotEmpty(checkItems)) {
            for (CheckItemResult item : checkItems) {
                if (StringUtils.isNotBlank(item.getAttrKey())
                    && StringUtils.isNotBlank(item.getActualValue())) {
                    attrValues.put(item.getAttrKey(), item.getActualValue());
                }
            }
        }

        // 2. 如果checkItems数据不完整，从数据库补充
        if (attrValues.size() < 3 && StringUtils.isNotBlank(detail.getDeviceModel())) {
            try {
                List<EmsObjAttrValue> dbValues = attrValueService.selectByObjCode(
                    detail.getDeviceModel(), detail.getDeviceCode());
                if (CollectionUtils.isNotEmpty(dbValues)) {
                    for (EmsObjAttrValue v : dbValues) {
                        if (v.getAttrKey() != null && v.getAttrValue() != null) {
                            // 不覆盖已有值
                            attrValues.putIfAbsent(v.getAttrKey(), v.getAttrValue());
                        }
                    }
                }
            } catch (Exception e) {
                log.warn("获取设备属性值失败: deviceCode={}, error={}",
                    detail.getDeviceCode(), e.getMessage());
            }
        }

        return attrValues;
    }

    /**
     * 将巡检规则转换为告警规则格式
     *
     * 【说明】
     * 用于需要复用巡检规则配置的场景
     * 当巡检规则和告警规则需要统一管理时使用
     *
     * @param inspectionRule 巡检规则
     * @return 告警规则
     */
    public AlarmRule convertToAlarmRule(InspectionRule inspectionRule) {
        if (inspectionRule == null) {
            return null;
        }

        AlarmRule alarmRule = new AlarmRule();
        alarmRule.setRuleCode("IR_" + inspectionRule.getRuleCode());
        alarmRule.setRuleName(inspectionRule.getRuleName());
        alarmRule.setDeviceModel(inspectionRule.getDeviceModel());
        alarmRule.setAttrKey(inspectionRule.getAttrKey());
        alarmRule.setAttrName(inspectionRule.getAttrName());
        alarmRule.setCheckType(inspectionRule.getCheckType());
        alarmRule.setThresholdMin(inspectionRule.getMinValue());
        alarmRule.setThresholdMax(inspectionRule.getMaxValue());
        alarmRule.setThresholdValue(inspectionRule.getExpectValue());
        alarmRule.setAlarmLevel(AlarmRule.LEVEL_NORMAL); // 默认一般级别
        alarmRule.setEnabled(inspectionRule.getEnabled());
        alarmRule.setUseForInspection(1);
        alarmRule.setUseForRealtime(0); // 巡检规则默认不用于实时监测

        // 根据检查类型设置操作符
        if (inspectionRule.getCheckType() != null) {
            switch (inspectionRule.getCheckType()) {
                case 1: // 范围检查
                    alarmRule.setOperator(AlarmRule.OP_RANGE);
                    break;
                case 2: // 等值检查
                    alarmRule.setOperator(AlarmRule.OP_EQ);
                    break;
                case 4: // 在线状态
                    alarmRule.setOperator(AlarmRule.OP_EQ);
                    alarmRule.setThresholdValue("0"); // 离线值
                    break;
                default:
                    alarmRule.setOperator(AlarmRule.OP_NE);
                    break;
            }
        }

        return alarmRule;
    }

    /**
     * 批量转换巡检规则为告警规则
     *
     * @param inspectionRules 巡检规则列表
     * @return 告警规则列表
     */
    public List<AlarmRule> convertToAlarmRules(List<InspectionRule> inspectionRules) {
        if (CollectionUtils.isEmpty(inspectionRules)) {
            return new ArrayList<>();
        }

        return inspectionRules.stream()
            .filter(r -> r != null && r.getEnabled() != null && r.getEnabled() == 1)
            .map(this::convertToAlarmRule)
            .filter(r -> r != null)
            .collect(Collectors.toList());
    }

    /**
     * 根据检查项结果直接生成告警（不依赖告警规则）
     *
     * 【用途】
     * 当巡检检查项结果已经明确标记异常时，直接生成告警
     * 无需再次进行规则匹配
     *
     * @param detail 巡检明细
     * @param reportCode 报告代码
     * @return 告警列表
     */
    public List<Alarm> createAlarmsFromCheckItems(InspectionReportDetail detail, String reportCode) {
        List<Alarm> alarms = new ArrayList<>();

        List<CheckItemResult> checkItems = detail.getCheckItemList();
        if (CollectionUtils.isEmpty(checkItems)) {
            return alarms;
        }

        for (CheckItemResult item : checkItems) {
            // 只处理异常项
            if (item.getStatus() == null || item.getStatus() == 0) {
                continue;
            }

            try {
                Alarm alarm = createAlarmFromCheckItem(detail, item, reportCode);
                if (alarm != null) {
                    alarms.add(alarm);
                }
            } catch (Exception e) {
                log.warn("从检查项创建告警失败: deviceCode={}, ruleCode={}, error={}",
                    detail.getDeviceCode(), item.getRuleCode(), e.getMessage());
            }
        }

        return alarms;
    }

    /**
     * 从单个检查项创建告警
     */
    private Alarm createAlarmFromCheckItem(InspectionReportDetail detail,
        CheckItemResult item,
        String reportCode) {
        Alarm alarm = new Alarm();

        // 设置告警ID（由AlarmProcessService处理）
        alarm.setAlarmId(null);

        // 设置区域（从areaPath解析）
        if (StringUtils.isNotBlank(detail.getAreaPath())) {
            String[] paths = detail.getAreaPath().split(",");
            if (paths.length > 0) {
                alarm.setAreaCode(paths[paths.length - 1].trim());
            }
        }

        // 设置目标信息
        alarm.setTargetType(2); // 设备
        alarm.setTargetCode(detail.getDeviceCode());
        alarm.setTargetName(detail.getDeviceName());
        alarm.setDeviceModel(detail.getDeviceModel());
        alarm.setDeviceModelName(detail.getDeviceModelName());
        alarm.setLocation(detail.getLocation());

        // 设置规则和属性信息
        alarm.setRuleCode(item.getRuleCode());
        alarm.setRuleName(item.getRuleName());
        alarm.setAttrKey(item.getAttrKey());
        alarm.setAttrName(item.getAttrName());
        alarm.setAttrValue(item.getActualValue());
        alarm.setThresholdValue(item.getExpectRange());

        // 设置告警级别（默认一般）
        alarm.setAlarmLevel(Alarm.LEVEL_NORMAL);

        // 设置告警代码（从规则代码派生）
        alarm.setAlarmCode("INSP_" + (StringUtils.isNotBlank(item.getRuleCode())
            ? item.getRuleCode() : "UNKNOWN"));

        // 设置告警消息
        String msg = StringUtils.isNotBlank(item.getMessage())
            ? item.getMessage()
            : String.format("设备[%s]%s异常，当前值：%s",
            detail.getDeviceName(),
            item.getAttrName() != null ? item.getAttrName() : item.getAttrKey(),
            item.getActualValue());
        alarm.setAlarmMsg(msg);

        // 设置来源信息
        alarm.setAlarmSource(Alarm.SOURCE_INSPECTION);
        alarm.setSourceRef(reportCode);

        return alarm;
    }
}