# SPDX-License-Identifier: MIT
cmake_minimum_required(VERSION 3.20)

project(clawdforge
    VERSION 0.1.0
    DESCRIPTION "C++ SDK for the clawdforge HTTP API"
    LANGUAGES CXX
)

# ---- options ----------------------------------------------------------------

option(CLAWDFORGE_BUILD_TESTS    "Build unit tests"   ON)
option(CLAWDFORGE_BUILD_EXAMPLES "Build examples"     ON)
option(CLAWDFORGE_WARNINGS_AS_ERRORS "Treat warnings as errors" ON)

# When consumed via add_subdirectory, default the extras off unless the user
# explicitly opts in. Top-level builds (the SDK's own CI / dev loop) keep them
# on so we exercise them.
if(NOT CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
    set(CLAWDFORGE_BUILD_TESTS OFF)
    set(CLAWDFORGE_BUILD_EXAMPLES OFF)
endif()

# ---- standard / flags -------------------------------------------------------

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
    set(CMAKE_BUILD_TYPE Release CACHE STRING "" FORCE)
endif()

include(CMakePackageConfigHelpers)
include(GNUInstallDirs)
include(FetchContent)

# ---- dependencies -----------------------------------------------------------

# nlohmann/json — try find_package first, fall back to FetchContent.
find_package(nlohmann_json 3.10 QUIET)
if(NOT nlohmann_json_FOUND)
    message(STATUS "clawdforge: nlohmann_json not installed, fetching v3.11.3")
    FetchContent_Declare(nlohmann_json
        GIT_REPOSITORY https://github.com/nlohmann/json.git
        GIT_TAG        v3.11.3
        GIT_SHALLOW    TRUE
    )
    set(JSON_BuildTests OFF CACHE INTERNAL "")
    set(JSON_Install ON CACHE INTERNAL "")
    FetchContent_MakeAvailable(nlohmann_json)
endif()

# libcurl — system-installed.
find_package(CURL REQUIRED)

# ---- library target ---------------------------------------------------------

add_library(clawdforge)
add_library(clawdforge::clawdforge ALIAS clawdforge)

target_sources(clawdforge
    PRIVATE
        src/client.cpp
        src/http.cpp
)

target_include_directories(clawdforge
    PUBLIC
        $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
        $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
    PRIVATE
        ${CMAKE_CURRENT_SOURCE_DIR}/src
)

target_link_libraries(clawdforge
    PUBLIC
        nlohmann_json::nlohmann_json
    PRIVATE
        CURL::libcurl
)

target_compile_features(clawdforge PUBLIC cxx_std_17)

set_target_properties(clawdforge PROPERTIES
    CXX_VISIBILITY_PRESET hidden
    VISIBILITY_INLINES_HIDDEN ON
    POSITION_INDEPENDENT_CODE ON
    VERSION   ${PROJECT_VERSION}
    SOVERSION ${PROJECT_VERSION_MAJOR}
    EXPORT_NAME clawdforge
)

# Warnings -- private so consumers don't inherit our flags.
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
    target_compile_options(clawdforge PRIVATE
        -Wall -Wextra -Wpedantic
        -Wshadow -Wconversion -Wsign-conversion
        -Wnon-virtual-dtor -Wold-style-cast
    )
    if(CLAWDFORGE_WARNINGS_AS_ERRORS)
        target_compile_options(clawdforge PRIVATE -Werror)
    endif()
elseif(MSVC)
    target_compile_options(clawdforge PRIVATE /W4 /permissive-)
    if(CLAWDFORGE_WARNINGS_AS_ERRORS)
        target_compile_options(clawdforge PRIVATE /WX)
    endif()
endif()

# ---- install ----------------------------------------------------------------

install(DIRECTORY include/clawdforge
    DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
    FILES_MATCHING PATTERN "*.hpp"
)

install(TARGETS clawdforge
    EXPORT  clawdforge-targets
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
)

install(EXPORT clawdforge-targets
    FILE        clawdforge-targets.cmake
    NAMESPACE   clawdforge::
    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/clawdforge
)

configure_package_config_file(
    cmake/clawdforge-config.cmake.in
    "${CMAKE_CURRENT_BINARY_DIR}/clawdforge-config.cmake"
    INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/clawdforge
)

write_basic_package_version_file(
    "${CMAKE_CURRENT_BINARY_DIR}/clawdforge-config-version.cmake"
    VERSION   ${PROJECT_VERSION}
    COMPATIBILITY SameMajorVersion
)

install(FILES
    "${CMAKE_CURRENT_BINARY_DIR}/clawdforge-config.cmake"
    "${CMAKE_CURRENT_BINARY_DIR}/clawdforge-config-version.cmake"
    DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/clawdforge
)

# ---- examples ---------------------------------------------------------------

if(CLAWDFORGE_BUILD_EXAMPLES)
    add_executable(clawdforge_basic_example examples/basic.cpp)
    target_link_libraries(clawdforge_basic_example PRIVATE clawdforge::clawdforge)
endif()

# ---- tests ------------------------------------------------------------------

if(CLAWDFORGE_BUILD_TESTS)
    enable_testing()

    # cpp-httplib for an in-process mock server. Prefer system / installed copy.
    # Test-only — never linked into the shipped library. Bumped from 0.15.3 to
    # 0.20.1 for clean dep graphs (0.15.x has several published advisories;
    # the SDK never exposes the mock to a network).
    find_package(httplib QUIET CONFIG)
    if(NOT httplib_FOUND)
        message(STATUS "clawdforge: cpp-httplib not installed, fetching v0.20.1")
        # The mock server doesn't need TLS / compression — disable optional
        # backends so we don't drag in zstd / brotli / openssl find_package
        # requirements for a test-only dep.
        set(HTTPLIB_USE_OPENSSL_IF_AVAILABLE OFF CACHE INTERNAL "")
        set(HTTPLIB_USE_ZLIB_IF_AVAILABLE    OFF CACHE INTERNAL "")
        set(HTTPLIB_USE_BROTLI_IF_AVAILABLE  OFF CACHE INTERNAL "")
        set(HTTPLIB_USE_ZSTD_IF_AVAILABLE    OFF CACHE INTERNAL "")
        FetchContent_Declare(cpp_httplib
            GIT_REPOSITORY https://github.com/yhirose/cpp-httplib.git
            GIT_TAG        v0.20.1
            GIT_SHALLOW    TRUE
        )
        FetchContent_MakeAvailable(cpp_httplib)
    endif()

    # doctest — single-header, fastest to compile of the popular options.
    find_package(doctest QUIET CONFIG)
    if(NOT doctest_FOUND)
        message(STATUS "clawdforge: doctest not installed, fetching v2.4.11")
        FetchContent_Declare(doctest
            GIT_REPOSITORY https://github.com/doctest/doctest.git
            GIT_TAG        v2.4.11
            GIT_SHALLOW    TRUE
        )
        FetchContent_MakeAvailable(doctest)
    endif()

    add_executable(clawdforge_tests
        tests/test_client.cpp
        tests/test_session.cpp
    )
    target_link_libraries(clawdforge_tests
        PRIVATE
            clawdforge::clawdforge
            httplib::httplib
            doctest::doctest
    )
    if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
        target_compile_options(clawdforge_tests PRIVATE
            -Wall -Wextra
            # Designated initializers in C++20 don't need to set every member.
            -Wno-missing-field-initializers
            # CHECK_THROWS_AS expands to a discarded-value expression; the
            # `[[nodiscard]]` on Client methods makes that legitimately noisy.
            -Wno-unused-result
        )
    endif()

    add_test(NAME clawdforge_tests COMMAND clawdforge_tests)
endif()
