package com.kym.service.awoara.event.handle;

import com.kym.common.enums.FaultType;
import com.kym.entity.WashDevice;
import com.kym.entity.awoara.DeviceStateObject;
import com.kym.entity.awoara.MessageBody;
import com.kym.service.FaultNotificationService;
import com.kym.service.WashDeviceService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;

/**
 * 设备状态更新事件处理
 *
 * @author skyline
 */
@Slf4j
public class DeviceStateEventHandler implements AwoaraEventHandler<DeviceStateObject> {

    private final WashDeviceService washDeviceService;
    private final FaultNotificationService faultNotificationService;

    public DeviceStateEventHandler(WashDeviceService washDeviceService,
                                   FaultNotificationService faultNotificationService) {
        this.washDeviceService = washDeviceService;
        this.faultNotificationService = faultNotificationService;
    }

    @Override
    @Transactional
    public void handle(MessageBody<DeviceStateObject> message) {
        log.debug("DeviceStateEventHandler: {}", message);

        var topic = message.getTopic().split("/");
        var productKey = topic[1];
        var deviceName = topic[2];
        var deviceState = message.getPayload().getData().getDevice_state();

        // 读取更新前的状态用于对比
        var oldDevice = washDeviceService.lambdaQuery()
                .eq(WashDevice::getProductKey, productKey)
                .eq(WashDevice::getDeviceName, deviceName)
                .one();

        // 状态更新
        washDeviceService.lambdaUpdate()
                .set(WashDevice::getUptimeMs, deviceState.getUptime_ms())
                .set(WashDevice::getState, deviceState.getState())
                .set(WashDevice::getFsmState, deviceState.getFsm_state())
                .set(WashDevice::getHasWater, deviceState.getHas_water())
                .set(WashDevice::getHasFoam, deviceState.getHas_foam())
                .set(WashDevice::getTemperatureChip, deviceState.getTemperature_chip())
                .eq(WashDevice::getProductKey, productKey)
                .eq(WashDevice::getDeviceName, deviceName)
                .update();

        // 检测水和泡沫变化
        if (oldDevice != null) {
            detectWaterChange(oldDevice, deviceState.getHas_water(), deviceName);
            detectFoamChange(oldDevice, deviceState.getHas_foam(), deviceName);
        }
    }

    private void detectWaterChange(WashDevice oldDevice, String newHasWaterVal, String deviceName) {
        var stationId = oldDevice.getStationId();
        int newVal = parseResourceValue(newHasWaterVal);
        boolean oldHasWater = oldDevice.getHasWater() != null && oldDevice.getHasWater();
        boolean newHasWater = newVal == 1;

        if (oldHasWater && !newHasWater) {
            log.info("检测到缺水: stationId={}, deviceName={}", stationId, deviceName);
            faultNotificationService.handleResourceShortage(stationId, deviceName, FaultType.WATER_SHORTAGE.getCode());
        } else if (!oldHasWater && newHasWater) {
            log.info("检测到水恢复: stationId={}, deviceName={}", stationId, deviceName);
            faultNotificationService.handleResourceRecovery(stationId, deviceName, FaultType.WATER_SHORTAGE.getCode());
        }
    }

    private void detectFoamChange(WashDevice oldDevice, String newHasFoamVal, String deviceName) {
        var stationId = oldDevice.getStationId();
        int newVal = parseResourceValue(newHasFoamVal);
        boolean oldHasFoam = oldDevice.getHasFoam() != null && oldDevice.getHasFoam();
        boolean newHasFoam = newVal == 1;

        if (oldHasFoam && !newHasFoam) {
            log.info("检测到缺泡沫: stationId={}, deviceName={}", stationId, deviceName);
            faultNotificationService.handleResourceShortage(stationId, deviceName, FaultType.FOAM_SHORTAGE.getCode());
        } else if (!oldHasFoam && newHasFoam) {
            log.info("检测到泡沫恢复: stationId={}, deviceName={}", stationId, deviceName);
            faultNotificationService.handleResourceRecovery(stationId, deviceName, FaultType.FOAM_SHORTAGE.getCode());
        }
    }

    private int parseResourceValue(String val) {
        if (val == null) return -1;
        return Integer.parseInt(val);
    }
}
