/**
 * @file main.cpp
 * @brief AvaotaF1 智能眼镜客户端 - 主程序
 * @date 2025-11-21
 * @platform Avaota F1 (Allwinner V821 / RISC-V)
 * 
 * 功能模块:
 * - 摄像头视频流 (WebSocket /ws/camera)
 * - 音频采集上传 (WebSocket /ws_audio)
 * - TTS 音频播放 (WebSocket /ws_audio - 双向)
 * - IMU 数据上报 (UDP :12345)
 */

#include <iostream>
#include <thread>
#include <atomic>
#include <vector>
#include <signal.h>
#include <unistd.h>

#include "camera/camera.h"
#include "audio/audio_capture.h"
#include "audio/audio_player.h"
// Day 21: VAD 已移到服务器端 (Silero VAD)，不再需要客户端 VAD
#include "imu/icm42688.h"
#include "network/ws_client.h"
#include "network/udp_sender.h"
#include "utils/logger.h"

// ===== 配置参数 =====
const char* SERVER_HOST = "8.148.25.142";
const int   SERVER_PORT = 8081;
const char* CAM_WS_PATH = "/ws/camera";
const char* AUD_WS_PATH = "/ws_audio";
const int   UDP_PORT = 12345;

// ===== 全局控制标志 =====
std::atomic<bool> g_running{true};

// ===== 信号处理 =====
void signal_handler(int sig) {
    LOG_INFO("Received signal %d, shutting down...", sig);
    g_running = false;
}

// ===== 摄像头线程 =====
void camera_thread() {
    LOG_INFO("[CAM] Thread started");
    
    Camera camera;
    if (!camera.init()) {
        LOG_ERROR("[CAM] Init failed");
        return;
    }
    
    WSClient ws_cam(SERVER_HOST, SERVER_PORT, CAM_WS_PATH);
    
    // Day 11: 添加连续失败计数和恢复机制
    int consecutive_failures = 0;
    const int MAX_FAILURES = 5;
    
    while (g_running) {
        // 连接 WebSocket
        bool connected = ws_cam.is_connected();
        if (!connected) {
            if (ws_cam.connect()) {
                LOG_INFO("[CAM] WebSocket connected");
                connected = true;
            } else {
                LOG_WARN("[CAM] WebSocket connect failed, will retry after frame consume");
                // Day 11: 不再 continue，而是继续采集帧来清空 VBV
            }
        }
        
        // 采集一帧
        uint8_t* jpeg_data = nullptr;
        size_t jpeg_size = 0;
        
        if (camera.capture_frame(&jpeg_data, &jpeg_size)) {
            consecutive_failures = 0;  // 成功时重置计数
            
            // Day 11: 只在连接时发送，否则丢弃帧以保持 VBV 流畅
            if (connected) {
                if (!ws_cam.send_binary(jpeg_data, jpeg_size)) {
                    LOG_ERROR("[CAM] Send failed");
                    ws_cam.disconnect();
                }
            } else {
                // 未连接时消费帧但不发送，间隔 1 秒重试连接
                usleep(1000000);
            }
            camera.release_frame(jpeg_data);
        } else {
            consecutive_failures++;
            LOG_WARN("[CAM] Capture failed (%d/%d)", consecutive_failures, MAX_FAILURES);
            
            // Day 11: 连续失败超过阈值，尝试重新初始化
            if (consecutive_failures >= MAX_FAILURES) {
                LOG_WARN("[CAM] Too many failures, reinitializing camera...");
                camera.deinit();
                usleep(1000000);  // 等待 1 秒
                
                if (!camera.init()) {
                    LOG_ERROR("[CAM] Reinit failed, fatal error!");
                    break;  // 无法恢复，退出线程
                }
                
                LOG_INFO("[CAM] Camera reinitialized successfully");
                consecutive_failures = 0;
            }
            
            usleep(100000); // 100ms 等待
        }
        
        // 处理服务器消息 (SET:FRAMESIZE=VGA 等)
        ws_cam.poll_messages([&camera](const std::string& msg) {
            if (msg.find("SET:FRAMESIZE=") == 0) {
                std::string size = msg.substr(14);
                camera.set_framesize(size);
            } else if (msg.find("SET:QUALITY=") == 0) {
                int quality = std::stoi(msg.substr(12));
                camera.set_quality(quality);
            }
        });
    }
    
    LOG_INFO("[CAM] Thread stopped");
}

// ===== 音频采集线程 =====
void audio_capture_thread() {
    LOG_INFO("[AUD-CAP] Thread started");
    
    AudioCapture mic("hw:0,0", 16000, 1);  // 16kHz, mono - 麦克风
    if (!mic.init()) {
        LOG_ERROR("[AUD-CAP] Init failed");
        return;
    }
    
    // Day 21 改进: 移除客户端 VAD，改为服务器端 Silero VAD
    // 客户端持续发送所有音频，服务器负责语音检测
    LOG_INFO("[AUD-CAP] Server-side VAD mode (continuous audio streaming)");
    
    
    // Day 14 修正: 恢复 WebSocket TTS 播放（经验证有效）
    // 初始化扬声器 (hw:1,0 - I2S 接口连接 MAX98357A)
    AudioPlayer speaker("hw:1,0", 16000, 1);  // 16kHz, mono
    bool speaker_enabled = false;
    
    if (speaker.init()) {
        LOG_INFO("[AUD-PLAY] Speaker initialized on hw:1,0");
        speaker_enabled = true;
    } else {
        LOG_WARN("[AUD-PLAY] Speaker init failed, audio playback disabled");
    }
    
    WSClient ws_aud(SERVER_HOST, SERVER_PORT, AUD_WS_PATH);
    
    // Day 11: 添加诊断计数器
    int audio_send_count = 0;
    int audio_bytes_total = 0;
    int audio_read_attempts = 0;
    int audio_zero_reads = 0;
    
    // TTS 预缓冲区 - Day 22 优化: 降低延迟
    // 原来2秒预缓冲导致外出时语音延迟太大，改为0.5秒
    std::vector<int16_t> tts_buffer;
    const size_t PRE_BUFFER_FRAMES = 8000;   // 0.5 秒的帧数 (16kHz) - 从32000降低
    const size_t MIN_PLAY_FRAMES = 1600;     // 最小播放帧数 (0.1s) - 从4800降低
    bool is_buffering = true;
    int tts_recv_count = 0;
    
    // Day 21 优化：指数退避重连策略
    int reconnect_delay = 1;  // 初始 1 秒
    const int MAX_RECONNECT_DELAY = 16;  // 最大 16 秒
    
    while (g_running) {
        if (!ws_aud.is_connected()) {
            if (ws_aud.connect()) {
                LOG_INFO("[AUD-CAP] WebSocket connected");
                ws_aud.send_text("START");
                // 重置 TTS 缓冲状态
                tts_buffer.clear();
                is_buffering = true;
                // 连接成功，重置退避时间
                reconnect_delay = 1;
            } else {
                LOG_WARN("[AUD-CAP] Connect failed, retry in %ds", reconnect_delay);
                sleep(reconnect_delay);
                // 指数退避：每次失败后延迟翻倍，最大 16 秒
                reconnect_delay = std::min(reconnect_delay * 2, MAX_RECONNECT_DELAY);
                continue;
            }
        }

        
        // Day 22 优化: 使用20ms音频包(320 samples)，与服务器ASR期望一致
        // 20ms @ 16kHz = 320 samples = 640 bytes
        int16_t buffer[320];
        snd_pcm_sframes_t frames_read = mic.read(buffer, 320);
        audio_read_attempts++;
        
        // 每 100 次读取输出诊断
        if (audio_read_attempts % 100 == 0) {
            LOG_INFO("[AUD-CAP] Stats: attempts=%d, sent=%d, zero_reads=%d", 
                     audio_read_attempts, audio_send_count, audio_zero_reads);
        }
        
        // 检查致命错误（设备重新初始化失败）
        if (frames_read < 0) {
            LOG_ERROR("[AUD-CAP] Fatal error, exiting thread");
            break;
        }
        
        if (frames_read > 0) {
            // Day 21 改进: 移除客户端 VAD，改为持续发送所有音频
            // 服务器端使用 Silero VAD 进行语音检测（更准确）
            int bytes_to_send = frames_read * 2;
            if (ws_aud.send_binary((uint8_t*)buffer, bytes_to_send)) {
                audio_send_count++;
                audio_bytes_total += bytes_to_send;
                
                // 第一次发送时打印日志
                if (audio_send_count == 1) {
                    LOG_INFO("[AUD-CAP] First audio packet sent! (%d bytes)", bytes_to_send);
                }
            
                // 每 100 次发送输出一次诊断日志
                if (audio_send_count % 100 == 0) {
                    LOG_INFO("[AUD-CAP] Sent %d packets, %d bytes total", 
                             audio_send_count, audio_bytes_total);
                }
            } else {
                LOG_WARN("[AUD-CAP] Send failed");
            }
        } else {
            audio_zero_reads++;
            // 非阻塞模式：等待 20ms
            usleep(20000);  // 20ms
        }
        
        // 处理服务器消息 (文本命令和二进制音频数据)
        ws_aud.poll_messages([&](const std::string& msg) {
            // Day 21: 正确处理 RESET/RESTART 命令，重新启动 ASR 会话
            if (msg == "RESTART" || msg == "RESET") {
                LOG_INFO("[AUD-CAP] Received %s command, restarting ASR...", msg.c_str());
                ws_aud.send_text("START");
                // 重置 TTS 缓冲状态
                tts_buffer.clear();
                is_buffering = true;
                tts_recv_count = 0;
            }
        });
        
        // Day 14 修正: 恢复 WebSocket TTS 播放（服务器返回 16kHz PCM）
        if (speaker_enabled) {
            ws_aud.poll_binary_messages([&](const uint8_t* data, size_t size) {
                // 服务器返回的是 16kHz, mono, S16_LE PCM 数据
                if (size % 2 == 0) {
                    size_t frames = size / 2;
                    tts_recv_count++;
                    
                    // 将新数据追加到缓冲区
                    const int16_t* samples = (const int16_t*)data;
                    tts_buffer.insert(tts_buffer.end(), samples, samples + frames);
                    
                    // 第一次收到时输出日志
                    if (tts_recv_count == 1) {
                        LOG_INFO("[AUD-PLAY] 🔊 First TTS chunk: %zu bytes", size);
                    }
                    
                    // 检查是否应该开始播放
                    if (is_buffering && tts_buffer.size() >= PRE_BUFFER_FRAMES) {
                        LOG_INFO("[AUD-PLAY] Pre-buffer full (%zu frames), starting playback", 
                                 tts_buffer.size());
                        is_buffering = false;
                    }
                }
            });
            
            // 播放缓冲区中的数据
            if (!is_buffering && tts_buffer.size() >= MIN_PLAY_FRAMES) {
                // 每次播放 1600 帧 (100ms)
                size_t play_frames = std::min(tts_buffer.size(), (size_t)1600);
                snd_pcm_sframes_t written = speaker.write(tts_buffer.data(), play_frames);
                
                if (written > 0) {
                    tts_buffer.erase(tts_buffer.begin(), tts_buffer.begin() + written);
                } else if (written == -EAGAIN) {
                    usleep(5000);  // 5ms
                }
            } else if (!is_buffering && tts_buffer.empty()) {
                // 缓冲区空了，重新进入缓冲状态
                is_buffering = true;
                tts_recv_count = 0;
            }
        }
    }
    
    LOG_INFO("[AUD-CAP] Thread stopped");
}



// ===== IMU 线程 =====
void imu_thread() {
    LOG_INFO("[IMU] Thread started");
    
    ICM42688 imu("/dev/spidev0.0");
    if (!imu.init()) {
        LOG_ERROR("[IMU] Init failed (check Device Tree SPI config)");
        return;
    }
    
    UDPSender udp(SERVER_HOST, UDP_PORT);
    
    while (g_running) {
        float temp_c, ax, ay, az, gx, gy, gz;
        
        if (imu.read_sensors(temp_c, ax, ay, az, gx, gy, gz)) {
            // 构造 JSON
            char json[256];
            snprintf(json, sizeof(json),
                "{\"ts\":%lu,\"temp_c\":%.2f,"
                "\"accel\":{\"x\":%.3f,\"y\":%.3f,\"z\":%.3f},"
                "\"gyro\":{\"x\":%.3f,\"y\":%.3f,\"z\":%.3f}}",
                (unsigned long)(time(nullptr) * 1000), temp_c,
                ax, ay, az, gx, gy, gz);
            
            udp.send(json, strlen(json));
        }
        
        usleep(100000); // 10 Hz (100ms) - 降低采样率减少对音频的干扰
    }
    
    LOG_INFO("[IMU] Thread stopped");
}

// ===== 主函数 =====
int main(int argc, char** argv) {
    (void)argc;  // 未使用
    (void)argv;
    // 初始化日志系统
    Logger::init(LOG_LEVEL_INFO);
    LOG_INFO("========================================");
    LOG_INFO("AvaotaF1 Client Starting...");
    LOG_INFO("Server: %s:%d", SERVER_HOST, SERVER_PORT);
    LOG_INFO("========================================");
    
    // 注册信号处理
    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);
    
    // 创建线程
    std::thread t_camera(camera_thread);
    std::thread t_mic(audio_capture_thread);
    // Day 14 修正: 移除 HTTP TTS 线程，改回 WebSocket TTS 播放（在 audio_capture_thread 中处理）
    std::thread t_imu(imu_thread);
    
    // 主线程监控
    while (g_running) {
        sleep(5);
        LOG_INFO("[MAIN] Heartbeat - all threads running");
    }
    
    // 等待线程退出
    LOG_INFO("Waiting for threads to exit...");
    t_camera.join();
    t_mic.join();
    t_imu.join();
    
    LOG_INFO("========================================");
    LOG_INFO("AvaotaF1 Client Stopped");
    LOG_INFO("========================================");
    
    return 0;
}
