package com.zksy.manhole.utils;

import com.alibaba.fastjson.JSONObject;
import com.zksy.api.utils.AlarmLevelUtil;
import com.zksy.api.utils.SmsUtil;
import com.zksy.common.utils.AjaxResult;
import com.zksy.utils.DevicePhoneFetchUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class AlarmUtil {

    private static final Logger log = LoggerFactory.getLogger(AlarmUtil.class);

    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private SmsUtil smsUtil;
    @Autowired
    private DevicePhoneFetchUtil devicePhoneFetchUtil;

    @Value("${alarm.api.url:http://zk-api-service/alarmData/save}")
    private String alarmApiUrl;

    @Value("${device.status.api.url:http://zk-api-service/equipmentStatus/updateAlarmStatus}")
    private String deviceStatusApiUrl;

    public void checkAndSaveAlarm(String deviceCode,
                                    String warningType, String warningCode, Double minValue, Double maxValue,
                                    BigDecimal actualValue, String remark) {
        if (actualValue == null) {
            return;
        }

        boolean shouldAlarm = false;
        if (minValue != null && actualValue.doubleValue() <= minValue) {
            shouldAlarm = true;
        }
        if (maxValue != null && actualValue.doubleValue() >= maxValue) {
            shouldAlarm = true;
        }

        if (shouldAlarm) {
            saveAlarm(deviceCode, warningType, warningCode,
                    minValue != null ? BigDecimal.valueOf(minValue) : null,
                    maxValue != null ? BigDecimal.valueOf(maxValue) : null,
                    actualValue, remark);
        }
    }

    public int saveAlarm(String deviceCode,
                           String warningType, String warningCode, BigDecimal minValue, BigDecimal maxValue,
                           BigDecimal actualValue, String remark) {
        int alarmLevel = 4;
        try {
            Map<String, Object> alarmData = new HashMap<>();
            alarmData.put("deviceCode", deviceCode);
            alarmData.put("warningType", warningType);
            alarmData.put("warningCode", warningCode);
            alarmData.put("minValue", minValue);
            alarmData.put("maxValue", maxValue);
            alarmData.put("actualValue", actualValue);

            alarmLevel = AlarmLevelUtil.calculateLevel(actualValue, minValue, maxValue);
            BigDecimal deviationRatio = AlarmLevelUtil.calculateDeviationRatio(actualValue, minValue, maxValue);
            alarmData.put("alarmLevel", alarmLevel);
            alarmData.put("deviationRatio", deviationRatio);

            alarmData.put("alarmStatus", 0);
            alarmData.put("alarmTime", LocalDateTime.now().toString());
            alarmData.put("remark", remark);

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<Map<String, Object>> request = new HttpEntity<>(alarmData, headers);

            restTemplate.postForObject(alarmApiUrl, request, AjaxResult.class);

            if (alarmLevel == 1) {
                log.warn("【1级紧急告警】deviceCode={}, warningCode={}, deviationRatio={}%",
                        deviceCode, warningCode, deviationRatio);
                sendAlarmSms(deviceCode, warningType, actualValue, minValue, maxValue);
            }
            log.info("告警数据入库成功: deviceCode={}, warningCode={}, level={}级", deviceCode, warningCode, alarmLevel);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return alarmLevel;
    }

    /**
     * 保存告警数据（指定告警等级，适用于状态型告警）
     * @param deviceCode 设备编码
     * @param warningType 告警类型
     * @param warningCode 告警编码
     * @param actualValue 实际值（可为null）
     * @param alarmLevel 告警等级（1-4）
     * @param remark 备注
     * @return 告警等级
     */
    public int saveAlarmWithLevel(String deviceCode,
                                   String warningType, String warningCode,
                                   BigDecimal actualValue, int alarmLevel, String remark) {
        try {
            Map<String, Object> alarmData = new HashMap<>();
            alarmData.put("deviceCode", deviceCode);
            alarmData.put("warningType", warningType);
            alarmData.put("warningCode", warningCode);
            alarmData.put("actualValue", actualValue);
            alarmData.put("alarmLevel", alarmLevel);
            alarmData.put("deviationRatio", BigDecimal.ZERO);
            alarmData.put("alarmStatus", 0);
            alarmData.put("alarmTime", LocalDateTime.now().toString());
            alarmData.put("remark", remark);

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<Map<String, Object>> request = new HttpEntity<>(alarmData, headers);

            restTemplate.postForObject(alarmApiUrl, request, AjaxResult.class);

            if (alarmLevel == 1) {
                log.warn("【1级紧急告警】deviceCode={}, warningCode={}", deviceCode, warningCode);
                sendAlarmSms(deviceCode, warningType, actualValue, null, null);
            }
            log.info("告警数据入库成功: deviceCode={}, warningCode={}, level={}级", deviceCode, warningCode, alarmLevel);
        } catch (Exception e) {
            log.error("保存告警数据异常: {}", e.getMessage());
        }
        return alarmLevel;
    }

    private void sendAlarmSms(String deviceCode, String warningType, BigDecimal actualValue,
                              BigDecimal minValue, BigDecimal maxValue) {
        try {
            List<String> phoneList = devicePhoneFetchUtil.getPhoneListByDeviceId(deviceCode);
            if (phoneList == null || phoneList.isEmpty()) {
                log.warn("报警短信发送失败：未找到设备{}的联系人手机号", deviceCode);
                return;
            }
            JSONObject params = new JSONObject();
            params.put("deviceNo", deviceCode);
            params.put("alarmType", warningType);
            params.put("location", "当前值：" + actualValue + "，正常范围：" + minValue + "~" + maxValue);

            Map<String, Boolean> result = smsUtil.sendBatchSms(phoneList, params.toJSONString());
            long successCount = result.values().stream().filter(Boolean::booleanValue).count();
            log.info("1级告警短信发送完成，成功{}条，失败{}条", successCount, phoneList.size() - successCount);
        } catch (Exception e) {
            log.error("发送报警短信异常: {}", e.getMessage());
        }
    }

    /**
     * 更新设备报警状态
     * @param deviceCode 设备编码
     * @param alarmStatus 报警状态：0-正常，1-报警
     */
    public void updateDeviceAlarmStatus(String deviceCode, int alarmStatus) {
        try {
            Map<String, Object> params = new HashMap<>();
            params.put("deviceCode", deviceCode);
            params.put("alarmStatus", alarmStatus);

            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<Map<String, Object>> request = new HttpEntity<>(params, headers);

            restTemplate.postForObject(deviceStatusApiUrl, request, Map.class);
            log.info("设备报警状态更新成功: deviceCode={}, alarmStatus={}", deviceCode, alarmStatus);
        } catch (Exception e) {
            log.error("更新设备报警状态失败: deviceCode={}, alarmStatus={}", deviceCode, alarmStatus, e);
        }
    }
}
