package com.shzg.project.worn.sensor.mqtt.handler;

import com.alibaba.fastjson2.JSONObject;
import com.shzg.project.system.domain.SysDept;
import com.shzg.project.system.service.ISysDeptService;
import com.shzg.project.worn.domain.*;
import com.shzg.project.worn.service.*;
import com.shzg.project.worn.unit.DeviceStatusUtil;
import com.shzg.project.worn.websocket.manager.WebSocketSessionManager;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Date;

/**
 * 综合环境传感器 Handler
 */
@Slf4j
@Component
public class EnvSensorHandler {

    @Autowired
    private IMqttSensorDataService sensorDataService;

    @Autowired
    private IMqttSensorEventService eventService;

    @Autowired
    private IMqttSensorThresholdService thresholdService;

    @Autowired
    private WebSocketSessionManager sessionManager;

    @Autowired
    private ISysDeptService deptService;

    @Autowired
    private IDeviceStatusService deviceStatusService;

    @Autowired
    private DeviceStatusUtil deviceStatusUtil;

    public void handle(MqttSensorDevice device, String topic, String payload) {

        if (device == null) {
            log.error("[ENV] device为空");
            return;
        }

        if (device.getDeptId() == null) {
            log.error("[ENV] device未绑定deptId，拒绝处理 deviceId={}", device.getId());
            return;
        }

        JSONObject json = parseJson(payload);
        if (json == null) return;

        SensorValue v = buildValue(json);
        if (v.isEmpty()) return;

        TopicInfo topicInfo = parseTopic(topic);

        // =========================
        // 1️⃣ 入库
        // =========================
        saveData(device, topic, payload, topicInfo, v);

        // =========================
        // 2️⃣ 恢复在线
        // =========================
        deviceStatusUtil.handleOnline(device);

        // =========================
        // 3️⃣ 推送（周期数据必须推）
        // =========================
        pushWebSocket(device, v);

        // =========================
        // 4️⃣ 事件检测（带去重）
        // =========================
        handleEvent(device, v);
    }

    // ================== WebSocket ==================

    private void pushWebSocket(MqttSensorDevice device, SensorValue v) {

        try {
            JSONObject msg = new JSONObject();

            SysDept dept = deptService.selectDeptById(device.getDeptId());

            msg.put("type", "env");
            msg.put("deviceId", device.getId());
            msg.put("deviceName", device.getDeviceName());
            msg.put("deptId", device.getDeptId());
            msg.put("deptName", dept == null ? null : dept.getDeptName());

            msg.put("temperature", v.temperature);
            msg.put("humidity", v.humidity);
            msg.put("nh3", v.nh3);
            msg.put("h2s", v.h2s);
            msg.put("battery", v.battery);

            msg.put("time", System.currentTimeMillis());

            sessionManager.sendToDept(device.getDeptId(), msg.toJSONString());

        } catch (Exception e) {
            log.error("[ENV] WebSocket推送失败", e);
        }
    }

    // ================== 事件处理 ==================

    private void handleEvent(MqttSensorDevice device, SensorValue v) {

        check(device, "temperature", v.temperature, "温度");
        check(device, "humidity", v.humidity, "湿度");
        check(device, "nh3", v.nh3, "氨气");
        check(device, "h2s", v.h2s, "硫化氢");

        if (v.battery != null) {
            MqttSensorThreshold t = thresholdService.getThreshold(
                    device.getId(), device.getDeptId(), "battery");

            if (t != null) {
                String status = calcStatus(new BigDecimal(v.battery), t);
                changeStatus(device, "battery", status, "电量:" + v.battery + "%");
            }
        }
    }

    private void check(MqttSensorDevice device, String metric, BigDecimal value, String name) {

        if (value == null) return;

        MqttSensorThreshold t = thresholdService.getThreshold(
                device.getId(), device.getDeptId(), metric);

        if (t == null) return;

        String status = calcStatus(value, t);

        changeStatus(device, metric, status, name + ":" + value);
    }

    private String calcStatus(BigDecimal value, MqttSensorThreshold t) {

        if (t.getAlarmMax() != null && value.compareTo(t.getAlarmMax()) > 0) return "alarm";
        if (t.getAlarmMin() != null && value.compareTo(t.getAlarmMin()) < 0) return "alarm";
        if (t.getWarnMax() != null && value.compareTo(t.getWarnMax()) > 0) return "warning";
        if (t.getWarnMin() != null && value.compareTo(t.getWarnMin()) < 0) return "warning";

        return "normal";
    }

    private void changeStatus(MqttSensorDevice device,
                              String metric,
                              String newStatus,
                              String desc) {

        boolean changed = deviceStatusService.isStatusChanged(
                device.getId(),
                metric,
                newStatus
        );

        if (!changed) return;

        if ("alarm".equals(newStatus)) {
            triggerEvent(device, metric + "_alarm", "HIGH", desc);
        } else if ("warning".equals(newStatus)) {
            triggerEvent(device, metric + "_warning", "MEDIUM", desc);
        } else if ("normal".equals(newStatus)) {
            triggerEvent(device, metric + "_recovery", "LOW", desc + " 正常");
        }
    }

    private void triggerEvent(MqttSensorDevice device,
                              String type,
                              String level,
                              String desc) {

        MqttSensorEvent event = new MqttSensorEvent();

        event.setDeviceId(device.getId());
        event.setDeptId(device.getDeptId());
        event.setEventType(type);
        event.setLevel(level);
        event.setEventDesc(desc);

        event.setStatus("0");
        event.setIsDelete("0");
        event.setCreateTime(new Date());

        eventService.insertMqttSensorEvent(event);
    }

    // ================== 入库 ==================

    private void saveData(MqttSensorDevice device,
                          String topic,
                          String payload,
                          TopicInfo topicInfo,
                          SensorValue v) {

        MqttSensorData data = new MqttSensorData();

        data.setDeviceId(device.getId());
        data.setDeptId(device.getDeptId());

        data.setTopic(topic);
        data.setProject(topicInfo.project);
        data.setWarehouse(topicInfo.warehouse);

        data.setPayload(payload);
        data.setDataJson(payload);

        data.setTemperature(v.temperature);
        data.setHumidity(v.humidity);
        data.setNh3(v.nh3);
        data.setH2s(v.h2s);
        data.setBattery(v.battery == null ? null : Long.valueOf(v.battery));

        data.setCreateTime(new Date());
        data.setIsDelete("0");

        sensorDataService.insertMqttSensorData(data);
    }

    // ================== 工具 ==================

    private JSONObject parseJson(String payload) {
        try {
            return JSONObject.parseObject(payload);
        } catch (Exception e) {
            log.error("[ENV] JSON解析失败 payload={}", payload, e);
            return null;
        }
    }

    private SensorValue buildValue(JSONObject json) {
        SensorValue v = new SensorValue();
        v.temperature = json.getBigDecimal("temperature");
        v.humidity = json.getBigDecimal("humidity");
        v.nh3 = json.getBigDecimal("nh3");
        v.h2s = json.getBigDecimal("h2s");
        v.battery = json.getInteger("battery");
        return v;
    }

    private TopicInfo parseTopic(String topic) {
        TopicInfo info = new TopicInfo();
        try {
            String[] arr = topic.split("/");
            info.project = arr.length > 1 ? arr[1] : "";
            info.warehouse = arr.length > 2 ? arr[2] : "";
        } catch (Exception e) {
            log.warn("[ENV] topic解析失败 topic={}", topic);
        }
        return info;
    }

    private static class SensorValue {
        BigDecimal temperature;
        BigDecimal humidity;
        BigDecimal nh3;
        BigDecimal h2s;
        Integer battery;

        boolean isEmpty() {
            return temperature == null && humidity == null && nh3 == null && h2s == null;
        }
    }

    private static class TopicInfo {
        String project;
        String warehouse;
    }
}