/**
 * @file GroundReceiver.cpp
 * @brief SkyLink Qt 地面站 - UDP 接收和数据重组实现
 * 
 * @author flowzl
 * @date 2026-01-19
 */

#include "GroundReceiver.h"
#include <QTimer>
#include <QHostAddress>
#include <QDateTime>
#include <QDebug>
#include <QByteArray>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>

GroundReceiver::GroundReceiver(QObject* parent, uint16_t port)
    : QObject(parent), listen_port_(port), last_complete_frame_id_(0) {
    
    // 创建 UDP 套接字
    udp_socket_ = std::make_unique<QUdpSocket>(this);
    
    // 连接信号
    connect(udp_socket_.get(), &QUdpSocket::readyRead,
            this, &GroundReceiver::on_udp_read_ready);
    
    // 定时器用于清理超时帧
    QTimer* cleanup_timer = new QTimer(this);
    connect(cleanup_timer, &QTimer::timeout,
            this, &GroundReceiver::on_cleanup_timeout);
    cleanup_timer->start(1000);  // 每秒清理一次
    
    stats_.last_stats_time = QDateTime::currentMSecsSinceEpoch();
}

GroundReceiver::~GroundReceiver() {
    stop();
}

void GroundReceiver::start() {
    if (!udp_socket_->bind(QHostAddress::AnyIPv4, listen_port_)) {
        emit error(QString("无法绑定 UDP 端口 %1: %2")
                  .arg(listen_port_).arg(udp_socket_->errorString()));
        return;
    }
    
    std::cout << "✓ UDP 接收器已启动，监听端口: " << listen_port_ << std::endl;
}

void GroundReceiver::stop() {
    if (udp_socket_) {
        udp_socket_->close();
    }
}

bool GroundReceiver::is_running() const {
    return udp_socket_ && udp_socket_->isOpen();
}

void GroundReceiver::on_udp_read_ready() {
    while (udp_socket_->hasPendingDatagrams()) {
        QByteArray datagram;
        datagram.resize(udp_socket_->pendingDatagramSize());
        
        QHostAddress sender;
        quint16 sender_port;
        
        udp_socket_->readDatagram(datagram.data(), datagram.size(), &sender, &sender_port);
        
        // 处理数据包
        process_packet((const uint8_t*)datagram.data(), datagram.size());
    }
}

void GroundReceiver::on_udp_error() {
    emit error(udp_socket_->errorString());
}

void GroundReceiver::on_cleanup_timeout() {
    cleanup_timeout_frames();
}

void GroundReceiver::process_packet(const uint8_t* data, size_t len) {
    // 检查最少包大小
    if (len < sizeof(PacketHeader)) {
        static int error_count = 0;
        if (++error_count % 100 == 0) {
            qWarning() << "收到过小的数据包:" << len << "字节，需要至少" << sizeof(PacketHeader) << "字节";
        }
        return;
    }
    
    // 解析包头
    const PacketHeader* header = (const PacketHeader*)data;
    
    // 验证魔数
    if (!isValidPacket(*header)) {
        static int error_count = 0;
        if (++error_count % 100 == 0) {
            qWarning() << "收到无效魔数的数据包，魔数:" << QString::number(header->magic, 16)
                       << "期望: 0xAA55";
        }
        return;
    }
    
    // 检查分片有效性
    if (header->chunk_index >= header->total_chunks) {
        qWarning() << "帧" << header->frame_id << "分片索引无效:" 
                   << header->chunk_index << ">=" << header->total_chunks;
        return;
    }
    
    // 获取载荷
    uint16_t payload_size = header->data_len;
    if (sizeof(PacketHeader) + payload_size != len) {
        qWarning() << "帧" << header->frame_id << "分片" << header->chunk_index 
                   << "包大小不匹配: 期望" << (sizeof(PacketHeader) + payload_size) 
                   << "实际" << len;
        return;
    }
    
    const uint8_t* payload = data + sizeof(PacketHeader);
    
    // 更新统计
    {
        std::lock_guard<std::mutex> lock(stats_mutex_);
        stats_.total_packets++;
        stats_.total_bytes += len;
        stats_.bytes_this_second += len;
    }
    
    // 查找或创建帧缓冲区
    {
        std::lock_guard<std::mutex> lock(frame_buffers_mutex_);
        
        auto it = frame_buffers_.find(header->frame_id);
        if (it == frame_buffers_.end()) {
            // 创建新的帧缓冲区
            FrameBuffer fb;
            fb.frame_id = header->frame_id;
            fb.total_chunks = header->total_chunks;
            fb.timestamp = header->timestamp;
            fb.lat = header->lat;
            fb.lon = header->lon;
            fb.alt = header->alt;
            fb.receive_time_ms = QDateTime::currentMSecsSinceEpoch();
            
            it = frame_buffers_.insert({header->frame_id, fb}).first;
        }
        
        FrameBuffer& frame = it->second;
        
        // 添加分片（如果还没有的话）
        if (frame.chunks.find(header->chunk_index) == frame.chunks.end()) {
            std::vector<uint8_t> chunk(payload, payload + payload_size);
            frame.chunks[header->chunk_index] = chunk;
            
            // 调试：如果是第一个分片，检查是否包含JPEG文件头
            if (header->chunk_index == 0 && payload_size >= 2) {
                QString hex_preview;
                for (size_t i = 0; i < std::min((size_t)8, (size_t)payload_size); i++) {
                    hex_preview += QString::number(payload[i], 16).rightJustified(2, '0') + " ";
                }
                qDebug() << "帧" << header->frame_id << "分片0前8字节:" << hex_preview
                         << "期望JPEG头: ff d8";
            }
        } else {
            // 如果分片已存在，可能是重复包，忽略
            qDebug() << "帧" << header->frame_id << "分片" << header->chunk_index << "已存在，忽略重复包";
        }
        
        // 检查是否完整 - 双重验证
        bool is_complete_check = frame.is_complete();
        bool has_all_chunks = (frame.chunks.size() == frame.total_chunks);
        
        // 额外检查：确保第一个分片存在
        bool has_first_chunk = (frame.chunks.find(0) != frame.chunks.end());
        
        if (is_complete_check && has_all_chunks && has_first_chunk) {
            // 创建副本以在锁外处理
            FrameBuffer complete_frame = frame;
            frame_buffers_.erase(it);
            
            // 释放锁后处理
            handle_complete_frame(complete_frame);
        } else {
            // 如果检查不一致，记录警告
            if (is_complete_check && (!has_all_chunks || !has_first_chunk)) {
                qWarning() << "帧" << frame.frame_id << "is_complete()检查不一致:"
                           << "is_complete()=" << is_complete_check
                           << "chunks.size()=" << frame.chunks.size()
                           << "total_chunks=" << frame.total_chunks
                           << "has_first_chunk=" << has_first_chunk;
                
                // 找出缺少的分片
                QString missing_chunks;
                for (uint16_t i = 0; i < frame.total_chunks; i++) {
                    if (frame.chunks.find(i) == frame.chunks.end()) {
                        missing_chunks += QString::number(i) + " ";
                    }
                }
                qWarning() << "缺少的分片:" << missing_chunks;
            }
            
            // 调试信息：显示当前接收进度
            if (frame.chunks.size() % 10 == 0 || frame.chunks.size() == frame.total_chunks - 1) {
                qDebug() << "帧" << frame.frame_id << "接收进度:" 
                         << frame.chunks.size() << "/" << frame.total_chunks
                         << "缺少分片:" << (frame.total_chunks - frame.chunks.size());
            }
        }
    }
}

void GroundReceiver::handle_complete_frame(const FrameBuffer& frame) {
    // 调试：打印分片信息
    qDebug() << "帧" << frame.frame_id << "开始合并，总分片数:" << frame.total_chunks 
             << "已接收分片数:" << frame.chunks.size();
    
    // 再次验证分片完整性（防止并发问题）
    if (frame.chunks.size() != frame.total_chunks) {
        qWarning() << "帧" << frame.frame_id << "分片数量不匹配:" 
                   << frame.chunks.size() << "!=" << frame.total_chunks
                   << "，跳过处理";
        {
            std::lock_guard<std::mutex> lock(stats_mutex_);
            stats_.dropped_frames++;
        }
        return;
    }
    
    // 检查分片完整性
    QString missing_chunks;
    for (uint16_t i = 0; i < frame.total_chunks; i++) {
        if (frame.chunks.find(i) == frame.chunks.end()) {
            missing_chunks += QString::number(i) + " ";
        }
    }
    
    if (!missing_chunks.isEmpty()) {
        qWarning() << "帧" << frame.frame_id << "缺少分片:" << missing_chunks
                   << "，跳过处理";
        {
            std::lock_guard<std::mutex> lock(stats_mutex_);
            stats_.dropped_frames++;
        }
        return;
    }
    
    // 只打印前几个分片的信息（避免日志过多）
    for (uint16_t i = 0; i < std::min((uint16_t)5, frame.total_chunks); i++) {
        qDebug() << "帧" << frame.frame_id << "分片" << i 
                 << "大小:" << frame.chunks.at(i).size();
    }
    
    // 合并分片
    std::vector<uint8_t> jpeg_data = frame.merge();
    
    if (jpeg_data.empty()) {
        qWarning() << "帧" << frame.frame_id << "合并后数据为空";
        return;
    }
    
    // 打印合并后的前几个字节用于调试
    qDebug() << "帧" << frame.frame_id << "合并后数据大小:" << jpeg_data.size();
    QString hex_preview;
    for (size_t i = 0; i < std::min((size_t)16, jpeg_data.size()); i++) {
        hex_preview += QString::number(jpeg_data[i], 16).rightJustified(2, '0') + " ";
    }
    qDebug() << "前16字节(hex):" << hex_preview;
    
    // 检查数据格式
    bool has_jpeg_header = (jpeg_data.size() >= 2 && jpeg_data[0] == 0xFF && jpeg_data[1] == 0xD8);
    QImage image;
    
    if (has_jpeg_header) {
        // 标准JPEG格式
        image = decode_jpeg(jpeg_data);
    } else {
        // 可能是YUYV格式，尝试转换
        // YUYV格式：每个像素2字节，所以数据大小 = width * height * 2
        // 常见的分辨率：640x480 = 614400字节, 1280x720 = 1843200字节, 1920x1080 = 4147200字节
        int width = 0, height = 0;
        
        // 尝试从数据大小推断分辨率
        if (jpeg_data.size() == 640 * 480 * 2) {
            width = 640;
            height = 480;
        } else if (jpeg_data.size() == 1280 * 720 * 2) {
            width = 1280;
            height = 720;
        } else if (jpeg_data.size() == 1920 * 1080 * 2) {
            width = 1920;
            height = 1080;
        } else {
            // 尝试计算：sqrt(size / 2) 来估算分辨率
            int estimated_size = static_cast<int>(std::sqrt(jpeg_data.size() / 2));
            // 取最接近的常见分辨率
            if (estimated_size >= 1000) {
                width = 1920;
                height = 1080;
            } else if (estimated_size >= 700) {
                width = 1280;
                height = 720;
            } else {
                width = 640;
                height = 480;
            }
            qDebug() << "帧" << frame.frame_id << "无法确定分辨率，使用估算值:" << width << "x" << height;
        }
        
        qDebug() << "帧" << frame.frame_id << "检测到YUYV格式，数据大小:" << jpeg_data.size()
                 << "分辨率:" << width << "x" << height;
        
        image = decode_yuyv(jpeg_data, width, height);
        
        if (image.isNull()) {
            // 如果YUYV转换失败，尝试作为JPEG解码
            qDebug() << "帧" << frame.frame_id << "YUYV转换失败，尝试作为JPEG解码";
            image = decode_jpeg(jpeg_data);
        }
    }
    
    if (image.isNull()) {
        qWarning() << "帧" << frame.frame_id << "所有解码方式都失败，数据大小:" << jpeg_data.size()
                   << "前16字节:" << QByteArray((const char*)jpeg_data.data(), 
                                                 std::min(16, (int)jpeg_data.size())).toHex();
        {
            std::lock_guard<std::mutex> lock(stats_mutex_);
            stats_.dropped_frames++;
        }
        return;
    }
    
    // 更新统计
    {
        std::lock_guard<std::mutex> lock(stats_mutex_);
        stats_.total_frames++;
        stats_.frames_this_second++;
        last_complete_frame_id_ = frame.frame_id;
    }
    
    // 发出信号
    qDebug() << "帧" << frame.frame_id << "解码成功，图像大小:" << image.width() << "x" << image.height()
             << "格式:" << image.format() << "准备发出frameDecoded信号";
    emit frameDecoded(image, frame.lat, frame.lon, frame.alt);
    qDebug() << "frameDecoded信号已发出";
}

QImage GroundReceiver::decode_jpeg(const std::vector<uint8_t>& data) {
    if (data.empty()) {
        qWarning() << "JPEG解码：数据为空";
        return QImage();
    }
    
    // 使用QByteArray可能更可靠，因为Qt内部可能对QByteArray有优化
    QByteArray jpeg_bytes(reinterpret_cast<const char*>(data.data()), data.size());
    
    QImage image;
    bool success = image.loadFromData(jpeg_bytes, "JPEG");
    
    if (!success) {
        // 尝试不指定格式，让Qt自动检测
        success = image.loadFromData(jpeg_bytes);
        if (!success) {
            qWarning() << "JPEG解码失败，数据大小:" << data.size()
                       << "前8字节:" << jpeg_bytes.left(8).toHex();
        }
    }
    
    return image;
}

QImage GroundReceiver::decode_yuyv(const std::vector<uint8_t>& yuyv_data, int width, int height) {
    if (yuyv_data.empty() || width <= 0 || height <= 0) {
        qWarning() << "YUYV解码：参数无效，数据大小:" << yuyv_data.size() 
                   << "分辨率:" << width << "x" << height;
        return QImage();
    }
    
    // 验证数据大小：YUYV格式每个像素2字节
    size_t expected_size = width * height * 2;
    if (yuyv_data.size() != expected_size) {
        qWarning() << "YUYV数据大小不匹配：期望" << expected_size 
                   << "实际" << yuyv_data.size();
        return QImage();
    }
    
    try {
        // 使用OpenCV转换YUYV到RGB
        cv::Mat yuyv_mat(height, width, CV_8UC2, (void*)yuyv_data.data());
        cv::Mat rgb_mat;
        
        // YUYV (YUV422) 转换为 RGB
        cv::cvtColor(yuyv_mat, rgb_mat, cv::COLOR_YUV2RGB_YUYV);
        
        if (rgb_mat.empty()) {
            qWarning() << "OpenCV YUYV转换失败";
            return QImage();
        }
        
        // 将OpenCV Mat转换为QImage
        // OpenCV使用BGR格式，QImage使用RGB格式
        cv::Mat rgb_mat_rgb;
        cv::cvtColor(rgb_mat, rgb_mat_rgb, cv::COLOR_BGR2RGB);
        
        QImage image(rgb_mat_rgb.data, rgb_mat_rgb.cols, rgb_mat_rgb.rows, 
                     rgb_mat_rgb.step, QImage::Format_RGB888);
        
        // 创建副本，因为原始数据可能被释放
        return image.copy();
        
    } catch (const cv::Exception& e) {
        qWarning() << "OpenCV YUYV转换异常:" << e.what();
        return QImage();
    }
}

void GroundReceiver::cleanup_timeout_frames() {
    uint64_t now_ms = QDateTime::currentMSecsSinceEpoch();
    
    std::lock_guard<std::mutex> lock(frame_buffers_mutex_);
    
    // 查找并删除超时的帧
    uint32_t timeout_count = 0;
    for (auto it = frame_buffers_.begin(); it != frame_buffers_.end();) {
        if (now_ms - it->second.receive_time_ms > FRAME_TIMEOUT_MS) {
            qDebug() << "帧" << it->second.frame_id << "超时，已接收分片:" 
                     << it->second.chunks.size() << "/" << it->second.total_chunks;
            it = frame_buffers_.erase(it);
            timeout_count++;
            stats_.dropped_frames++;
        } else {
            ++it;
        }
    }
    
    if (timeout_count > 0) {
        qDebug() << "清理了" << timeout_count << "个超时帧";
    }
    
    // 更新统计
    uint64_t current_time = QDateTime::currentMSecsSinceEpoch();
    if (current_time - stats_.last_stats_time >= 1000) {
        int fps = stats_.frames_this_second;
        int kbs = stats_.bytes_this_second / 1024;
        
        emit statsUpdated(fps, kbs);
        
        // 重置计数器
        stats_.frames_this_second = 0;
        stats_.bytes_this_second = 0;
        stats_.last_stats_time = current_time;
    }
}

void GroundReceiver::update_stats(uint32_t packet_size) {
    std::lock_guard<std::mutex> lock(stats_mutex_);
    stats_.total_bytes += packet_size;
    stats_.bytes_this_second += packet_size;
}
