cmake_minimum_required(VERSION 3.20)
project(Aissia VERSION 0.2.0 LANGUAGES CXX)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Export compile commands for IDE support
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# ============================================================================
# GroveEngine Integration
# ============================================================================
set(GROVE_BUILD_TESTS OFF CACHE BOOL "Disable GroveEngine tests" FORCE)
add_subdirectory(external/GroveEngine)

# ============================================================================
# Dependencies
# ============================================================================

# SQLite3 - Use bundled amalgamation for MinGW compatibility
enable_language(C)  # SQLite is C code
add_library(sqlite3 STATIC
    ${CMAKE_CURRENT_SOURCE_DIR}/deps/sqlite/sqlite3.c
)
set_target_properties(sqlite3 PROPERTIES LINKER_LANGUAGE C)
target_include_directories(sqlite3 PUBLIC
    ${CMAKE_CURRENT_SOURCE_DIR}/deps/sqlite
)
target_compile_definitions(sqlite3 PRIVATE
    SQLITE_THREADSAFE=1
    SQLITE_ENABLE_FTS5
    SQLITE_ENABLE_JSON1
)
# Create alias to match find_package naming
add_library(SQLite::SQLite3 ALIAS sqlite3)

# OpenSSL for HTTPS (optional for MinGW)
find_package(OpenSSL QUIET)
if(NOT OPENSSL_FOUND)
    message(STATUS "OpenSSL not found - HTTPS features will be disabled")
endif()

# cpp-httplib (header-only HTTP client)
include(FetchContent)
FetchContent_Declare(
    httplib
    GIT_REPOSITORY https://github.com/yhirose/cpp-httplib.git
    GIT_TAG v0.14.1
)
FetchContent_MakeAvailable(httplib)

# ============================================================================
# Shared Libraries (used by services in main)
# ============================================================================

# LLM Providers Library
add_library(AissiaLLM STATIC
    src/shared/llm/LLMProviderFactory.cpp
    src/shared/llm/ClaudeProvider.cpp
    src/shared/llm/OpenAIProvider.cpp
    src/shared/llm/ToolRegistry.cpp
)
target_include_directories(AissiaLLM PUBLIC
    ${CMAKE_CURRENT_SOURCE_DIR}/src
    ${httplib_SOURCE_DIR}
)
target_link_libraries(AissiaLLM PUBLIC
    GroveEngine::impl
    spdlog::spdlog
)
if(OPENSSL_FOUND)
    target_link_libraries(AissiaLLM PUBLIC OpenSSL::SSL OpenSSL::Crypto)
    target_compile_definitions(AissiaLLM PRIVATE CPPHTTPLIB_OPENSSL_SUPPORT)
endif()

# Tools Library (Internal tools + FileSystem tools + MCP client + MCP server)
add_library(AissiaTools STATIC
    src/shared/tools/InternalTools.cpp
    src/shared/tools/FileSystemTools.cpp
    src/shared/mcp/StdioTransport.cpp
    src/shared/mcp/MCPClient.cpp
    src/shared/mcp/MCPServer.cpp
)
target_include_directories(AissiaTools PUBLIC
    ${CMAKE_CURRENT_SOURCE_DIR}/src
)
target_link_libraries(AissiaTools PUBLIC
    GroveEngine::impl
    spdlog::spdlog
)

# Platform Library (window tracking)
add_library(AissiaPlatform STATIC
    src/shared/platform/WindowTrackerFactory.cpp
)
target_include_directories(AissiaPlatform PUBLIC
    ${CMAKE_CURRENT_SOURCE_DIR}/src
)
target_link_libraries(AissiaPlatform PUBLIC
    spdlog::spdlog
)
if(WIN32)
    target_link_libraries(AissiaPlatform PUBLIC psapi)
endif()

# Audio Library (TTS/STT)
add_library(AissiaAudio STATIC
    src/shared/audio/TTSEngineFactory.cpp
    src/shared/audio/STTEngineFactory.cpp
    src/shared/audio/VoskSTTEngine.cpp
    src/shared/audio/PocketSphinxEngine.cpp
    src/shared/audio/WhisperCppEngine.cpp
)
target_include_directories(AissiaAudio PUBLIC
    ${CMAKE_CURRENT_SOURCE_DIR}/src
    ${httplib_SOURCE_DIR}
    ${nlohmann_json_SOURCE_DIR}/include
)
target_link_libraries(AissiaAudio PUBLIC
    spdlog::spdlog
)
if(OPENSSL_FOUND)
    target_link_libraries(AissiaAudio PUBLIC OpenSSL::SSL OpenSSL::Crypto)
    target_compile_definitions(AissiaAudio PRIVATE CPPHTTPLIB_OPENSSL_SUPPORT)
endif()
if(WIN32)
    target_link_libraries(AissiaAudio PUBLIC sapi ole32)
endif()

# Optional: Link Vosk if available (Phase 7 STT)
find_library(VOSK_LIBRARY vosk)
if(VOSK_LIBRARY)
    message(STATUS "Vosk found: ${VOSK_LIBRARY}")
    target_link_libraries(AissiaAudio PUBLIC ${VOSK_LIBRARY})
    target_compile_definitions(AissiaAudio PRIVATE HAS_VOSK)
else()
    message(STATUS "Vosk not found - STT will use fallback engines only")
endif()

# ============================================================================
# Infrastructure Services Library (linked into main)
# ============================================================================
add_library(AissiaServices STATIC
    src/services/LLMService.cpp
    src/services/StorageService.cpp
    src/services/PlatformService.cpp
    src/services/VoiceService.cpp
    src/services/STTService.cpp
)
target_include_directories(AissiaServices PUBLIC
    ${CMAKE_CURRENT_SOURCE_DIR}/src
)
target_link_libraries(AissiaServices PUBLIC
    GroveEngine::impl
    spdlog::spdlog
    AissiaLLM
    AissiaTools
    AissiaPlatform
    AissiaAudio
    SQLite::SQLite3
)

# ============================================================================
# Main Executable (with services)
# ============================================================================
add_executable(aissia
    src/main.cpp
)

target_link_libraries(aissia PRIVATE
    GroveEngine::impl
    spdlog::spdlog
    AissiaServices
)

target_include_directories(aissia PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}/src
)

# ============================================================================
# Hot-Reloadable Modules (.so) - Pure business logic only
# ============================================================================

# SchedulerModule - Gestion du temps et detection hyperfocus
add_library(SchedulerModule SHARED
    src/modules/SchedulerModule.cpp
)
target_link_libraries(SchedulerModule PRIVATE
    GroveEngine::impl
    spdlog::spdlog
)
set_target_properties(SchedulerModule PROPERTIES
    PREFIX "lib"
    LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/modules
)

# NotificationModule - Alertes systeme
add_library(NotificationModule SHARED
    src/modules/NotificationModule.cpp
)
target_link_libraries(NotificationModule PRIVATE
    GroveEngine::impl
    spdlog::spdlog
)
set_target_properties(NotificationModule PROPERTIES
    PREFIX "lib"
    LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/modules
)

# StorageModule - Pure logic, no SQLite (uses StorageService via IIO)
add_library(StorageModule SHARED
    src/modules/StorageModule.cpp
)
target_include_directories(StorageModule PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
target_link_libraries(StorageModule PRIVATE
    GroveEngine::impl
    spdlog::spdlog
)
set_target_properties(StorageModule PROPERTIES
    PREFIX "lib"
    LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/modules
)

# MonitoringModule - Pure logic, no Win32 (uses PlatformService via IIO)
add_library(MonitoringModule SHARED
    src/modules/MonitoringModule.cpp
)
target_include_directories(MonitoringModule PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
target_link_libraries(MonitoringModule PRIVATE
    GroveEngine::impl
    spdlog::spdlog
)
set_target_properties(MonitoringModule PROPERTIES
    PREFIX "lib"
    LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/modules
)

# AIModule - Pure logic, no HTTP (uses LLMService via IIO)
add_library(AIModule SHARED
    src/modules/AIModule.cpp
)
target_include_directories(AIModule PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
target_link_libraries(AIModule PRIVATE
    GroveEngine::impl
    spdlog::spdlog
)
set_target_properties(AIModule PROPERTIES
    PREFIX "lib"
    LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/modules
)

# VoiceModule - Pure logic, no TTS (uses VoiceService via IIO)
add_library(VoiceModule SHARED
    src/modules/VoiceModule.cpp
)
target_include_directories(VoiceModule PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
target_link_libraries(VoiceModule PRIVATE
    GroveEngine::impl
    spdlog::spdlog
)
set_target_properties(VoiceModule PROPERTIES
    PREFIX "lib"
    LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/modules
)

# WebModule - HTTP requests via HttpClient
add_library(WebModule SHARED
    src/modules/WebModule.cpp
)
target_include_directories(WebModule PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}/src
    ${httplib_SOURCE_DIR}
)
target_link_libraries(WebModule PRIVATE
    GroveEngine::impl
    spdlog::spdlog
)
if(OPENSSL_FOUND)
    target_link_libraries(WebModule PRIVATE OpenSSL::SSL OpenSSL::Crypto)
    target_compile_definitions(WebModule PRIVATE CPPHTTPLIB_OPENSSL_SUPPORT)
endif()
set_target_properties(WebModule PROPERTIES
    PREFIX "lib"
    LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/modules
)

# ============================================================================
# Copy config files to build directory
# ============================================================================
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/config/
     DESTINATION ${CMAKE_BINARY_DIR}/config)

# ============================================================================
# Development targets
# ============================================================================

# TestRunnerModule - Orchestrator for integration tests
add_library(TestRunnerModule SHARED
    src/modules/TestRunnerModule.cpp
)
target_include_directories(TestRunnerModule PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
target_link_libraries(TestRunnerModule PRIVATE
    GroveEngine::impl
    spdlog::spdlog
    ${CMAKE_DL_LIBS}
)
set_target_properties(TestRunnerModule PROPERTIES
    PREFIX "lib"
    LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/modules
)

# Quick rebuild of modules only (for hot-reload workflow)
add_custom_target(modules
    DEPENDS SchedulerModule NotificationModule StorageModule MonitoringModule AIModule VoiceModule WebModule TestRunnerModule
    COMMENT "Building hot-reloadable modules only"
)

# Create data directory
file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/data)

# Run Aissia
add_custom_target(run
    COMMAND $<TARGET_FILE:aissia>
    DEPENDS aissia modules
    WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
    COMMENT "Running Aissia"
)

# ============================================================================
# Tests (optional, enabled with BUILD_TESTING=ON)
# ============================================================================
option(BUILD_TESTING "Build integration tests" OFF)
if(BUILD_TESTING)
    add_subdirectory(tests)
endif()
