// D:\Dev\Mosis\MosisService\designer\src\hot_reload.cpp
#include "hot_reload.h"
#include <iostream>

#ifdef _WIN32
#include <Windows.h>
#endif

namespace mosis {

HotReload::HotReload(const std::filesystem::path& watch_path, ReloadCallback callback)
    : m_watch_path(watch_path)
    , m_callback(std::move(callback))
{}

HotReload::~HotReload() {
    Stop();
}

void HotReload::Start() {
    if (m_running) return;

    m_running = true;
#ifdef _WIN32
    // Create a manual-reset event for signaling shutdown
    m_stop_event = CreateEventW(nullptr, TRUE, FALSE, nullptr);
    if (!m_stop_event) {
        std::cerr << "Failed to create stop event" << std::endl;
        m_running = false;
        return;
    }

    m_notification_handle = FindFirstChangeNotificationW(
        m_watch_path.c_str(),
        TRUE,  // Watch subtree
        FILE_NOTIFY_CHANGE_LAST_WRITE
    );

    if (m_notification_handle == INVALID_HANDLE_VALUE) {
        std::cerr << "Failed to set up file watching" << std::endl;
        CloseHandle(m_stop_event);
        m_stop_event = nullptr;
        m_running = false;
        return;
    }
#endif
    m_watch_thread = std::thread(&HotReload::WatchThread, this);
}

void HotReload::Stop() {
    m_running = false;
#ifdef _WIN32
    // Signal the stop event to wake up the watch thread
    if (m_stop_event) {
        SetEvent(m_stop_event);
    }
#endif
    if (m_watch_thread.joinable()) {
        m_watch_thread.join();
    }
#ifdef _WIN32
    if (m_notification_handle && m_notification_handle != INVALID_HANDLE_VALUE) {
        FindCloseChangeNotification(m_notification_handle);
        m_notification_handle = nullptr;
    }
    if (m_stop_event) {
        CloseHandle(m_stop_event);
        m_stop_event = nullptr;
    }
#endif
}

void HotReload::WatchThread() {
    while (m_running) {
#ifdef _WIN32
        // Wait on both the file change notification and the stop event
        HANDLE handles[2] = { m_notification_handle, m_stop_event };
        DWORD result = WaitForMultipleObjects(2, handles, FALSE, INFINITE);

        if (result == WAIT_OBJECT_0) {
            // File change notification
            // Debounce - wait a bit for file writes to complete
            std::this_thread::sleep_for(std::chrono::milliseconds(100));
            if (m_callback && m_running) {
                m_callback();
            }
            FindNextChangeNotification(m_notification_handle);
        } else if (result == WAIT_OBJECT_0 + 1) {
            // Stop event signaled - exit the loop
            break;
        }
        // WAIT_FAILED or other errors will just loop and check m_running
#else
        // TODO: Linux inotify / macOS FSEvents implementation
        std::this_thread::sleep_for(std::chrono::milliseconds(100));
#endif
    }
}

} // namespace mosis
