/**
 * @file basic_test.cpp
 * @brief 战场任务规划管理系统基本单元测试
 *
 * 使用标准库 assert 进行单元测试，覆盖核心功能模块：
 * - SU-01: 事件接收与处理
 * - SU-02: 事件标准化处理
 * - SU-03: 事件展示与操作
 * - SU-04: 任务生成
 * - SU-05: 任务模板管理
 * - SU-06: 计划管理
 * - SU-07: 方案分发
 * - SU-08: 状态监控
 */

#include "app.hpp"
#include <cassert>
#include <iostream>
#include <string>
#include <vector>
#include <thread>
#include <chrono>

using namespace bmp;

/**
 * @brief 测试事件接收与处理（SU-01）
 *
 * @requirement(name="事件接收与处理", id="SU-01")
 * 测试接收有效JSON事件、有效XML事件、空数据和无效数据。
 */
static void testEventReception() {
    std::cout << "[测试] SU-01: 事件接收与处理" << std::endl;
    EventService svc;

    // 测试1: 接收有效JSON事件
    std::string jsonEvent = "{ \"type\": \"敌情侦察\", \"priority\": \"HIGH\" }";
    bool result = svc.receiveEvent(jsonEvent);
    assert(result && "接收有效JSON事件应该成功");

    // 测试2: 接收有效XML事件
    std::string xmlEvent = "<event><type>空情预警</type></event>";
    result = svc.receiveEvent(xmlEvent);
    assert(result && "接收有效XML事件应该成功");

    // 测试3: 接收空数据
    result = svc.receiveEvent("");
    assert(!result && "接收空数据应该失败");

    // 测试4: 接收无效数据（既不是JSON也不是XML）
    result = svc.receiveEvent("invalid data without brackets");
    assert(!result && "接收无效格式数据应该失败");

    // 测试5: 发送ACK
    std::string ack = svc.sendAck("unknown");
    assert(ack == "ACK:UNKNOWN" && "未知事件ID应返回 UNKNOWN");

    std::cout << "  SU-01 测试通过！" << std::endl << std::endl;
}

/**
 * @brief 测试事件标准化处理（SU-02）
 *
 * @requirement(name="事件标准化处理", id="SU-02")
 * 测试获取原始事件、处理事件和保存标准化事件。
 */
static void testEventStandardization() {
    std::cout << "[测试] SU-02: 事件标准化处理" << std::endl;
    EventService svc;

    // 准备测试数据
    std::string jsonEvent = "{ \"type\": \"敌情侦察\", \"priority\": \"HIGH\" }";
    svc.receiveEvent(jsonEvent);
    auto pending = svc.getPendingEvents();
    assert(!pending.empty() && "应有待处理事件");

    // 测试1: 获取原始事件
    const Event* raw = svc.getRawEvent(pending[0].id);
    assert(raw != nullptr && "应能获取原始事件");
    assert(raw->status == EventStatus::PENDING && "原始事件状态应为PENDING");

    // 测试2: 处理事件（标准化）
    bool processed = svc.processEvent(pending[0].id);
    assert(processed && "事件标准化应成功");

    // 测试3: 再次处理应失败（状态已变更）
    processed = svc.processEvent(pending[0].id);
    assert(!processed && "重复处理应失败");

    // 测试4: 处理不存在的事件
    processed = svc.processEvent("nonexistent");
    assert(!processed && "处理不存在的事件应失败");

    // 测试5: 保存标准化事件
    Event customEvent;
    customEvent.id = "CUSTOM_001";
    customEvent.title = "测试事件";
    customEvent.status = EventStatus::ACCEPTED;
    svc.saveStandardEvent(customEvent);
    const Event* saved = svc.getRawEvent("CUSTOM_001");
    assert(saved != nullptr && "保存后应能获取标准化事件");
    assert(saved->status == EventStatus::ACCEPTED && "标准化事件状态应正确");

    std::cout << "  SU-02 测试通过！" << std::endl << std::endl;
}

/**
 * @brief 测试事件展示与操作（SU-03）
 *
 * @requirement(name="事件展示与操作", id="SU-03")
 * 测试事件查询、获取待处理事件等功能。
 */
static void testEventQuery() {
    std::cout << "[测试] SU-03: 事件展示与操作" << std::endl;
    EventService svc;

    // 准备测试数据
    svc.receiveEvent("{ \"type\": \"A\" }");
    svc.receiveEvent("{ \"type\": \"B\" }");

    // 测试1: 查询所有事件
    auto all = svc.queryEvents({});
    assert(all.size() == 2 && "应有2个事件");

    // 测试2: 获取待处理事件
    auto pending = svc.getPendingEvents();
    assert(pending.size() == 2 && "应有2个待处理事件");

    // 测试3: 过滤状态
    auto filtered = svc.queryEvents({{"status", "PENDING"}});
    assert(filtered.size() == 2 && "过滤PENDING应有2个");

    std::cout << "  SU-03 测试通过！" << std::endl << std::endl;
}

/**
 * @brief 测试任务模板管理（SU-05）
 *
 * @requirement(name="任务模板管理", id="SU-05")
 * 测试模板接收、列表、选择和推荐功能。
 */
static void testTemplateManagement() {
    std::cout << "[测试] SU-05: 任务模板管理" << std::endl;
    TemplateService svc;

    // 测试1: 接收空数据
    size_t count = svc.receiveTemplates("");
    assert(count == 0 && "空数据应解析出0个模板");

    // 测试2: 接收有效模板
    std::string tmplData =
        "{\"id\":\"T1\",\"name\":\"模板1\",\"scenario\":\"侦察\"}\n"
        "{\"id\":\"T2\",\"name\":\"模板2\",\"scenario\":\"预警\"}\n";
    count = svc.receiveTemplates(tmplData);
    assert(count == 2 && "应有2个模板被解析");

    // 测试3: 获取模板列表
    auto list = svc.getTemplateList();
    assert(list.size() == 2 && "模板列表应有2个");

    // 测试4: 选择模板
    bool selected = svc.selectTemplate("T1");
    assert(selected && "选择存在的模板应成功");

    selected = svc.selectTemplate("NONEXIST");
    assert(!selected && "选择不存在的模板应失败");

    // 测试5: 推荐模板
    std::string recommended = svc.recommendTemplate("侦察");
    assert(recommended == "T1" && "应为侦察推荐T1模板");

    recommended = svc.recommendTemplate("未知");
    assert(!recommended.empty() && "无匹配时应有默认推荐");

    // 测试6: 获取配置
    auto config = svc.getConfig();
    assert(config.find("auto_recommend") != config.end() && "应有auto_recommend配置");

    std::cout << "  SU-05 测试通过！" << std::endl << std::endl;
}

/**
 * @brief 测试任务生成与计划管理（SU-04, SU-06）
 *
 * @requirement(name="任务生成", id="SU-04")
 * @requirement(name="计划管理", id="SU-06")
 * 测试任务生成、提交、计划列表、排序、重配置和HITL通知。
 */
static void testPlanManagement() {
    std::cout << "[测试] SU-04/SU-06: 任务生成与计划管理" << std::endl;
    PlanService svc;

    // 测试1: 生成任务 - 空参数应失败
    std::string planId = svc.generateTask("", "T1", {});
    assert(planId.empty() && "空事件ID应生成失败");

    // 测试2: 生成任务 - 有效参数
    planId = svc.generateTask("EVT_001", "T1", {{"remarks", "测试"}});
    assert(!planId.empty() && "有效参数应生成计划");
    assert(planId.find("PLAN_") == 0 && "计划ID应以PLAN_开头");

    // 测试3: 提交任务
    TaskPlan plan = svc.submitTask(planId);
    assert(plan.status == PlanStatus::CONFIRMED && "提交后状态应为CONFIRMED");
    assert(plan.id == planId && "返回的计划ID应匹配");

    // 测试4: 提交不存在的计划
    TaskPlan emptyPlan = svc.submitTask("NONEXIST");
    assert(emptyPlan.id.empty() && "不存在的计划应返回空");

    // 测试5: 获取计划列表
    auto plans = svc.getPlanList();
    assert(plans.size() == 1 && "应有1个计划");

    // 测试6: 排序计划
    svc.sortPlans({{"priority", 1}, {"time", 1}});

    // 测试7: 计划重配置
    std::vector<PlanNode> newNodes;
    PlanNode node;
    node.nodeId = "NODE_001";
    node.planId = planId;
    node.taskType = "侦察";
    node.executeUnit = "无人机";
    newNodes.push_back(node);
    bool reconfigured = svc.reconfigurePlan(planId, newNodes);
    assert(reconfigured && "重配置应成功");

    // 重配置不存在的计划
    reconfigured = svc.reconfigurePlan("NONEXIST", newNodes);
    assert(!reconfigured && "重配置不存在计划应失败");

    // 测试8: HITL通知
    svc.notifyHITL(planId, "请确认方案");
    svc.notifyHITL("NONEXIST", "测试"); // 不应崩溃

    std::cout << "  SU-04/SU-06 测试通过！" << std::endl << std::endl;
}

/**
 * @brief 测试方案分发（SU-07）
 *
 * @requirement(name="方案分发", id="SU-07")
 * 测试分发流程、ACK接收、重试和状态更新。
 */
static void testDistribution() {
    std::cout << "[测试] SU-07: 方案分发" << std::endl;
    DistributionService svc;

    // 测试1: 分发计划
    auto logs = svc.distributePlan("PLAN_001");
    assert(logs.size() == 3 && "应有3条分发日志");
    for (const auto& log : logs) {
        assert(!log.logId.empty() && "日志ID不应为空");
        assert(log.response == DistributionResponse::TIMEOUT && "初始状态应为TIMEOUT");
        assert(log.retryCount == 0 && "初始重试次数应为0");
    }

    // 测试2: 接收ACK
    bool ackOk = svc.receiveAck(logs[0].logId, DistributionResponse::ACK);
    assert(ackOk && "接收ACK应成功");

    ackOk = svc.receiveAck("NONEXIST", DistributionResponse::ACK);
    assert(!ackOk && "接收不存在的日志ACK应失败");

    // 测试3: 接收NACK并验证重试
    bool nackOk = svc.receiveAck(logs[1].logId, DistributionResponse::NACK);
    assert(nackOk && "接收NACK应成功");

    // 测试4: 查询分发日志
    auto queriedLogs = svc.getLogsByPlan("PLAN_001");
    assert(queriedLogs.size() == 3 && "应有3条日志");
    assert(queriedLogs[0].response == DistributionResponse::ACK && "第一条应为ACK");
    assert(queriedLogs[1].response == DistributionResponse::NACK && "第二条应为NACK");

    // 测试5: 状态更新（不崩溃即可）
    svc.updateStatus("PLAN_001");

    std::cout << "  SU-07 测试通过！" << std::endl << std::endl;
}

/**
 * @brief 测试状态监控（SU-08）
 *
 * @requirement(name="状态监控", id="SU-08")
 * 测试遥测数据接收、解析、报警触发和数据陈旧检查。
 */
static void testStatusMonitoring() {
    std::cout << "[测试] SU-08: 状态监控" << std::endl;
    StatusMonitorService svc;

    // 测试1: 接收有效遥测数据
    std::vector<uint8_t> validData = {
        0x00, 0x01, 0x00, 0x01,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x23, 0x28,
        0x4E, 0x6F, 0x72, 0x6D, 0x61, 0x6C
    };
    StatusLog log = svc.receiveTelemetry(validData);
    assert(!log.recordId.empty() && "记录ID不应为空");
    assert(!log.isAbnormal && "正常状态码不应标记为异常");

    // 测试2: 接收异常遥测数据
    std::vector<uint8_t> abnormalData = {
        0x00, 0x01, 0x00, 0x02,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x23, 0x38,  // 9016 > 9000
        0x45, 0x72, 0x72, 0x6F, 0x72
    };
    StatusLog abnormalLog = svc.receiveTelemetry(abnormalData);
    assert(abnormalLog.isAbnormal && "状态码大于9000应标记为异常");

    // 测试3: 接收短数据（无效）
    std::vector<uint8_t> shortData = {0x00, 0x01};
    StatusLog shortLog = svc.receiveTelemetry(shortData);
    assert(shortLog.isAbnormal && "短数据应标记为异常");
    assert(shortLog.statusCode == "ERR_INVALID_DATA" && "短数据应有错误码");

    // 测试4: 触发报警
    std::string alarm = svc.triggerAlarm(abnormalLog);
    assert(!alarm.empty() && "异常状态应触发报警");
    assert(alarm.find("[ALARM]") == 0 && "报警消息应以[ALARM]开头");

    // 正常状态不触发报警
    alarm = svc.triggerAlarm(log);
    assert(alarm.empty() && "正常状态不应触发报警");

    // 测试5: 获取最新状态
    StatusLog latest = svc.getLatestStatus("AST_65537");
    assert(latest.assetId == "AST_65537" && "应返回正确资产的状态");

    // 不存在的资产
    latest = svc.getLatestStatus("UNKNOWN");
    assert(latest.isAbnormal && "不存在的资产应标记异常");

    // 测试6: 数据陈旧检查
    std::this_thread::sleep_for(std::chrono::milliseconds(50));
    svc.checkStaleData(10);
    StatusLog staleLog = svc.getLatestStatus("AST_65537");
    assert(staleLog.isAbnormal && "超过阈值后应标记为陈旧");
    assert(staleLog.statusCode == "STALE" && "陈旧数据状态码应为STALE");

    std::cout << "  SU-08 测试通过！" << std::endl << std::endl;
}

/**
 * @brief 测试系统外观类
 *
 * @requirement(name="业务目标", id="REQ-BMP-001")
 * 测试系统初始化、完整业务流程的协调。
 */
static void testSystemIntegration() {
    std::cout << "[测试] BMP集成: 系统外观类" << std::endl;
    BattlefieldMissionPlanner bmp;

    // 测试1: 初始化
    bool initialized = bmp.initialize();
    assert(initialized && "系统初始化应成功");

    // 测试2: 获取各服务引用
    assert(&bmp.getEventService() != nullptr && "事件服务不应为空");
    assert(&bmp.getTemplateService() != nullptr && "模板服务不应为空");
    assert(&bmp.getPlanService() != nullptr && "计划服务不应为空");
    assert(&bmp.getDistributionService() != nullptr && "分发服务不应为空");
    assert(&bmp.getStatusMonitorService() != nullptr && "状态监控服务不应为空");

    // 测试3: 运行主循环（不崩溃即可）
    bmp.run();

    std::cout << "  BMP集成测试通过！" << std::endl << std::endl;
}

int main() {
    std::cout << "========================================" << std::endl;
    std::cout << "  战场任务规划管理系统 - 单元测试" << std::endl;
    std::cout << "========================================" << std::endl << std::endl;

    testEventReception();
    testEventStandardization();
    testEventQuery();
    testTemplateManagement();
    testPlanManagement();
    testDistribution();
    testStatusMonitoring();
    testSystemIntegration();

    std::cout << "========================================" << std::endl;
    std::cout << "  全部测试通过！" << std::endl;
    std::cout << "========================================" << std::endl;
    return 0;
}
