cmake_minimum_required(VERSION 3.22)
cmake_policy(SET CMP0135 NEW)

project(smartbotic-crm
    VERSION 0.1.0
    DESCRIPTION "SmartBotic CRM System"
    LANGUAGES CXX
)

# C++20 standard
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

# Export compile commands for tooling
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# Build options
option(BUILD_TESTING "Build tests" ON)
option(ENABLE_SANITIZERS "Enable address and undefined behavior sanitizers" OFF)

# Compiler warnings - applied only to project targets, not dependencies
set(SMARTBOTIC_CXX_WARNINGS
    -Wall
    -Wextra
    -Wpedantic
    -Werror
    -Wno-unused-parameter
    -Wno-dangling-reference  # False positive in spdlog's bundled fmt with GCC 13+
)

# Sanitizers for debug builds
if(ENABLE_SANITIZERS)
    add_compile_options(-fsanitize=address,undefined)
    add_link_options(-fsanitize=address,undefined)
endif()

# Include FetchContent module
include(FetchContent)

# ============================================================================
# External Dependencies via FetchContent
# ============================================================================

# spdlog - Fast C++ logging library
FetchContent_Declare(
    spdlog
    GIT_REPOSITORY https://github.com/gabime/spdlog.git
    GIT_TAG v1.13.0
)

# nlohmann_json - JSON for Modern C++
FetchContent_Declare(
    nlohmann_json
    GIT_REPOSITORY https://github.com/nlohmann/json.git
    GIT_TAG v3.11.3
)

# yaml-cpp - YAML parser library
FetchContent_Declare(
    yaml-cpp
    GIT_REPOSITORY https://github.com/jbeder/yaml-cpp.git
    GIT_TAG 0.8.0
)

# gRPC and Protobuf
FetchContent_Declare(
    grpc
    GIT_REPOSITORY https://github.com/grpc/grpc.git
    GIT_TAG v1.60.0
    GIT_SHALLOW TRUE
)

# libsodium - Cryptography library
FetchContent_Declare(
    libsodium
    GIT_REPOSITORY https://github.com/jedisct1/libsodium.git
    GIT_TAG 1.0.19
)

# Boost - For Beast HTTP/WebSocket library
FetchContent_Declare(
    Boost
    URL https://github.com/boostorg/boost/releases/download/boost-1.86.0/boost-1.86.0-cmake.tar.xz
    URL_HASH SHA256=2c5ec5edcdff47ff55e27ed9560b0a0b94b07bd07ed9928b476150e16b0efc57
    DOWNLOAD_EXTRACT_TIMESTAMP TRUE
)

# Make dependencies available
message(STATUS "Fetching spdlog...")
FetchContent_MakeAvailable(spdlog)

message(STATUS "Fetching nlohmann_json...")
FetchContent_MakeAvailable(nlohmann_json)

message(STATUS "Fetching yaml-cpp...")
set(YAML_CPP_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(YAML_CPP_BUILD_TOOLS OFF CACHE BOOL "" FORCE)
set(YAML_CPP_BUILD_CONTRIB OFF CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(yaml-cpp)

message(STATUS "Fetching gRPC (this may take a while)...")
set(gRPC_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(gRPC_INSTALL OFF CACHE BOOL "" FORCE)
set(gRPC_BUILD_GRPC_CSHARP_PLUGIN OFF CACHE BOOL "" FORCE)
set(gRPC_BUILD_GRPC_NODE_PLUGIN OFF CACHE BOOL "" FORCE)
set(gRPC_BUILD_GRPC_OBJECTIVE_C_PLUGIN OFF CACHE BOOL "" FORCE)
set(gRPC_BUILD_GRPC_PHP_PLUGIN OFF CACHE BOOL "" FORCE)
set(gRPC_BUILD_GRPC_PYTHON_PLUGIN OFF CACHE BOOL "" FORCE)
set(gRPC_BUILD_GRPC_RUBY_PLUGIN OFF CACHE BOOL "" FORCE)
set(ABSL_ENABLE_INSTALL OFF CACHE BOOL "" FORCE)
set(ABSL_PROPAGATE_CXX_STD ON CACHE BOOL "" FORCE)
set(protobuf_INSTALL OFF CACHE BOOL "" FORCE)
set(utf8_range_ENABLE_INSTALL OFF CACHE BOOL "" FORCE)
# Disable -Werror for gRPC and its dependencies (abseil uses __int128 which triggers -Wpedantic)
set(CMAKE_CXX_FLAGS_BACKUP "${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-pedantic -Wno-overflow -Wno-error")
FetchContent_MakeAvailable(grpc)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_BACKUP}")

message(STATUS "Fetching Boost...")
set(BOOST_INCLUDE_LIBRARIES beast asio system)
set(BUILD_SHARED_LIBS OFF CACHE BOOL "" FORCE)
set(CMAKE_CXX_FLAGS_BACKUP2 "${CMAKE_CXX_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error")
FetchContent_MakeAvailable(Boost)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_BACKUP2}")

# libsodium requires special handling as it uses autotools
FetchContent_GetProperties(libsodium)
if(NOT libsodium_POPULATED)
    FetchContent_Populate(libsodium)

    # Build libsodium using autotools
    execute_process(
        COMMAND ${libsodium_SOURCE_DIR}/configure
                --prefix=${libsodium_BINARY_DIR}/install
                --disable-shared
                --enable-static
        WORKING_DIRECTORY ${libsodium_SOURCE_DIR}
        RESULT_VARIABLE SODIUM_CONFIGURE_RESULT
    )

    if(NOT SODIUM_CONFIGURE_RESULT EQUAL 0)
        message(WARNING "libsodium configure failed, will try system libsodium")
        find_package(PkgConfig REQUIRED)
        pkg_check_modules(SODIUM REQUIRED libsodium)
    else()
        execute_process(
            COMMAND make -j${CMAKE_BUILD_PARALLEL_LEVEL}
            WORKING_DIRECTORY ${libsodium_SOURCE_DIR}
        )
        execute_process(
            COMMAND make install
            WORKING_DIRECTORY ${libsodium_SOURCE_DIR}
        )

        set(SODIUM_INCLUDE_DIRS ${libsodium_BINARY_DIR}/install/include)
        set(SODIUM_LIBRARY_DIRS ${libsodium_BINARY_DIR}/install/lib)
        set(SODIUM_LIBRARIES sodium)
    endif()
endif()

# Create imported target for libsodium
add_library(sodium STATIC IMPORTED GLOBAL)
set_target_properties(sodium PROPERTIES
    IMPORTED_LOCATION ${SODIUM_LIBRARY_DIRS}/libsodium.a
    INTERFACE_INCLUDE_DIRECTORIES ${SODIUM_INCLUDE_DIRS}
)

# ============================================================================
# Project Subdirectories
# ============================================================================

add_subdirectory(common)
add_subdirectory(proto)
add_subdirectory(database)
add_subdirectory(webserver)
add_subdirectory(webui)

if(BUILD_TESTING)
    add_subdirectory(tests)
endif()

# ============================================================================
# Summary
# ============================================================================

message(STATUS "")
message(STATUS "SmartBotic CRM Configuration Summary")
message(STATUS "=====================================")
message(STATUS "Version:           ${PROJECT_VERSION}")
message(STATUS "C++ Standard:      ${CMAKE_CXX_STANDARD}")
message(STATUS "Build Type:        ${CMAKE_BUILD_TYPE}")
message(STATUS "Compiler:          ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION}")
message(STATUS "Build Testing:     ${BUILD_TESTING}")
message(STATUS "Sanitizers:        ${ENABLE_SANITIZERS}")
message(STATUS "")
