cmake_minimum_required(VERSION 3.18)
project(bgbot LANGUAGES CXX CUDA)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_POSITION_INDEPENDENT_CODE ON)

option(BGBOT_BUILD_PYTHON "Build the pybind11 Python extension" ON)

# Optimization flags — compiler-specific
if(MSVC)
    set(BGBOT_OPT_FLAGS /O2 /fp:fast /GL /arch:AVX2)
    set(BGBOT_SAFE_OPT_FLAGS /O2)
elseif(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
    if(CMAKE_SYSTEM_PROCESSOR MATCHES "arm64|aarch64")
        set(BGBOT_OPT_FLAGS -O3 -funsafe-math-optimizations -fno-math-errno -funroll-loops)
    else()
        set(BGBOT_OPT_FLAGS -O3 -ffast-math -funroll-loops -mavx2 -mfma)
    endif()
    set(BGBOT_SAFE_OPT_FLAGS -O3 -funroll-loops)
endif()

# Core library (CPU only)
add_library(bgbot_lib STATIC
    src/board.cpp
    src/moves.cpp
    src/strategy.cpp
    src/pubeval.cpp
    src/game.cpp
    src/benchmark.cpp
    src/encoding.cpp
    src/neural_net.cpp
    src/training.cpp
    src/multipy.cpp
    src/rollout.cpp
    src/cube.cpp
    src/cube_eval.cpp
    src/match_equity.cpp
    src/bearoff.cpp
)
target_include_directories(bgbot_lib PUBLIC include)
target_compile_options(bgbot_lib PRIVATE ${BGBOT_OPT_FLAGS})

# Threading support
find_package(Threads REQUIRED)
target_link_libraries(bgbot_lib PUBLIC Threads::Threads)

# CUDA support — real GPU training via cuBLAS
find_package(CUDAToolkit REQUIRED)
add_library(bgbot_cuda STATIC src/cuda_nn.cu)
target_include_directories(bgbot_cuda PUBLIC include)
target_link_libraries(bgbot_cuda PUBLIC bgbot_lib CUDA::cublas CUDA::cudart)
set_target_properties(bgbot_cuda PROPERTIES CUDA_ARCHITECTURES "89")
target_compile_options(bgbot_cuda PRIVATE $<$<COMPILE_LANGUAGE:CUDA>:--allow-unsupported-compiler>)

# CUDA stub (provides cuda_available() = false, no-op cuda_supervised_train)
add_library(bgbot_cuda_stub STATIC src/cuda_nn_stub.cpp)
target_include_directories(bgbot_cuda_stub PUBLIC include)
target_link_libraries(bgbot_cuda_stub PUBLIC bgbot_lib)

# 4-ply cube profiler
add_executable(bgbot_profile_4ply src/profile_cube_4ply.cpp)
target_link_libraries(bgbot_profile_4ply PRIVATE bgbot_lib)

# Truncated rollout benchmark/profilers
add_executable(benchmark_truncated_rollout src/benchmark_truncated_rollout.cpp)
target_link_libraries(benchmark_truncated_rollout PRIVATE bgbot_lib)

add_executable(benchmark_3t src/benchmark_3t.cpp)
target_link_libraries(benchmark_3t PRIVATE bgbot_lib)

add_executable(benchmark_4ply src/benchmark_4ply.cpp)
target_link_libraries(benchmark_4ply PRIVATE bgbot_lib)

add_executable(benchmark_4ply_opt src/benchmark_4ply_opt.cpp)
target_link_libraries(benchmark_4ply_opt PRIVATE bgbot_lib)

add_executable(test_4ply_accuracy src/test_4ply_accuracy.cpp)
target_link_libraries(test_4ply_accuracy PRIVATE bgbot_lib)

add_executable(profile_3t src/profile_3t.cpp)
target_link_libraries(profile_3t PRIVATE bgbot_lib)

add_executable(profile_3t_detailed src/profile_3t_detailed.cpp)
target_link_libraries(profile_3t_detailed PRIVATE bgbot_lib)

add_executable(profile_cube_benchmark src/profile_cube_benchmark.cpp)
target_link_libraries(profile_cube_benchmark PRIVATE bgbot_lib)

add_executable(profile_nn_inference src/profile_nn_inference.cpp)
target_link_libraries(profile_nn_inference PRIVATE bgbot_lib)

if(BGBOT_BUILD_PYTHON)
    find_package(pybind11 CONFIG REQUIRED)
    pybind11_add_module(bgbot_cpp pybind/bindings.cpp)
    target_link_libraries(bgbot_cpp PRIVATE bgbot_lib bgbot_cuda)
endif()
