package com.zksy.environment.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zksy.environment.domain.po.PictureMessage;
import com.zksy.environment.mapper.PictureMessageMapper;
import com.zksy.environment.service.PictureMessageService;
import com.zksy.environment.utils.DateTimeUtil;
import com.zksy.environment.utils.HexToImageConverter;
import com.zksy.service.MinioFileStorageService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.time.LocalDateTime;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
@Service
public class PictureMessageServiceImpl extends ServiceImpl<PictureMessageMapper, PictureMessage>
        implements PictureMessageService {

    // 每个传输任务独立存储数据段，用 ThreadLocal 隔离线程状态
    private final ThreadLocal<List<String>> allDataSegmentsThreadLocal =
            ThreadLocal.withInitial(ArrayList::new);

    // 新增：使用 ThreadLocal 存储 tempMap，确保同一个图片传输使用同一个 map
    private final ThreadLocal<Map<String, String>> tempMapThreadLocal =
            ThreadLocal.withInitial(HashMap::new);

    @Autowired
    private MinioFileStorageService minioFileStorageService;

    @Override
    public boolean savePictureMessage(String oldDataStr, String dataStr) {
        boolean flag = false;
        List<String> allDataSegments = allDataSegmentsThreadLocal.get();
        Map<String, String> tempMap = tempMapThreadLocal.get(); // 从 ThreadLocal 获取 tempMap

        try {
            PictureMessage pictureMessage = new PictureMessage();
            if (dataStr.length() < 8) {
                log.warn("数据长度不足，无法解析包序号: {}", dataStr);
                clearThreadLocal(allDataSegments);
                return false;
            }

            // 解析固定头部：总包数、包序号
            String totalHex = dataStr.substring(2, 5);
            int totalPackets;
            try {
                totalPackets = Integer.parseUnsignedInt(totalHex, 16);
                if (totalPackets <= 0) {
                    log.error("总包数不能为 0，hex: {}", totalHex);
                    clearThreadLocal(allDataSegments);
                    return false;
                }

                // 根据总包数初始化数据段列表
                if (allDataSegments.isEmpty()) {
                    allDataSegments = new ArrayList<>(Collections.nCopies(totalPackets, ""));
                    allDataSegmentsThreadLocal.set(allDataSegments);
                }
            } catch (Exception e) {
                log.error("总包数解析失败，hex: {}", totalHex, e);
                clearThreadLocal(allDataSegments);
                return false;
            }

            String packageNumberHex = dataStr.substring(5, 8);
            int packageNumber;
            try {
                packageNumber = Integer.parseUnsignedInt(packageNumberHex, 16);
            } catch (NumberFormatException e) {
                log.error("包序号解析失败，hex: {}", packageNumberHex, e);
                clearThreadLocal(allDataSegments);
                return false;
            }

            // 提取当前包的数据段
            String segment;
            if (packageNumber == 1) {
                // 首包：清空 tempMap 并解析额外信息（测站地址、时间等）
                tempMap.clear();

                String dataTime = dataStr.substring(12, 24);
                LocalDateTime sendingMessageTime = DateTimeUtil.parseDateTime("20" + dataTime);
                tempMap.put("sendingMessageTime", sendingMessageTime.toString());

                // 改进测站地址解析逻辑
                String stationAddressPattern = "F1F1([0-9A-F]{10})";
                Pattern pattern = Pattern.compile(stationAddressPattern, Pattern.CASE_INSENSITIVE);
                Matcher matcher = pattern.matcher(dataStr);
                if (matcher.find()) {
                    tempMap.put("measuringStationAddress", matcher.group(1));
                }

                // 改进测站类型和观测时间解析逻辑
                String[] f0F0Parts = dataStr.split("F0F0", Pattern.CASE_INSENSITIVE);
                if (f0F0Parts.length > 1) {
                    // 测站类型：F0F0之前的最后两个字符
                    String firstPart = f0F0Parts[0];
                    if (firstPart.length() >= 2) {
                        tempMap.put("measuringStationType", firstPart.substring(firstPart.length() - 2));
                    }

                    // 观测时间：F0F0之后的前10个字符（YYYYMMDDHH格式）
                    String secondPart = f0F0Parts[1];
                    if (secondPart.length() >= 10) {
                        String observeTimeStr = "20" + secondPart.substring(0, 10) + "00";
                        LocalDateTime observeTime = DateTimeUtil.parseDateTime(observeTimeStr);
                        tempMap.put("observeTime", observeTime.toString());
                    }
                }

                // 提取首包数据段（基于 "F3F3" 标识）
                int dataStartIndex = dataStr.indexOf("F3F3");
                segment = (dataStartIndex != -1)
                        ? dataStr.substring(dataStartIndex + "F3F3".length())
                        : "";
            } else {
                // 分包：直接截取数据段
                segment = dataStr.substring(8);
            }

            int index = packageNumber - 1;
            if (index < 0 || index >= totalPackets) {
                log.warn("包序号越界，总包数: {}, 包序号: {}", totalPackets, packageNumber);
                clearThreadLocal(allDataSegments);
                return false;
            }
            allDataSegments.set(index, segment);

            // 检查是否收全所有包
            if (totalPackets == index + 1) {
                // 拼接完整数据
                StringBuilder completeDataBuilder = new StringBuilder();
                for (String seg : allDataSegments) {
                    completeDataBuilder.append(Objects.toString(seg, ""));
                }
                String completeImageData = completeDataBuilder.toString();
                log.info("完整图片数据长度: {}", completeImageData.length());

                // 转换为图片并上传
                File image = HexToImageConverter.hexStringToImage(completeImageData, "output.png");
                if (image != null) {
                    String filePath = minioFileStorageService.uploadFileByFile(image, "environment-image");
                    pictureMessage.setMessage(filePath);

                    // 填充对象字段
                    pictureMessage.setId(UUID.randomUUID().toString().replace("-", ""));
                    pictureMessage.setCreateTime(LocalDateTime.now());

                    // 从tempMap获取值并设置，增加空值检查
                    if (tempMap.get("sendingMessageTime") != null) {
                        pictureMessage.setSendingMessageTime(LocalDateTime.parse(tempMap.get("sendingMessageTime")));
                    }
                    if (tempMap.get("measuringStationAddress") != null) {
                        pictureMessage.setMeasuringStationAddress(tempMap.get("measuringStationAddress"));
                    }
                    if (tempMap.get("measuringStationType") != null) {
                        pictureMessage.setMeasuringStationType(tempMap.get("measuringStationType"));
                    }
                    if (tempMap.get("observeTime") != null) {
                        pictureMessage.setObserveTime(LocalDateTime.parse(tempMap.get("observeTime")));
                    }

                    // 保存到数据库
                    flag = super.save(pictureMessage);
                    if (flag) {
                        log.info("图片数据保存成功，文件路径: {}", filePath);
                    } else {
                        log.error("数据库保存失败");
                    }
                }

                // 清理状态，为下次传输做准备
                clearThreadLocal(allDataSegments);
                tempMapThreadLocal.remove(); // 移除 tempMap
            }
            return flag;
        } catch (Exception e) {
            log.error("图片数据解析失败，原始数据: {}", oldDataStr, e);
            clearThreadLocal(allDataSegments);
            tempMapThreadLocal.remove(); // 异常情况下也需要清理
        }
        return flag;
    }

    /**
     * 清理 ThreadLocal 中的数据，避免内存泄漏和状态污染
     */
    private void clearThreadLocal(List<String> list) {
        list.clear();
        allDataSegmentsThreadLocal.remove();
    }
}