package com.zksy.environment.utils;

import com.zksy.environment.service.PictureMessageService;
import com.zksy.environment.service.StationHourService;
import io.netty.buffer.ByteBuf;
import io.netty.util.internal.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;

/**
 * @Description
 * @Date 2021- 06-01-下午 14:37
 * @auther Javen
 */
@Service
@Slf4j
@Scope(SCOPE_PROTOTYPE)
public class MonitorDatasynch {
    @Autowired
    private StationHourService stationHourService;
    @Autowired
    private PictureMessageService pictureMessageService;

    private final List<String> data1List = new ArrayList<>();
    private final Object lock = new Object();
    private AtomicBoolean isWaitingForNextStart = new AtomicBoolean(false);
    private int maxBufferSize = 10; // 最大缓冲数据条数，防止内存溢出

    /**
     * 获取水质同步数据，数据有效性校验，解析
     */
    public String pushMonitorData(ByteBuf dataBuf) {
        String response = null;
        try {
            if (dataBuf.isReadable()) {
                // 读取并转换 ByteBuf 中的数据为16进制字符串
                byte[] dataByte = new byte[dataBuf.readableBytes()];
                dataBuf.readBytes(dataByte);
                String oldDataStr = HexToImageConverter.bytesToHex(dataByte);

                // 获取检验码数据
                String codeStr = oldDataStr.substring(0, oldDataStr.length() - 4);
                // 获取数据CRC16检验码
                String code = oldDataStr.substring(oldDataStr.length() - 4);

                // 通过数据生成CRC16校验码
                String nowCode = DataCheckUtil.getCRC16Result(codeStr);

                // 先将两个字符串转换为相同的大小写形式（默认是小写）
                if (code.equals(nowCode)) {
                    // 校验通过，正常处理数据
                    processValidData(oldDataStr);
                } else {
                    // 校验不通过，处理图片数据的拼接
                    handleInvalidData(oldDataStr);
                }
            } else {
                log.info("==========数据长度格式不正确==========");
            }
        } catch (Exception e) {
            log.error("处理数据异常", e);
        }
        return response;
    }

    /**
     * 处理校验通过的数据
     */
    private void processValidData(String oldDataStr) {
        boolean flag = false;
        // dataType == "32" 遥测站定时报，"33" 遥测站加时报，"34" 遥测站小时报,"36" 查询/报送 JPG 图片信息
        // 获取报文特征
        String dataType = oldDataStr.substring(20, 22);

        if (!"2F".equals(dataType)) {
            if ("36".equals(dataType)) {
                // 获取数据正文
                String dataStr = oldDataStr.substring(26, oldDataStr.length() - 6);
                flag = pictureMessageService.savePictureMessage(oldDataStr, dataStr);
                // 清除data1List
                synchronized (lock) {
                    data1List.clear();
                    isWaitingForNextStart.set(false);
                }
                if (flag) {
                    log.info("新增成功", oldDataStr);
                }
            } else {
                // 获取数据正文
                String dataStr = oldDataStr.substring(32, oldDataStr.length() - 6);
                flag = stationHourService.saveStationHour(oldDataStr, dataStr);
                if (flag) {
                    log.info("新增成功", oldDataStr);
                } else {
                    log.info("新增失败", oldDataStr);
                }
            }
        } else {
            log.info("收到2f数据========", oldDataStr);
        }
    }

    /**
     * 处理校验不通过的数据
     */
    private void handleInvalidData(String oldDataStr) {
        // 检查是否是新的数据包开始
        String startCharacter = oldDataStr.substring(0, 4);
        String endCharacter = oldDataStr.substring(oldDataStr.length() - 2);

        synchronized (lock) {
            // 如果检测到新的数据包开始，且之前正在等待拼接
            if ("7E7E".equals(startCharacter) && isWaitingForNextStart.get()) {
                // 尝试处理已缓存的数据
                processBufferedData();
                // 重置标志
                isWaitingForNextStart.set(false);
                data1List.clear();
            }

            // 如果是dataType=36的第一条数据且校验不通过，或者正在等待拼接
            String dataType = oldDataStr.substring(20, 22);
            if ("36".equals(dataType) || isWaitingForNextStart.get()) {
                // 将数据添加到缓冲区
                data1List.add(oldDataStr);
                isWaitingForNextStart.set(true);

                // 限制缓冲区大小，防止内存溢出
                if (data1List.size() > maxBufferSize) {
                    log.warn("缓冲区数据过多，移除最早的数据");
                    data1List.remove(0);
                }

                // 尝试拼接并校验
                if (tryToProcessBufferedData()) {
                    return; // 成功处理，返回
                }

                // 如果检测到数据包结束但仍未通过校验
                if ("17".equals(endCharacter) && data1List.size() > 1) {
                    log.error("图片数据拼接后校验失败，数据可能损坏");
                    data1List.clear();
                    isWaitingForNextStart.set(false);
                }
            }
        }
    }

    /**
     * 尝试处理已缓存的数据
     */
    private boolean tryToProcessBufferedData() {
        if (data1List.isEmpty()) {
            return false;
        }

        StringBuilder dataBuilder = new StringBuilder();
        for (String data : data1List) {
            dataBuilder.append(data);
        }

        String combinedData = dataBuilder.toString();
        if (combinedData.length() <= 6) {
            return false;
        }

        // 校验拼接后的数据
        String codeStr = combinedData.substring(0, combinedData.length() - 4);
        String code = combinedData.substring(combinedData.length() - 4);
        String nowCode = DataCheckUtil.getCRC16Result(codeStr);

        if (code.equalsIgnoreCase(nowCode)) {
            String dataType = combinedData.substring(20, 22);
            if ("36".equals(dataType)) {
                String dataStr = combinedData.substring(26, combinedData.length() - 6);
                boolean saved = pictureMessageService.savePictureMessage(combinedData, dataStr);
                if (saved) {
                    log.info("图片数据拼接成功并保存");
                    data1List.clear();
                    isWaitingForNextStart.set(false);
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 处理已缓存的数据（当检测到新的数据包开始时调用）
     */
    private void processBufferedData() {
        if (!tryToProcessBufferedData() && !data1List.isEmpty()) {
            log.error("读取到下一条7E7E之前，缓存的图片数据一直未能通过校验，校验失败");
            data1List.clear();
        }
    }
}
