package com.zksy.gas.utils;

import cn.hutool.core.lang.UUID;
import com.alibaba.fastjson.JSONObject;
import com.zksy.api.domain.WarningThreshold;
import com.zksy.api.service.WarningThresholdService;
import com.zksy.api.utils.SmsUtil;
import com.zksy.common.exception.InvalidMessageException;
import com.zksy.gas.domain.Enum.GasDeviceCodeEnum;
import com.zksy.gas.domain.Enum.GasWarningCodeEnum;
import com.zksy.gas.domain.GasMonitorData;
import com.zksy.gas.service.GasMonitorDataService;
import com.zksy.utils.DevicePhoneFetchUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.ReadTimeoutException;
import io.netty.util.ReferenceCountUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

@ChannelHandler.Sharable
@Slf4j
@Component
public class MessageHandler extends ChannelInboundHandlerAdapter {
	private static Logger logger = LoggerFactory.getLogger(MessageHandler.class);
	private final GasMonitorDataService service;
	@Autowired
	private WarningThresholdService warningThresholdService;
	@Autowired
	private SmsUtil smsUtil;
	@Autowired
	private DevicePhoneFetchUtil devicePhoneFetchUtil;
	@Autowired
	private AlarmUtil alarmUtil;

	@Autowired
	public MessageHandler(GasMonitorDataService firefightingPressureService) {
		this.service = firefightingPressureService;
	}

	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		super.channelActive(ctx);
		//sendDataToDevice(ctx);
	}

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg) {
		try {
			ByteBuf msgByteBuf = (ByteBuf) msg;
			if (msgByteBuf == null || !msgByteBuf.isReadable()) {
				logger.warn("接收到无效的消息");
				return;
			}
			int readable = msgByteBuf.readableBytes();
			byte[] msgBytes = new byte[readable];
			msgByteBuf.readBytes(msgBytes);
			logger.info("接收到 {} 字节的数据: {}, 来自: {}",
					readable, ProtocolUtils.bytesToHex(msgBytes), ctx.channel().remoteAddress());

			int checksumTotalLength = 2; // 末尾2字节校验码（如ED34）
			int bodyStartOffset = 16;    // 校验和07的主体起始索引
			int fullDataStartOffset = 3; // 校验和16的完整数据起始索引

			// 校验报文长度合法性
			if (readable < fullDataStartOffset + checksumTotalLength) {
				throw new InvalidMessageException("报文长度不足，无法完成校验");
			}

			int bodyEndOffset = msgBytes.length - checksumTotalLength; // 避开末尾2字节校验码
			int bodyLength = bodyEndOffset - bodyStartOffset;
			if (bodyLength <= 0) {
				throw new InvalidMessageException("主体数据长度无效，无法计算校验和07");
			}
			int checksum07 = DataCheckUtil.calcSumOnly(msgBytes, bodyStartOffset, bodyLength);

			int fullDataEndOffset = msgBytes.length - 1; // 包含倒数第二个字节
			int fullDataLength = fullDataEndOffset - fullDataStartOffset;
			if (fullDataLength <= 0) {
				throw new InvalidMessageException("完整数据长度无效，无法计算校验和16");
			}
			int checksum16 = DataCheckUtil.calcChecksum(msgBytes, fullDataStartOffset, fullDataLength);

			int calculatedChecksum = (checksum07 << 8) | checksum16;
			int receivedChecksum = ((msgBytes[msgBytes.length - 2] & 0xFF) << 8)
					| (msgBytes[msgBytes.length - 1] & 0xFF);

			// 打印调试信息，确认拼接结果
			logger.debug("校验和07（高8位，仅求和）: {}", Integer.toHexString(checksum07).toUpperCase());
			logger.debug("校验和16（低8位，FF-求和）: {}", Integer.toHexString(checksum16).toUpperCase());
			logger.debug("修改后拼接校验码: {}", Integer.toHexString(calculatedChecksum).toUpperCase());
			logger.debug("报文携带校验码: {}", Integer.toHexString(receivedChecksum).toUpperCase());

			if (calculatedChecksum != receivedChecksum) {
				throw new InvalidMessageException(
						String.format("数据校验失败：本地计算（07+16）=%04X（07=%02X, 16=%02X），报文携带=%04X",
								calculatedChecksum, checksum07, checksum16, receivedChecksum));
			}

			com.zksy.gas.domain.GasMonitorData resultData = DataParser.parseMessage(msgBytes);
			resultData.setId(java.util.UUID.randomUUID().toString());
			service.save(resultData);
			checkIfSmsAlertNeeded(resultData);
			logger.info("数据解析入库成功: {}", resultData);

		} catch (InvalidMessageException e) {
			logger.error("数据校验失败: {}", e.getMessage());
			ctx.writeAndFlush(Unpooled.copiedBuffer("数据校验失败".getBytes()));
		} catch (Exception e) {
			logger.error("数据解析/入库异常", e);
			ctx.writeAndFlush(Unpooled.copiedBuffer("数据处理异常".getBytes()));
		} finally {
			ReferenceCountUtil.release(msg);
		}
	}

	private String printHexBinary(byte[] bytes) {
		StringBuilder sb = new StringBuilder();
		for (byte b : bytes) {
			sb.append(String.format("%02X ", b));
		}
		System.out.println("Received raw data: " + sb.toString());
		logger.info("Received raw data: " + sb.toString());
		return sb.toString();
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
		if (cause instanceof ReadTimeoutException) {
			logger.info("来自" + ctx.channel().remoteAddress() + "的连接超时断开");
		} else {
			cause.printStackTrace();
			logger.info("来自" + ctx.channel().remoteAddress() + "的连接异常断开");
			ctx.close();
		}
	}

	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		ctx.flush();
	}

	@Override
	public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
		logger.info("来自" + ctx.channel().remoteAddress() + "的连接主动断开");
		ctx.fireChannelUnregistered();
	}

	// 主动向设备发送数据
	public void sendDataToDevice(ChannelHandlerContext ctx) {
		try {
			// 将字符串形式的十六进制数据转换为字节数组
			String hexData = "01 03 00 00 00 01 84 0A ";
			String[] hexArray = hexData.split(" ");
			byte[] dataBytes = new byte[hexArray.length];
			for (int i = 0; i < hexArray.length; i++) {
				dataBytes[i] = (byte) Integer.parseInt(hexArray[i], 16);
			}
			ByteBuf byteBuf = Unpooled.copiedBuffer(dataBytes);
			ctx.writeAndFlush(byteBuf);
			logger.info("已向设备发送数据: {}", printHexBinary(dataBytes));
		} catch (Exception e) {
			logger.error("发送数据失败: {}", e.getMessage());
		}
	}
	public void checkIfSmsAlertNeeded(GasMonitorData resultData){

		//用MAC地址作为设备的设备编号
		String deviceId = resultData.getMacAddress();
		String deviceName = "可燃气体设备";
		String deviceType = "flammable-gas";

		//获取温度阈值
		String deviceWarningCode = GasDeviceCodeEnum.FIREFIGHTING_DEVICE.getCode();
		GasWarningCodeEnum temTargetWarningType=GasWarningCodeEnum.TEMPERATRUE;
		String temWarningCode = temTargetWarningType.getCode();
		String temWarningMsg = temTargetWarningType.getName();
		Double temWarningValue = checkTemAndHum(deviceWarningCode, temWarningCode);
		//获取湿度阈值
		GasWarningCodeEnum humTargetWarningType=GasWarningCodeEnum.HUMIDITY;
		String humWarningCode = humTargetWarningType.getCode();
		String humWarningMsg = humTargetWarningType.getName();
		Double humWarningValue = checkTemAndHum(deviceWarningCode, humWarningCode);
		//获取气体浓度阈值
		GasWarningCodeEnum gasTargetWarningType=GasWarningCodeEnum.GASCONCENTRATION;
		String gasWarningCode = gasTargetWarningType.getCode();
		String gasWarningMsg = gasTargetWarningType.getName();
		Double gasWarningValue = checkTemAndHum(deviceWarningCode, gasWarningCode);

		//判断温度
		float temperature = resultData.getTemperature();
		boolean temperatureIsOverThreshold = temperature > temWarningValue;
		if(temperatureIsOverThreshold){
			sendMessage(deviceId,temWarningMsg,resultData.getLongitude(),resultData.getLatitude());
			alarmUtil.saveAlarm(deviceName, deviceId, deviceType,
					temWarningMsg, temWarningCode, BigDecimal.valueOf(temWarningValue),
					BigDecimal.valueOf(temperature), "可燃气体温度报警");
		}
		//判断湿度
		float humidity = resultData.getHumidity();
		boolean humidityIsOverThreshold=humidity>humWarningValue;
		if(humidityIsOverThreshold){
			sendMessage(deviceId,humWarningMsg,resultData.getLongitude(),resultData.getLatitude());
			alarmUtil.saveAlarm(deviceName, deviceId, deviceType,
					humWarningMsg, humWarningCode, BigDecimal.valueOf(humWarningValue),
					BigDecimal.valueOf(humidity), "可燃气体湿度报警");
		}
		//判断气体浓度
		BigDecimal gasConcentration = resultData.getGasConcentration();
		float actualGasConcentration=gasConcentration.floatValue();
		boolean concentrationIsOverThreshold=actualGasConcentration>gasWarningValue;
		if(concentrationIsOverThreshold){
			sendMessage(deviceId,gasWarningMsg,resultData.getLongitude(),resultData.getLatitude());
			alarmUtil.saveAlarm(deviceName, deviceId, deviceType,
					gasWarningMsg, gasWarningCode, BigDecimal.valueOf(gasWarningValue),
					gasConcentration, "可燃气体浓度报警");
		}
		//获取到的数据逐一进行判断
		Map<String, Boolean> alarmBits = resultData.parseAlarmBits();
		if(alarmBits.get("unknownAlarm")){
			sendMessage(deviceId,"未知报警",resultData.getLongitude(),resultData.getLatitude());
			alarmUtil.saveAlarm(deviceName, deviceId, deviceType,
					"未知报警", "WARN-UNKNOWN", null,
					null, "可燃气体未知报警");
		}
		if(alarmBits.get("highAlarm")){
			sendMessage(deviceId,"高报警",resultData.getLongitude(),resultData.getLatitude());
			alarmUtil.saveAlarm(deviceName, deviceId, deviceType,
					"高报警", "WARN-HIGH", null,
					null, "可燃气体高报警");
		}
		if(alarmBits.get("overRange")){
			sendMessage(deviceId,"超量程",resultData.getLongitude(),resultData.getLatitude());
			alarmUtil.saveAlarm(deviceName, deviceId, deviceType,
					"超量程", "WARN-OVER-RANGE", null,
					null, "可燃气体超量程报警");
		}
		if(alarmBits.get("calibrationCycle")){
			sendMessage(deviceId,"标定周期",resultData.getLongitude(),resultData.getLatitude());
			alarmUtil.saveAlarm(deviceName, deviceId, deviceType,
					"标定周期", "WARN-CALIBRATION-CYCLE", null,
					null, "可燃气体标定周期报警");
		}
		if(alarmBits.get("overLife")){
			sendMessage(deviceId,"超寿命",resultData.getLongitude(),resultData.getLatitude());
			alarmUtil.saveAlarm(deviceName, deviceId, deviceType,
					"超寿命", "WARN-OVER-LIFE", null,
					null, "可燃气体超寿命报警");
		}
		if(alarmBits.get("fallAlarm")){
			sendMessage(deviceId,"跌倒报警",resultData.getLongitude(),resultData.getLatitude());
			alarmUtil.saveAlarm(deviceName, deviceId, deviceType,
					"跌倒报警", "WARN-FALL", null,
					null, "可燃气体跌倒报警");
		}
		if(alarmBits.get("undervoltage")){
			sendMessage(deviceId,"欠压报警",resultData.getLongitude(),resultData.getLatitude());
			alarmUtil.saveAlarm(deviceName, deviceId, deviceType,
					"欠压报警", "WARN-UNDERVOLTAGE", null,
					null, "可燃气体欠压报警");
		}
		if(alarmBits.get("rangeAlarm")){
			sendMessage(deviceId,"区间报警",resultData.getLongitude(),resultData.getLatitude());
			alarmUtil.saveAlarm(deviceName, deviceId, deviceType,
					"区间报警", "WARN-RANGE", null,
					null, "可燃气体区间报警");
		}
		if(alarmBits.get("keyAlarm")){
			sendMessage(deviceId,"按键报警",resultData.getLongitude(),resultData.getLatitude());
			alarmUtil.saveAlarm(deviceName, deviceId, deviceType,
					"按键报警", "WARN-KEY", null,
					null, "可燃气体按键报警");
		}
		if(alarmBits.get("vibrationAlarm")){
			sendMessage(deviceId,"震动报警",resultData.getLongitude(),resultData.getLatitude());
			alarmUtil.saveAlarm(deviceName, deviceId, deviceType,
					"震动报警", "WARN-VIBRATION", null,
					null, "可燃气体震动报警");
		}
		if(alarmBits.get("waterLevelAlarm")){
			sendMessage(deviceId,"水位报警",resultData.getLongitude(),resultData.getLatitude());
			alarmUtil.saveAlarm(deviceName, deviceId, deviceType,
					"水位报警", "WARN-WATER-LEVEL", null,
					null, "可燃气体水位报警");
		}
		if(alarmBits.get("powerOffAlarm")){
			sendMessage(deviceId,"断电报警",resultData.getLongitude(),resultData.getLatitude());
			alarmUtil.saveAlarm(deviceName, deviceId, deviceType,
					"断电报警", "WARN-POWER-OFF", null,
					null, "可燃气体断电报警");
		}
		if(alarmBits.get("sensorFault")){
			sendMessage(deviceId,"传感器故障",resultData.getLongitude(),resultData.getLatitude());
			alarmUtil.saveAlarm(deviceName, deviceId, deviceType,
					"传感器故障", "WARN-SENSOR-FAULT", null,
					null, "可燃气体传感器故障");
		}
		if(alarmBits.get("overHumidity")){
			sendMessage(deviceId,"超湿报警",resultData.getLongitude(),resultData.getLatitude());
			alarmUtil.saveAlarm(deviceName, deviceId, deviceType,
					"超湿报警", "WARN-OVER-HUMIDITY", null,
					null, "可燃气体超湿报警");
		}
		if(alarmBits.get("overTemperature")){
			sendMessage(deviceId,"超温报警",resultData.getLongitude(),resultData.getLatitude());
			alarmUtil.saveAlarm(deviceName, deviceId, deviceType,
					"超温报警", "WARN-OVER-TEMPERATURE", null,
					null, "可燃气体超温报警");
		}
		if(alarmBits.get("systemFault")){
			sendMessage(deviceId,"系统故障",resultData.getLongitude(),resultData.getLatitude());
			alarmUtil.saveAlarm(deviceName, deviceId, deviceType,
					"系统故障", "WARN-SYSTEM-FAULT", null,
					null, "可燃气体系统故障");
		}
	}
	public Double checkTemAndHum(String deviceWarningCode,String warningCode){
		//获取数据库中的阈值
		WarningThreshold threshold = warningThresholdService.getWarningThresholdByDeviceAndCode(deviceWarningCode, warningCode);
		return threshold.getWarningValue();
	}
	//构造发送短信参数&&发送短信
	public void sendMessage(String deviceNo, String alarmType, BigDecimal lng, BigDecimal lat){
		// 构造短信参数
		JSONObject params = new JSONObject();
		params.put("deviceNo", deviceNo);
		params.put("alarmType", alarmType);
		// 经纬度处理（位置）
		params.put("location", String.format("经纬度：%.6f,%.8f", lng, lat));
		List<String> phoneListByDeviceId = devicePhoneFetchUtil.getPhoneListByDeviceId(deviceNo);
		Map<String, Boolean> sendResults = smsUtil.sendBatchSms(phoneListByDeviceId, params.toJSONString());
		log.info("发送信息完成");
	}
}