package com.zksy.api.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zksy.api.domain.EarlyWarning;
import com.zksy.api.domain.EquipmentBase;
import com.zksy.api.mapper.EarlyWarningApiMapper;
import com.zksy.api.mapper.EquipmentBaseApiMapper;
import com.zksy.api.service.EarlyWarningAutoService;
import com.zksy.api.utils.EarlyWarningLevelUtil;
import com.zksy.api.utils.EarlyWarningLevelUtil.EarlyWarningLevelResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.List;
import java.util.Random;

/**
 * 采集数据接近阈值时自动写入 early_warning
 */
@Slf4j
@Service
public class EarlyWarningAutoServiceImpl implements EarlyWarningAutoService {

    private static final String AUTO_PREFIX = "AUTO|";
    private static final String SYSTEM_USER = "系统自动";
    private static final List<String> OPEN_STATUS = Arrays.asList(
            "DRAFT", "PENDING", "PROCESSING", "RELEASED"
    );

    @Autowired
    private EarlyWarningApiMapper earlyWarningApiMapper;

    @Autowired
    private EquipmentBaseApiMapper equipmentBaseApiMapper;

    @Override
    public Integer checkAndGenerate(String deviceCode, String warningType, String warningCode,
                                    BigDecimal minValue, BigDecimal maxValue, BigDecimal actualValue,
                                    String extraRemark) {
        if (deviceCode == null || deviceCode.isEmpty() || warningCode == null || warningCode.isEmpty()) {
            return null;
        }
        if (actualValue == null || (minValue == null && maxValue == null)) {
            return null;
        }

        try {
            // 已越限或回到安全区：关闭自动预警
            if (EarlyWarningLevelUtil.isOverThreshold(actualValue, minValue, maxValue)) {
                closeAutoWarning(deviceCode, warningCode, "已达报警阈值，转报警处理");
                return null;
            }

            EarlyWarningLevelResult result = EarlyWarningLevelUtil.calculate(actualValue, minValue, maxValue);
            if (result == null) {
                closeAutoWarning(deviceCode, warningCode, "监测值已回落至安全区间");
                return null;
            }

            EarlyWarning existing = findOpenAutoWarning(deviceCode, warningCode);
            String content = buildContent(deviceCode, warningType, warningCode,
                    minValue, maxValue, actualValue, result, extraRemark);

            if (existing != null) {
                updateExisting(existing, result, content, warningType);
                return result.getLevel();
            }

            createNew(deviceCode, warningType, warningCode, result, content, minValue, maxValue, actualValue);
            return result.getLevel();
        } catch (Exception e) {
            log.error("自动生成预警失败: deviceCode={}, warningCode={}", deviceCode, warningCode, e);
            return null;
        }
    }

    @Override
    public void closeAutoWarning(String deviceCode, String warningCode, String reason) {
        try {
            EarlyWarning existing = findOpenAutoWarning(deviceCode, warningCode);
            if (existing == null) {
                return;
            }
            existing.setStatus("CLOSED");
            existing.setUpdateBy(SYSTEM_USER);
            existing.setUpdateTime(LocalDateTime.now());
            if (reason != null && !reason.isEmpty()) {
                String content = existing.getWarningContent() == null ? "" : existing.getWarningContent();
                existing.setWarningContent(content + "【系统自动解除】" + reason);
            }
            earlyWarningApiMapper.updateById(existing);
            log.info("自动关闭预警: warningNo={}, deviceCode={}, warningCode={}, reason={}",
                    existing.getWarningNo(), deviceCode, warningCode, reason);
        } catch (Exception e) {
            log.error("关闭自动预警失败: deviceCode={}, warningCode={}", deviceCode, warningCode, e);
        }
    }

    private EarlyWarning findOpenAutoWarning(String deviceCode, String warningCode) {
        String marker = buildRemarkMarker(deviceCode, warningCode);
        return earlyWarningApiMapper.selectOne(new LambdaQueryWrapper<EarlyWarning>()
                .eq(EarlyWarning::getRemark, marker)
                .in(EarlyWarning::getStatus, OPEN_STATUS)
                .orderByDesc(EarlyWarning::getCreateTime)
                .last("LIMIT 1"));
    }

    private void updateExisting(EarlyWarning existing, EarlyWarningLevelResult result,
                                String content, String warningType) {
        String newLevel = String.valueOf(result.getLevel());
        boolean levelChanged = !newLevel.equals(existing.getWarningLevel());
        existing.setWarningLevel(newLevel);
        existing.setWarningContent(content);
        if (warningType != null && !warningType.isEmpty()) {
            existing.setWarningType(warningType);
            existing.setWarningName(buildWarningName(warningType, result.getLevel()));
        }
        existing.setUpdateBy(SYSTEM_USER);
        existing.setUpdateTime(LocalDateTime.now());
        earlyWarningApiMapper.updateById(existing);
        if (levelChanged) {
            log.info("自动更新预警级别: warningNo={}, level={}级, approachRatio={}%",
                    existing.getWarningNo(), result.getLevel(), result.getApproachRatio());
        }
    }

    private void createNew(String deviceCode, String warningType, String warningCode,
                           EarlyWarningLevelResult result, String content,
                           BigDecimal minValue, BigDecimal maxValue, BigDecimal actualValue) {
        EquipmentBase equipment = findEquipment(deviceCode);
        LocalDateTime now = LocalDateTime.now();

        EarlyWarning warning = new EarlyWarning();
        warning.setWarningNo(generateWarningNo());
        warning.setWarningName(buildWarningName(
                warningType != null ? warningType : warningCode, result.getLevel()));
        warning.setWarningType(warningType != null && !warningType.isEmpty() ? warningType : warningCode);
        warning.setWarningLevel(String.valueOf(result.getLevel()));
        warning.setWarningSpecial(warningCode);
        warning.setStatus("RELEASED");
        warning.setPublisher(SYSTEM_USER);
        warning.setPublishTime(now);
        warning.setCreateBy(SYSTEM_USER);
        warning.setCreateTime(now);
        warning.setUpdateTime(now);
        warning.setWarningContent(content);
        warning.setRemark(buildRemarkMarker(deviceCode, warningCode));

        if (equipment != null) {
            warning.setLocation(equipment.getEquipmentLocation());
            warning.setLongitude(equipment.getLongitude());
            warning.setLatitude(equipment.getLatitude());
            warning.setOwnershipUnit(equipment.getOwnershipUnit());
            warning.setHandler(equipment.getMaintainer());
            if (equipment.getEquipmentName() != null) {
                warning.setWarningName(equipment.getEquipmentName() + "-"
                        + buildWarningName(warningType != null ? warningType : warningCode, result.getLevel()));
            }
        } else {
            warning.setLocation("设备编码：" + deviceCode);
        }

        earlyWarningApiMapper.insert(warning);
        log.info("自动生成预警成功: warningNo={}, deviceCode={}, warningCode={}, level={}级, actual={}, min={}, max={}",
                warning.getWarningNo(), deviceCode, warningCode, result.getLevel(),
                actualValue, minValue, maxValue);
    }

    private EquipmentBase findEquipment(String deviceCode) {
        try {
            return equipmentBaseApiMapper.selectOne(new LambdaQueryWrapper<EquipmentBase>()
                    .eq(EquipmentBase::getEquipmentCode, deviceCode)
                    .last("LIMIT 1"));
        } catch (Exception e) {
            log.warn("查询设备信息失败: deviceCode={}", deviceCode);
            return null;
        }
    }

    private static String buildRemarkMarker(String deviceCode, String warningCode) {
        return AUTO_PREFIX + deviceCode + "|" + warningCode;
    }

    private static String buildWarningName(String warningType, int level) {
        return warningType + "-接近阈值预警(" + EarlyWarningLevelUtil.getLevelName(level) + ")";
    }

    private static String buildContent(String deviceCode, String warningType, String warningCode,
                                       BigDecimal minValue, BigDecimal maxValue, BigDecimal actualValue,
                                       EarlyWarningLevelResult result, String extraRemark) {
        StringBuilder sb = new StringBuilder();
        sb.append("【系统自动预警】设备[").append(deviceCode).append("]");
        if (warningType != null) {
            sb.append(" ").append(warningType);
        }
        sb.append("(").append(warningCode).append(")");
        sb.append(" 当前值=").append(actualValue);
        sb.append("，阈值范围=[")
                .append(minValue != null ? minValue : "-")
                .append(", ")
                .append(maxValue != null ? maxValue : "-")
                .append("]");
        sb.append("，逼近侧=").append("UPPER".equals(result.getSide()) ? "上限" : "下限");
        sb.append("，逼近率=").append(result.getApproachRatio()).append("%");
        sb.append("，级别=").append(EarlyWarningLevelUtil.getLevelName(result.getLevel()));
        sb.append("。数据已接近阈值但尚未越限，请关注。");
        if (extraRemark != null && !extraRemark.isEmpty()) {
            sb.append(" 备注：").append(extraRemark);
        }
        return sb.toString();
    }

    private static String generateWarningNo() {
        String ts = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
        String random = String.format("%04d", new Random().nextInt(10000));
        return "YJ" + ts + random;
    }
}
