#include "PlatformService.hpp"

#include <spdlog/sinks/stdout_color_sinks.h>

namespace celuna {

PlatformService::PlatformService() {
    m_logger = spdlog::get("PlatformService");
    if (!m_logger) {
        m_logger = spdlog::stdout_color_mt("PlatformService");
    }
}

bool PlatformService::initialize(grove::IIO* io) {
    m_io = io;

    // Create platform-specific window tracker
    m_tracker = WindowTrackerFactory::create();

    if (!m_tracker || !m_tracker->isAvailable()) {
        m_logger->warn("Window tracker not available on this platform");
        return true; // Non-fatal, module can work without tracking
    }

    if (m_io) {
        grove::SubscriptionConfig config;
        m_io->subscribe("platform:query_window", config);
    }

    m_logger->info("PlatformService initialized: {}", m_tracker->getPlatformName());
    return true;
}

void PlatformService::configure(int pollIntervalMs, int idleThresholdSeconds) {
    m_pollIntervalMs = pollIntervalMs;
    m_idleThresholdSeconds = idleThresholdSeconds;
    m_logger->debug("Configured: poll={}ms, idle={}s", pollIntervalMs, idleThresholdSeconds);
}

void PlatformService::process() {
    if (!m_tracker || !m_tracker->isAvailable()) return;

    // Use monotonic clock for timing
    static auto startTime = std::chrono::steady_clock::now();
    auto now = std::chrono::steady_clock::now();
    float currentTime = std::chrono::duration<float>(now - startTime).count();

    float pollIntervalSec = m_pollIntervalMs / 1000.0f;
    if (currentTime - m_lastPollTime >= pollIntervalSec) {
        m_lastPollTime = currentTime;
        pollWindowInfo(currentTime);
    }

    // Handle query requests
    if (m_io) {
        while (m_io->hasMessages() > 0) {
            auto msg = m_io->pullMessage();
            if (msg.topic == "platform:query_window") {
                publishWindowInfo();
            }
        }
    }
}

void PlatformService::pollWindowInfo(float currentTime) {
    std::string newApp = m_tracker->getCurrentAppName();
    std::string newTitle = m_tracker->getCurrentWindowTitle();

    // Check for app change
    if (newApp != m_currentApp) {
        int duration = static_cast<int>(currentTime - m_appStartTime);

        if (!m_currentApp.empty() && duration > 0) {
            publishWindowChanged(m_currentApp, newApp, duration);
        }

        m_currentApp = newApp;
        m_currentWindowTitle = newTitle;
        m_appStartTime = currentTime;

        m_logger->debug("App: {} - {}", m_currentApp,
                       m_currentWindowTitle.size() > 50 ?
                       m_currentWindowTitle.substr(0, 50) + "..." : m_currentWindowTitle);
    }

    // Check idle state
    bool isIdle = m_tracker->isUserIdle(m_idleThresholdSeconds);

    if (isIdle && !m_wasIdle) {
        m_logger->info("User idle detected ({}s)", m_idleThresholdSeconds);
        if (m_io) {
            auto event = std::make_unique<grove::JsonDataNode>("idle");
            event->setInt("idleSeconds", m_tracker->getIdleTimeSeconds());
            m_io->publish("platform:idle_detected", std::move(event));
        }
    }
    else if (!isIdle && m_wasIdle) {
        m_logger->info("User activity resumed");
        if (m_io) {
            auto event = std::make_unique<grove::JsonDataNode>("active");
            m_io->publish("platform:activity_resumed", std::move(event));
        }
    }

    m_wasIdle = isIdle;

    // Publish periodic window info
    publishWindowInfo();
}

void PlatformService::publishWindowInfo() {
    if (!m_io || !m_tracker) return;

    auto event = std::make_unique<grove::JsonDataNode>("window");
    event->setString("appName", m_currentApp);
    event->setString("windowTitle", m_currentWindowTitle);
    event->setBool("isIdle", m_wasIdle);
    event->setInt("idleSeconds", m_tracker->getIdleTimeSeconds());
    m_io->publish("platform:window_info", std::move(event));
}

void PlatformService::publishWindowChanged(const std::string& oldApp,
                                           const std::string& newApp,
                                           int duration) {
    if (!m_io) return;

    auto event = std::make_unique<grove::JsonDataNode>("changed");
    event->setString("oldApp", oldApp);
    event->setString("newApp", newApp);
    event->setInt("duration", duration);
    m_io->publish("platform:window_changed", std::move(event));
}

void PlatformService::shutdown() {
    m_tracker.reset();
    m_logger->info("PlatformService shutdown");
}

} // namespace celuna
