cmake_minimum_required(VERSION 3.16)
project(BlueZSDKUnitTests LANGUAGES CXX)

# 定义项目根目录变量，供所有子目录使用
set(PROJECT_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/..)

# 查找 Qt5 所需模块
find_package(Qt5 REQUIRED COMPONENTS Core Test DBus Quick X11Extras)
# 根据测试实际需要添加其他模块（如 Widgets、Qml、DBus）
find_package(Qt5 COMPONENTS Widgets Qml Quick)

find_package(GTest REQUIRED)

find_package(PkgConfig REQUIRED)
pkg_check_modules(GSETTINGS_QT REQUIRED gsettings-qt)
pkg_check_modules(GIO REQUIRED gio-2.0)
pkg_check_modules(KYSDK_SYSINFO REQUIRED kysdk-sysinfo)
pkg_check_modules(PEONY REQUIRED peony)
pkg_check_modules(X11 REQUIRED x11)
pkg_check_modules(XI REQUIRED xi)

# 设置 C++ 标准（与原 qmake 项目保持一致）
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# 自动处理 Qt 的 moc、rcc、uic
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_AUTOUIC ON)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fprofile-arcs -ftest-coverage")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -lgcov --coverage")

# 全局包含路径（假设公共头文件位于各个子目录）
include_directories(
    ${PROJECT_ROOT_DIR}/bluezsdk
    ${PROJECT_ROOT_DIR}/service
    ${PROJECT_ROOT_DIR}/ukui-shortcut-bluetooth/plugin
)

file(GLOB ALL_BLUEZSDK_SOURCES "${PROJECT_ROOT_DIR}/bluezsdk/*.cpp")
# 从列表中移除 main.cpp
list(REMOVE_ITEM ALL_BLUEZSDK_SOURCES "${PROJECT_ROOT_DIR}/bluezsdk/main.cpp")

file(GLOB ALL_SERVICE_SOURCES "${PROJECT_ROOT_DIR}/service/*.cpp")
# 从列表中移除 main.cpp
list(REMOVE_ITEM ALL_SERVICE_SOURCES "${PROJECT_ROOT_DIR}/service/main.cpp")

file(GLOB ALL_SHORTCUT_SOURCES "${PROJECT_ROOT_DIR}/ukui-shortcut-bluetooth/plugin/*.cpp")


# ========== 启用测试 ==========
enable_testing()

# ========== 辅助函数：添加单元测试 ==========
function(add_bluezsdk_unit_test TEST_NAME TEST_DIR)
    file(GLOB TEST_SOURCES "${TEST_DIR}/*.cpp")

    list(FILTER TEST_SOURCES EXCLUDE REGEX "main\\.cpp$")
    set(MAIN_SRC "${TEST_DIR}/main.cpp")
    if(NOT EXISTS ${MAIN_SRC})
        message(FATAL_ERROR "main.cpp not found in ${TEST_DIR}")
    endif()

    file(GLOB TEST_HEADERS "${TEST_DIR}/*.h") 

    # 创建可执行文件
    add_executable(${TEST_NAME} ${MAIN_SRC} ${TEST_SOURCES} ${TEST_HEADERS}  ${ALL_BLUEZSDK_SOURCES})

    # 包含目录
    target_include_directories(${TEST_NAME} PRIVATE
        ${TEST_DIR}
        ${PROJECT_ROOT_DIR}/bluezsdk
        ${PROJECT_ROOT_DIR}/service
    )

    # 链接库
    target_link_libraries(${TEST_NAME}
        Qt5::Core
        Qt5::Test
        Qt5::DBus
        GTest::gtest
        Threads::Threads
        gcov
    )

    # 定义 GTEST 宏（避免旧版本警告）
    target_compile_definitions(${TEST_NAME} PRIVATE GTEST_LANG_CXX14=1)
    target_compile_definitions(${TEST_NAME} PRIVATE UNIT_TEST_MODE)

    # 输出目录
    set_target_properties(${TEST_NAME} PROPERTIES
        RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
    )

    # 注册到 CTest
    add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME})
endfunction()

# 添加所有测试子目录
# SDK 层测试
add_bluezsdk_unit_test(test_agentrequstreply          ${CMAKE_CURRENT_SOURCE_DIR}/bluezsdk/agentrequstreply)
add_bluezsdk_unit_test(test_bluetoothadapter          ${CMAKE_CURRENT_SOURCE_DIR}/bluezsdk/bluetoothadapter)
add_bluezsdk_unit_test(test_bluetoothdevice           ${CMAKE_CURRENT_SOURCE_DIR}/bluezsdk/bluetoothdevice)
add_bluezsdk_unit_test(test_bluetoothfile             ${CMAKE_CURRENT_SOURCE_DIR}/bluezsdk/bluetoothfile)
add_bluezsdk_unit_test(test_bluetoothfileagent        ${CMAKE_CURRENT_SOURCE_DIR}/bluezsdk/bluetoothfileagent)
add_bluezsdk_unit_test(test_bluetoothfilemanager      ${CMAKE_CURRENT_SOURCE_DIR}/bluezsdk/bluetoothfilemanager)
add_bluezsdk_unit_test(test_bluetoothlistener         ${CMAKE_CURRENT_SOURCE_DIR}/bluezsdk/bluetoothlistener)
add_bluezsdk_unit_test(test_bluezagent                ${CMAKE_CURRENT_SOURCE_DIR}/bluezsdk/bluezagent)
add_bluezsdk_unit_test(test_bluetoothadaptermanager   ${CMAKE_CURRENT_SOURCE_DIR}/bluezsdk/test_bluetoothadaptermanager)
add_bluezsdk_unit_test(test_bluetoothobexsess         ${CMAKE_CURRENT_SOURCE_DIR}/bluezsdk/bluetoothobexsess)
add_bluezsdk_unit_test(test_bluetoothobextransfer     ${CMAKE_CURRENT_SOURCE_DIR}/bluezsdk/bluetoothobextransfer)
add_bluezsdk_unit_test(test_kylincommon               ${CMAKE_CURRENT_SOURCE_DIR}/bluezsdk/test_kylincommon)
add_bluezsdk_unit_test(test_sdkinterface              ${CMAKE_CURRENT_SOURCE_DIR}/bluezsdk/test_sdkinterface)
add_bluezsdk_unit_test(test_bluezbluetoothinterface   ${CMAKE_CURRENT_SOURCE_DIR}/bluezsdk/test_bluetoothinterface)

function(add_service_unit_test TEST_NAME TEST_DIR)
    file(GLOB TEST_SOURCES "${TEST_DIR}/*.cpp")

    list(FILTER TEST_SOURCES EXCLUDE REGEX "main\\.cpp$")
    set(MAIN_SRC "${TEST_DIR}/main.cpp")
    if(NOT EXISTS ${MAIN_SRC})
        message(FATAL_ERROR "main.cpp not found in ${TEST_DIR}")
    endif()

    file(GLOB TEST_HEADERS "${TEST_DIR}/*.h") 

    # 创建可执行文件
    add_executable(${TEST_NAME} ${MAIN_SRC} ${TEST_SOURCES} ${TEST_HEADERS} ${ALL_SERVICE_SOURCES} ${ALL_BLUEZSDK_SOURCES})

    # 包含目录
    target_include_directories(${TEST_NAME} PRIVATE
        ${TEST_DIR}
        ${PROJECT_ROOT_DIR}/bluezsdk
        ${PROJECT_ROOT_DIR}/service
        ${PROJECT_ROOT_DIR}/ukui-shortcut-bluetooth/plugin
        ${GSETTINGS_QT_INCLUDE_DIRS}
        ${GIO_INCLUDE_DIRS}
        ${KYSDK_SYSINFO_INCLUDE_DIRS}
        ${PEONY_INCLUDE_DIRS}
    )

    # 链接库
    target_link_libraries(${TEST_NAME}
        Qt5::Core
        Qt5::Test
        Qt5::DBus
        GTest::gtest
        Threads::Threads
        ${GSETTINGS_QT_LIBRARIES}
        ${GIO_LIBRARIES}
        ${KYSDK_SYSINFO_LIBRARIES}
        ${PEONY_LIBRARIES}
        pthread
        glib-2.0
        gcov
    )

    target_link_libraries(${TEST_NAME} gcov)

    # 定义 GTEST 宏（避免旧版本警告）
    target_compile_definitions(${TEST_NAME} PRIVATE GTEST_LANG_CXX14=1)
    target_compile_definitions(${TEST_NAME} PRIVATE UNIT_TEST_MODE)

    # 输出目录
    set_target_properties(${TEST_NAME} PROPERTIES
        RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
    )

    # 注册到 CTest
    add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME})
endfunction()

# Service 层测试
set(SERVICE_TEST_DIRS
    service/bluetoothagent
    service/bluetoothobexagent
    service/buriedpointdata
    service/common
    service/config
    service/leavelock
    service/sessiondbusregister
    service/test_daemon
    service/test_device
    service/systemadapter
    service/test_adapter
    service/test_enginedetectsensitivefile
    service/test_app
    service/test_filesess
)
foreach(dir ${SERVICE_TEST_DIRS})
    get_filename_component(TEST_NAME ${dir} NAME)
    add_service_unit_test(testservice_${TEST_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/${dir})
endforeach()


function(add_shortcut_unit_test TEST_NAME TEST_DIR)
    file(GLOB TEST_SOURCES "${TEST_DIR}/*.cpp")

    list(FILTER TEST_SOURCES EXCLUDE REGEX "main\\.cpp$")
    set(MAIN_SRC "${TEST_DIR}/main.cpp")
    if(NOT EXISTS ${MAIN_SRC})
        message(FATAL_ERROR "main.cpp not found in ${TEST_DIR}")
    endif()

    file(GLOB TEST_HEADERS "${TEST_DIR}/*.h") 

    # 创建可执行文件
    add_executable(${TEST_NAME} ${MAIN_SRC} ${TEST_SOURCES} ${TEST_HEADERS}  ${ALL_SHORTCUT_SOURCES})

    # 包含目录
    target_include_directories(${TEST_NAME} PRIVATE
        ${TEST_DIR}
        ${PROJECT_ROOT_DIR}/bluezsdk
        ${PROJECT_ROOT_DIR}/service
        ${PROJECT_ROOT_DIR}/ukui-shortcut-bluetooth/plugin
    )

    # 链接库
    target_link_libraries(${TEST_NAME}
        Qt5::Core
        Qt5::Test
        Qt5::DBus
        Qt5::Quick
        Qt5::X11Extras
        GTest::gtest
        Threads::Threads
        gcov
        ukui-log4qt
        ${X11_LIBRARIES}
        ${XI_LIBRARIES}
    )

    # 定义 GTEST 宏（避免旧版本警告）
    target_compile_definitions(${TEST_NAME} PRIVATE GTEST_LANG_CXX14=1)
    target_compile_definitions(${TEST_NAME} PRIVATE UNIT_TEST_MODE)

    # 输出目录
    set_target_properties(${TEST_NAME} PROPERTIES
        RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
    )

    # 注册到 CTest
    add_test(NAME ${TEST_NAME} COMMAND ${TEST_NAME})
endfunction()

# Plugin 层测试
add_shortcut_unit_test(testplugin_bluetoothinterface          ${CMAKE_CURRENT_SOURCE_DIR}/ukui-shortcut-bluetooth/plugin/bluetoothinterface)
add_shortcut_unit_test(testplugin_bluetoothqml_plugin         ${CMAKE_CURRENT_SOURCE_DIR}/ukui-shortcut-bluetooth/plugin/bluetoothqml_plugin)
add_shortcut_unit_test(testplugin_commontool                  ${CMAKE_CURRENT_SOURCE_DIR}/ukui-shortcut-bluetooth/plugin/commontool)
add_shortcut_unit_test(testplugin_test_platformadaptor        ${CMAKE_CURRENT_SOURCE_DIR}/ukui-shortcut-bluetooth/plugin/test_platformadaptor)
add_shortcut_unit_test(testplugin_test_devicemanager          ${CMAKE_CURRENT_SOURCE_DIR}/ukui-shortcut-bluetooth/plugin/test_devicemanager)

# ========== 覆盖率目标 ==========
add_custom_target(coverage
    COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/coverage-report
    # 运行所有测试（确保生成 .gcda 文件）
    COMMAND ${CMAKE_CTEST_COMMAND} --output-on-failure
    # 使用 gcovr 生成报告
    COMMAND gcovr -r ${PROJECT_ROOT_DIR} --xml -o ${CMAKE_BINARY_DIR}/coverage-report/coverage.xml
    COMMAND gcovr -r ${PROJECT_ROOT_DIR} --html --html-details -o ${CMAKE_BINARY_DIR}/coverage-report/coverage.html
    WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
    COMMENT "Generating coverage report with gcovr"
)