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
)

# cpp-httplib - Header-only HTTP library
FetchContent_Declare(
    httplib
    GIT_REPOSITORY https://github.com/yhirose/cpp-httplib.git
    GIT_TAG v0.30.1
)

# jwt-cpp - Header-only JWT library
FetchContent_Declare(
    jwt-cpp
    GIT_REPOSITORY https://github.com/Thalhammer/jwt-cpp.git
    GIT_TAG v0.7.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
)

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

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

message(STATUS "Fetching cpp-httplib...")
set(HTTPLIB_REQUIRE_OPENSSL ON CACHE BOOL "" FORCE)
set(HTTPLIB_COMPILE OFF CACHE BOOL "" FORCE)  # Header-only mode
FetchContent_MakeAvailable(httplib)

message(STATUS "Fetching jwt-cpp...")
set(JWT_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(JWT_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(JWT_EXTERNAL_PICOJSON OFF CACHE BOOL "" FORCE)  # Use bundled picojson
FetchContent_MakeAvailable(jwt-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}")

# libwebsockets via pkg-config (system library)
find_package(PkgConfig REQUIRED)
pkg_check_modules(LWS REQUIRED IMPORTED_TARGET libwebsockets)

# OpenSSL for HTTPS support
find_package(OpenSSL REQUIRED)

# 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 "")
