#include "NotificationModule.h"
#include <grove/JsonDataNode.h>

namespace celuna {

NotificationModule::NotificationModule() {
    m_logger = spdlog::get("NotificationModule");
    if (!m_logger) {
        m_logger = spdlog::stdout_color_mt("NotificationModule");
    }
    m_config = std::make_unique<grove::JsonDataNode>("config");
}

void NotificationModule::setConfiguration(const grove::IDataNode& configNode,
                                          grove::IIO* io,
                                          grove::ITaskScheduler* scheduler) {
    m_io = io;
    m_config = std::make_unique<grove::JsonDataNode>("config");

    // Charger la configuration
    m_language = configNode.getString("language", "fr");
    m_silentMode = configNode.getBool("silentMode", false);
    m_ttsEnabled = configNode.getBool("ttsEnabled", false);
    m_maxQueueSize = configNode.getInt("maxQueueSize", 50);

    m_logger->info("NotificationModule configuré: langue={}, silent={}, tts={}",
                  m_language, m_silentMode, m_ttsEnabled);
}

const grove::IDataNode& NotificationModule::getConfiguration() {
    return *m_config;
}

void NotificationModule::process(const grove::IDataNode& input) {
    // Traiter la file de notifications
    processNotificationQueue();
}

void NotificationModule::notify(const std::string& title, const std::string& message, Priority priority) {
    if (m_silentMode && priority != Priority::URGENT) {
        return;  // Ignorer les notifications non-urgentes en mode silencieux
    }

    Notification notif;
    notif.id = std::to_string(++m_notificationCount);
    notif.title = title;
    notif.message = message;
    notif.priority = priority;
    notif.language = m_language;
    notif.read = false;
    notif.timestamp = 0;  // Sera mis à jour lors du process

    // Limiter la taille de la queue
    while (static_cast<int>(m_pendingNotifications.size()) >= m_maxQueueSize) {
        m_pendingNotifications.pop();
    }

    m_pendingNotifications.push(notif);

    if (priority == Priority::URGENT) {
        m_urgentCount++;
    }
}

void NotificationModule::processNotificationQueue() {
    // Traiter jusqu'à 3 notifications par frame pour éviter le spam
    int processed = 0;
    while (!m_pendingNotifications.empty() && processed < 3) {
        Notification notif = m_pendingNotifications.front();
        m_pendingNotifications.pop();

        displayNotification(notif);
        processed++;
    }
}

void NotificationModule::displayNotification(const Notification& notif) {
    std::string emoji = priorityToEmoji(notif.priority);
    std::string priorityStr = priorityToString(notif.priority);

    // Affichage console (sera remplacé par Windows toast + TTS)
    switch (notif.priority) {
        case Priority::URGENT:
            m_logger->warn("{} [{}] {}: {}", emoji, priorityStr, notif.title, notif.message);
            break;
        case Priority::HIGH:
            m_logger->info("{} [{}] {}: {}", emoji, priorityStr, notif.title, notif.message);
            break;
        case Priority::NORMAL:
            m_logger->info("{} {}: {}", emoji, notif.title, notif.message);
            break;
        case Priority::LOW:
            m_logger->debug("{} {}: {}", emoji, notif.title, notif.message);
            break;
    }

    // TODO: Intégrer Windows Toast notifications
    // TODO: Intégrer TTS si m_ttsEnabled
}

std::string NotificationModule::priorityToString(Priority p) {
    switch (p) {
        case Priority::LOW:    return "INFO";
        case Priority::NORMAL: return "RAPPEL";
        case Priority::HIGH:   return "IMPORTANT";
        case Priority::URGENT: return "URGENT";
        default: return "?";
    }
}

std::string NotificationModule::priorityToEmoji(Priority p) {
    switch (p) {
        case Priority::LOW:    return "[i]";
        case Priority::NORMAL: return "[*]";
        case Priority::HIGH:   return "[!]";
        case Priority::URGENT: return "[!!!]";
        default: return "[ ]";
    }
}

std::unique_ptr<grove::IDataNode> NotificationModule::getHealthStatus() {
    auto status = std::make_unique<grove::JsonDataNode>("status");
    status->setString("status", "running");
    status->setInt("pendingCount", m_pendingNotifications.size());
    status->setInt("totalNotifications", m_notificationCount);
    status->setInt("urgentCount", m_urgentCount);
    status->setBool("silentMode", m_silentMode);
    return status;
}

void NotificationModule::shutdown() {
    // Vider la queue avant arrêt
    while (!m_pendingNotifications.empty()) {
        displayNotification(m_pendingNotifications.front());
        m_pendingNotifications.pop();
    }
    m_logger->info("NotificationModule arrêté. Total: {} notifications ({} urgentes)",
                  m_notificationCount, m_urgentCount);
}

std::unique_ptr<grove::IDataNode> NotificationModule::getState() {
    auto state = std::make_unique<grove::JsonDataNode>("state");

    state->setInt("notificationCount", m_notificationCount);
    state->setInt("urgentCount", m_urgentCount);
    state->setInt("pendingCount", m_pendingNotifications.size());

    m_logger->debug("État sauvegardé: {} notifications", m_notificationCount);
    return state;
}

void NotificationModule::setState(const grove::IDataNode& state) {
    m_notificationCount = state.getInt("notificationCount", 0);
    m_urgentCount = state.getInt("urgentCount", 0);
    // Note: On ne restaure pas la queue - les notifications en attente sont perdues au reload

    m_logger->info("État restauré: {} notifications historiques", m_notificationCount);
}

} // namespace celuna

#ifndef CELUNA_TEST_BUILD
extern "C" {

grove::IModule* createModule() {
    return new celuna::NotificationModule();
}

void destroyModule(grove::IModule* module) {
    delete module;
}

}
#endif
