package com.zksy.manhole.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zksy.api.utils.AlarmLevelUtil;
import com.zksy.manhole.domain.ManholeData;
import com.zksy.manhole.mapper.ManholeDataMapper;
import com.zksy.manhole.service.ManholeDataService;
import com.zksy.manhole.utils.AlarmUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;

/**
 * 井盖数据Service业务层处理
 * 
 * @author zksy
 */
@Slf4j
@Service
public class ManholeDataServiceImpl extends ServiceImpl<ManholeDataMapper, ManholeData> implements ManholeDataService {

    @Autowired
    private ManholeDataMapper manholeDataMapper;
    @Autowired
    private AlarmUtil alarmUtil;

    /** 倾斜角度告警编码 */
    private static final String WARN_CODE_TILT = "WARN-TILT";
    /** 设备报警编码 */
    private static final String WARN_CODE_DEVICE = "WARN-DEVICE-ALARM";
    /** 水浸告警编码 */
    private static final String WARN_CODE_WATER_INFILTRATION = "WARN-WATER-INFILTRATION";
    /** 水位告警编码 */
    private static final String WARN_CODE_WATER_LEVEL = "WARN-WATER-LEVEL";

    @Override
    public Integer saveManholeData(ManholeData result) {
        Integer resultData = manholeDataMapper.insert(result);

        if (resultData > 0) {
            checkAndSaveAlarm(result);
        }

        return resultData;
    }

    /**
     * 检查并保存告警数据
     * - 倾斜角度：阈值来自采集数据字段 angleAlarmThreshold，根据偏差率计算告警等级
     * - 设备报警/水浸/水位：状态型告警，告警即为1级
     */
    private void checkAndSaveAlarm(ManholeData result) {
        String deviceCode = result.getImeiCardNumber();
        boolean hasAlarm = false;

        // 1. 倾斜角度告警：阈值从采集数据字段 angleAlarmThreshold 获取
        if (checkTiltAlarm(result, deviceCode)) {
            hasAlarm = true;
        }

        // 2. 设备报警状态：告警即为1级
        if ("1".equals(result.getAlarmStatus())) {
            alarmUtil.saveAlarmWithLevel(deviceCode, "设备报警", WARN_CODE_DEVICE,
                    null, 1, "井盖设备状态报警");
            hasAlarm = true;
        }

        // 3. 水浸报警状态：告警即为1级
        if ("1".equals(result.getWaterInfiltrationAlarmStatus())) {
            alarmUtil.saveAlarmWithLevel(deviceCode, "水浸预警", WARN_CODE_WATER_INFILTRATION,
                    null, 1, "井盖水浸报警");
            hasAlarm = true;
        }

        // 4. 水位报警状态：告警即为1级
        if ("1".equals(result.getWaterLevelAlarmStatus())) {
            alarmUtil.saveAlarmWithLevel(deviceCode, "水位预警", WARN_CODE_WATER_LEVEL,
                    null, 1, "井盖水位报警");
            hasAlarm = true;
        }

        // 5. 同步设备报警状态到 equipment_status 表
        alarmUtil.updateDeviceAlarmStatus(deviceCode, hasAlarm ? 1 : 0);
    }

    /**
     * 倾斜角度告警检查
     * 阈值直接从采集数据字段 angleAlarmThreshold 获取，不再查询阈值表
     * 根据实际值和阈值的偏差率计算告警等级
     * @return 是否触发告警
     */
    private boolean checkTiltAlarm(ManholeData result, String deviceCode) {
        String tiltAngleStr = result.getTiltAngle();
        String angleThresholdStr = result.getAngleAlarmThreshold();

        if (tiltAngleStr == null || tiltAngleStr.isEmpty()
                || angleThresholdStr == null || angleThresholdStr.isEmpty()) {
            return false;
        }

        try {
            BigDecimal tiltAngle = new BigDecimal(tiltAngleStr);
            BigDecimal angleThreshold = new BigDecimal(angleThresholdStr);

            // 倾斜角度超过阈值才告警
            if (tiltAngle.compareTo(angleThreshold) < 0) {
                return false;
            }

            // 使用 AlarmLevelUtil 计算告警等级
            // minValue=0（正常角度为0），maxValue=angleThreshold（阈值作为上限）
            BigDecimal minValue = BigDecimal.ZERO;
            int alarmLevel = AlarmLevelUtil.calculateLevel(tiltAngle, minValue, angleThreshold);
            BigDecimal deviationRatio = AlarmLevelUtil.calculateDeviationRatio(tiltAngle, minValue, angleThreshold);

            String remark = String.format("井盖倾斜报警，当前角度：%s°，阈值：%s°",
                    tiltAngle, angleThreshold);

            alarmUtil.saveAlarm(deviceCode, "倾斜预警", WARN_CODE_TILT,
                    minValue, angleThreshold, tiltAngle, remark);

            log.info("倾斜告警入库: deviceCode={}, tiltAngle={}°, threshold={}°, level={}级, deviationRatio={}%",
                    deviceCode, tiltAngle, angleThreshold, alarmLevel, deviationRatio);
            return true;
        } catch (NumberFormatException e) {
            log.error("倾斜角度或阈值解析失败: tiltAngle={}, threshold={}", tiltAngleStr, angleThresholdStr, e);
            return false;
        }
    }
}