// XYParser API 单元测试文件
// 测试 XYParser 库的核心功能，包括解析器创建、错误处理、帧解析等

#include <gtest/gtest.h>
#include "../XYParserApi.h"

#include <array>
#include <cstddef>
#include <cstdint>
#include <string>
#include <vector>

// 匿名命名空间，包含测试辅助代码
namespace {

/// ParserGuard 类：RAII 封装，确保解析器资源自动释放
/// 当对象生命周期结束时自动调用 XYParser_DestroyParser 释放资源
class ParserGuard {
public:
    /// 构造函数，接管解析器句柄的所有权
    /// @param handle XYParser 解析器句柄
    explicit ParserGuard(XYParserHandle handle) : handle_(handle) {}

    /// 析构函数，自动释放解析器资源
    ~ParserGuard()
    {
        if (handle_ != nullptr) {
            XYParser_DestroyParser(handle_);
        }
    }

    /// 获取解析器句柄
    /// @return XYParser 解析器句柄
    XYParserHandle get() const
    {
        return handle_;
    }

private:
    XYParserHandle handle_; ///< 解析器句柄
};

/// 构建最小帧数据的辅助函数
/// 生成符合 XYParser 协议格式的测试帧数据
/// @param channel_count 通道数量
/// @param frame_index 帧索引，小端写入标签区前 4 字节
/// @return 包含完整帧数据的字节向量
std::vector<std::uint8_t> BuildMinimalFrame(std::uint8_t channel_count, std::uint32_t frame_index)
{
    constexpr std::size_t kSamplesPerFrame = 5;  ///< 每帧采样数
    constexpr std::uint8_t kHeader = 0xAA;       ///< 帧头标记
    constexpr std::uint8_t kTail = 0x55;         ///< 帧尾标记
    constexpr std::size_t kTagLen = 25;          ///< 标签长度

    // 计算帧结构大小
    const std::size_t sample_bytes = static_cast<std::size_t>(channel_count) * 3 + 2;
    const std::uint16_t payload_length = static_cast<std::uint16_t>(sample_bytes * kSamplesPerFrame);
    const std::size_t frame_size = 1 + kTagLen + payload_length + 2;

    std::vector<std::uint8_t> frame(frame_size, 0);
    std::size_t offset = 0;

    // 写入帧头
    frame[offset++] = kHeader;

    // 写入标签数据中的帧索引（小端序）
    frame[offset++] = static_cast<std::uint8_t>(frame_index & 0xFF);
    frame[offset++] = static_cast<std::uint8_t>((frame_index >> 8) & 0xFF);
    frame[offset++] = static_cast<std::uint8_t>((frame_index >> 16) & 0xFF);
    frame[offset++] = static_cast<std::uint8_t>((frame_index >> 24) & 0xFF);

    // 写入负载长度（大端序）
    frame[offset++] = static_cast<std::uint8_t>((payload_length >> 8) & 0xFF);
    frame[offset++] = static_cast<std::uint8_t>(payload_length & 0xFF);

    // 写入电池电量和通道数
    frame[offset++] = 95;
    frame[offset++] = channel_count;

    // 跳过保留字段
    offset += 2 + 2 + 2 + 2 + 2 + 6;

    // 写入采样数据
    for (std::size_t sample = 0; sample < kSamplesPerFrame; ++sample) {
        for (std::size_t channel = 0; channel < channel_count; ++channel) {
            frame[offset++] = 0x00;
            frame[offset++] = 0x00;
            frame[offset++] = static_cast<std::uint8_t>(sample + channel + 1);
        }
        // 每个采样后的额外字节
        frame[offset++] = 0x00;
        frame[offset++] = 0x00;
    }

    // 写入帧尾
    frame[offset++] = 0x00;
    frame[offset++] = kTail;
    frame[offset++] = kTail;

    return frame;
}

/// 为现有调用点保留默认 frame_index=1 的便捷重载
std::vector<std::uint8_t> BuildMinimalFrame(std::uint8_t channel_count)
{
    return BuildMinimalFrame(channel_count, 1U);
}

} // namespace

/// 测试：创建解析器时拒绝不支持的通道数
TEST(XYParserApiTests, CreateParserRejectsUnsupportedChannelCount)
{
    // 7 通道是不支持的配置，应返回 nullptr
    EXPECT_EQ(XYParser_CreateParser(7), nullptr);
}

/// 测试：对空解析器句柄调用 GetLastError 应返回正确错误信息
TEST(XYParserApiTests, GetLastErrorReturnsMessageForNullParser)
{
    // 传入 nullptr 应返回 "invalid parser handle"
    EXPECT_EQ(std::string(XYParser_GetLastError(nullptr)), std::string("invalid parser handle"));
}

/// 测试：Feed 函数能正确解析完整的 8 通道帧
TEST(XYParserApiTests, FeedParsesAComplete8ChannelFrame)
{
    // 创建 8 通道解析器
    ParserGuard parser(XYParser_CreateParser(8));
    ASSERT_NE(parser.get(), nullptr);

    // 设置 ADC 参数和校验和绕过标志
    XYParser_SetAdcParams(parser.get(), 4.5, 6.0);
    XYParser_SetBypassChecksum(parser.get(), 1);

    // 构建测试帧并解析
    const std::vector<std::uint8_t> bytes = BuildMinimalFrame(8);
    std::array<XYParserFrameSummary, 1> summaries{};

    const int frame_count = XYParser_Feed(
        parser.get(),
        bytes.data(),
        bytes.size(),
        summaries.data(),
        static_cast<int>(summaries.size()));

    // 验证解析结果
    ASSERT_EQ(frame_count, 1);                             // 应解析出 1 帧
    EXPECT_EQ(summaries[0].frame_index, 1U);               // 帧索引应为 1
    EXPECT_EQ(summaries[0].channel_count, 8U);             // 通道数应为 8
    EXPECT_EQ(summaries[0].battery, 95U);                  // 电池电量应为 95
    EXPECT_EQ(summaries[0].sample_count, 5U);              // 采样数应为 5
    EXPECT_GT(summaries[0].channel_values_uv[0][0], 0.0);  // 通道值应大于 0
    EXPECT_EQ(summaries[0].trigger_types[0], 0U);          // 触发类型应为 0
    EXPECT_EQ(summaries[0].trigger_indices[0], 0U);        // 触发索引应为 0
}

/// 测试：Feed 函数能缓冲部分数据直到完整帧可用
TEST(XYParserApiTests, FeedBuffersPartialDataUntilAFullFrameIsAvailable)
{
    // 创建 8 通道解析器
    ParserGuard parser(XYParser_CreateParser(8));
    ASSERT_NE(parser.get(), nullptr);

    // 设置校验和绕过标志
    XYParser_SetBypassChecksum(parser.get(), 1);

    // 构建测试帧并分成两部分
    const std::vector<std::uint8_t> bytes = BuildMinimalFrame(8);
    const std::size_t split_index = bytes.size() / 2;
    std::array<XYParserFrameSummary, 1> summaries{};

    // 第一次 Feed：传入前半部分数据
    const int first_result = XYParser_Feed(
        parser.get(),
        bytes.data(),
        split_index,
        summaries.data(),
        static_cast<int>(summaries.size()));
    EXPECT_EQ(first_result, 0);  // 数据不完整，不应解析出帧

    // 第二次 Feed：传入后半部分数据
    const int second_result = XYParser_Feed(
        parser.get(),
        bytes.data() + split_index,
        bytes.size() - split_index,
        summaries.data(),
        static_cast<int>(summaries.size()));
    ASSERT_EQ(second_result, 1);         // 数据完整，应解析出 1 帧
    EXPECT_EQ(summaries[0].frame_index, 1U);  // 帧索引应为 1
}

// ============================================================================
// 解析器创建测试
// ============================================================================

/// 测试：成功创建 8 通道解析器
TEST(XYParserApiTests, CreateParserSucceedsFor8Channels)
{
    ParserGuard parser(XYParser_CreateParser(8));
    EXPECT_NE(parser.get(), nullptr);
}

/// 测试：成功创建 64 通道解析器
TEST(XYParserApiTests, CreateParserSucceedsFor64Channels)
{
    ParserGuard parser(XYParser_CreateParser(64));
    EXPECT_NE(parser.get(), nullptr);
}

/// 测试：创建 0 通道解析器应失败
TEST(XYParserApiTests, CreateParserRejectsZeroChannels)
{
    EXPECT_EQ(XYParser_CreateParser(0), nullptr);
}

/// 测试：创建不支持的通道数（如 100）应失败
TEST(XYParserApiTests, CreateParserRejectsExcessiveChannels)
{
    EXPECT_EQ(XYParser_CreateParser(100), nullptr);
}

// ============================================================================
// 参数设置函数测试
// ============================================================================

/// 测试：设置正常的 ADC 参数
TEST(XYParserApiTests, SetAdcParamsAcceptsValidValues)
{
    ParserGuard parser(XYParser_CreateParser(8));
    ASSERT_NE(parser.get(), nullptr);

    // 不应崩溃
    EXPECT_NO_THROW(XYParser_SetAdcParams(parser.get(), 4.5, 6.0));
}

/// 测试：设置边界值的 ADC 参数
TEST(XYParserApiTests, SetAdcParamsAcceptsBoundaryValues)
{
    ParserGuard parser(XYParser_CreateParser(8));
    ASSERT_NE(parser.get(), nullptr);

    // 测试零值
    EXPECT_NO_THROW(XYParser_SetAdcParams(parser.get(), 0.0, 0.0));
    // 测试较大值
    EXPECT_NO_THROW(XYParser_SetAdcParams(parser.get(), 100.0, 1000.0));
}

/// 测试：对空句柄调用 SetAdcParams
TEST(XYParserApiTests, SetAdcParamsOnNullHandle)
{
    // 不应崩溃
    EXPECT_NO_THROW(XYParser_SetAdcParams(nullptr, 4.5, 6.0));
}

/// 测试：关闭校验和绕过
TEST(XYParserApiTests, SetBypassChecksumOff)
{
    ParserGuard parser(XYParser_CreateParser(8));
    ASSERT_NE(parser.get(), nullptr);

    EXPECT_NO_THROW(XYParser_SetBypassChecksum(parser.get(), 0));
}

/// 测试：对空句柄调用 SetBypassChecksum
TEST(XYParserApiTests, SetBypassChecksumOnNullHandle)
{
    EXPECT_NO_THROW(XYParser_SetBypassChecksum(nullptr, 1));
}

// ============================================================================
// Feed 函数帧解析测试
// ============================================================================

/// 测试：传入空数据
TEST(XYParserApiTests, FeedParsesEmptyData)
{
    ParserGuard parser(XYParser_CreateParser(8));
    ASSERT_NE(parser.get(), nullptr);

    std::array<XYParserFrameSummary, 10> summaries{};
    const int result = XYParser_Feed(
        parser.get(),
        nullptr,
        0,
        summaries.data(),
        static_cast<int>(summaries.size()));

    EXPECT_EQ(result, 0);
}

/// 测试：只传入帧头数据
TEST(XYParserApiTests, FeedParsesOnlyHeader)
{
    ParserGuard parser(XYParser_CreateParser(8));
    ASSERT_NE(parser.get(), nullptr);

    XYParser_SetBypassChecksum(parser.get(), 1);

    // 只发送帧头
    const std::vector<std::uint8_t> header_only = {0xAA, 0x01, 0x00, 0x00, 0x00};
    std::array<XYParserFrameSummary, 10> summaries{};

    const int result = XYParser_Feed(
        parser.get(),
        header_only.data(),
        header_only.size(),
        summaries.data(),
        static_cast<int>(summaries.size()));

    EXPECT_EQ(result, 0);  // 数据不完整，不应解析出帧
}

/// 测试：解析完整的 64 通道帧
TEST(XYParserApiTests, FeedParses64ChannelFrame)
{
    ParserGuard parser(XYParser_CreateParser(64));
    ASSERT_NE(parser.get(), nullptr);

    XYParser_SetAdcParams(parser.get(), 4.5, 6.0);
    XYParser_SetBypassChecksum(parser.get(), 1);

    const std::vector<std::uint8_t> bytes = BuildMinimalFrame(64);
    std::array<XYParserFrameSummary, 1> summaries{};

    const int frame_count = XYParser_Feed(
        parser.get(),
        bytes.data(),
        bytes.size(),
        summaries.data(),
        static_cast<int>(summaries.size()));

    ASSERT_EQ(frame_count, 1);
    EXPECT_EQ(summaries[0].channel_count, 64U);
}

/// 测试：连续解析多个帧
TEST(XYParserApiTests, FeedParsesMultipleFrames)
{
    ParserGuard parser(XYParser_CreateParser(8));
    ASSERT_NE(parser.get(), nullptr);

    XYParser_SetBypassChecksum(parser.get(), 1);

    // 构建两个连续的帧
    const std::vector<std::uint8_t> frame1 = BuildMinimalFrame(8, 1U);
    const std::vector<std::uint8_t> frame2 = BuildMinimalFrame(8, 2U);

    std::vector<std::uint8_t> combined(frame1);
    combined.insert(combined.end(), frame2.begin(), frame2.end());

    std::array<XYParserFrameSummary, 10> summaries{};
    const int frame_count = XYParser_Feed(
        parser.get(),
        combined.data(),
        combined.size(),
        summaries.data(),
        static_cast<int>(summaries.size()));

    EXPECT_EQ(frame_count, 2);
    EXPECT_EQ(summaries[0].frame_index, 1U);
    EXPECT_EQ(summaries[1].frame_index, 2U);
}

/// 测试：帧索引递增
TEST(XYParserApiTests, FeedIncrementsFrameIndex)
{
    ParserGuard parser(XYParser_CreateParser(8));
    ASSERT_NE(parser.get(), nullptr);

    XYParser_SetBypassChecksum(parser.get(), 1);

    // 连续发送多个帧
    std::array<XYParserFrameSummary, 10> summaries{};
    int total_frames = 0;

    for (int i = 0; i < 3; ++i) {
        const std::vector<std::uint8_t> frame = BuildMinimalFrame(8, static_cast<std::uint32_t>(i + 1));
        const int count = XYParser_Feed(
            parser.get(),
            frame.data(),
            frame.size(),
            summaries.data() + total_frames,
            static_cast<int>(summaries.size()) - total_frames);
        total_frames += count;
    }

    EXPECT_EQ(total_frames, 3);
    for (int i = 0; i < 3; ++i) {
        EXPECT_EQ(summaries[i].frame_index, static_cast<std::uint32_t>(i + 1));
    }
}

/// 测试：电池电量字段解析
TEST(XYParserApiTests, FeedParsesBatteryValue)
{
    ParserGuard parser(XYParser_CreateParser(8));
    ASSERT_NE(parser.get(), nullptr);

    XYParser_SetBypassChecksum(parser.get(), 1);

    const std::vector<std::uint8_t> bytes = BuildMinimalFrame(8);
    std::array<XYParserFrameSummary, 1> summaries{};

    XYParser_Feed(
        parser.get(),
        bytes.data(),
        bytes.size(),
        summaries.data(),
        static_cast<int>(summaries.size()));

    EXPECT_EQ(summaries[0].battery, 95U);  // BuildMinimalFrame 中设置的电池电量
}

// ============================================================================
// 帧数据边界测试
// ============================================================================

/// 测试：跨多次 Feed 的不完整帧
TEST(XYParserApiTests, FeedHandlesIncompleteFrameAcrossMultipleFeeds)
{
    ParserGuard parser(XYParser_CreateParser(8));
    ASSERT_NE(parser.get(), nullptr);

    XYParser_SetBypassChecksum(parser.get(), 1);

    const std::vector<std::uint8_t> bytes = BuildMinimalFrame(8);
    std::array<XYParserFrameSummary, 1> summaries{};

    // 分成 3 次发送
    const std::size_t part1_size = bytes.size() / 3;
    const std::size_t part2_size = bytes.size() / 3;

    EXPECT_EQ(XYParser_Feed(parser.get(), bytes.data(), part1_size,
        summaries.data(), static_cast<int>(summaries.size())), 0);

    EXPECT_EQ(XYParser_Feed(parser.get(), bytes.data() + part1_size, part2_size,
        summaries.data(), static_cast<int>(summaries.size())), 0);

    const int result = XYParser_Feed(
        parser.get(),
        bytes.data() + part1_size + part2_size,
        bytes.size() - part1_size - part2_size,
        summaries.data(),
        static_cast<int>(summaries.size()));

    ASSERT_EQ(result, 1);
    EXPECT_EQ(summaries[0].frame_index, 1U);
}

// ============================================================================
// 销毁和错误处理测试
// ============================================================================

/// 测试：销毁空句柄
TEST(XYParserApiTests, DestroyParserAcceptsNullHandle)
{
    EXPECT_NO_THROW(XYParser_DestroyParser(nullptr));
}

/// 测试：连续创建和销毁
TEST(XYParserApiTests, CreateAndDestroyMultipleParsers)
{
    for (int i = 0; i < 10; ++i) {
        ParserGuard parser(XYParser_CreateParser(8));
        EXPECT_NE(parser.get(), nullptr);
    }
    // 析构时自动销毁所有解析器
}

/// 测试：GetLastError 在正常操作后
TEST(XYParserApiTests, GetLastErrorAfterSuccessfulCreate)
{
    ParserGuard parser(XYParser_CreateParser(8));
    ASSERT_NE(parser.get(), nullptr);

    // 正常操作后，错误信息应为空或无错误
    const char* error = XYParser_GetLastError(parser.get());
    // 错误信息可能为空或特定实现
    EXPECT_EQ(error, nullptr);
}


