#include "VoiceModule.h"
#include <grove/IIO.h>
#include <grove/JsonDataNode.h>

namespace celuna {

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

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

    // TTS config - support both nested and flat formats
    auto* ttsNode = const_cast<grove::IDataNode&>(configNode).getChildReadOnly("tts");
    if (ttsNode) {
        m_ttsEnabled = ttsNode->getBool("enabled", true);
    } else {
        // Fallback to flat format for tests
        m_ttsEnabled = configNode.getBool("ttsEnabled", true);
    }

    // STT config - support both nested and flat formats
    auto* sttNode = const_cast<grove::IDataNode&>(configNode).getChildReadOnly("stt");
    if (sttNode) {
        m_sttEnabled = sttNode->getBool("enabled", true);
        m_language = sttNode->getString("language", "fr");
    } else {
        // Fallback to flat format for tests
        m_sttEnabled = configNode.getBool("sttEnabled", true);
        m_language = configNode.getString("language", "fr");
    }

    // Subscribe to topics
    if (m_io) {
        grove::SubscriptionConfig subConfig;
        m_io->subscribe("ai:response", subConfig);
        m_io->subscribe("ai:suggestion", subConfig);
        m_io->subscribe("notification:speak", subConfig);
        m_io->subscribe("voice:speaking_started", subConfig);
        m_io->subscribe("voice:speaking_ended", subConfig);
        m_io->subscribe("voice:transcription", subConfig);
        // Tool request handlers
        m_io->subscribe("voice:command", subConfig);
    }

    m_logger->info("VoiceModule configure (v2 - sans infrastructure): TTS={}, STT={}",
                  m_ttsEnabled, m_sttEnabled);
}

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

void VoiceModule::process(const grove::IDataNode& input) {
    processMessages();
}

void VoiceModule::processMessages() {
    if (!m_io) return;

    while (m_io->hasMessages() > 0) {
        auto msg = m_io->pullMessage();

        if (msg.topic == "ai:response" && msg.data) {
            handleAIResponse(*msg.data);
        }
        else if (msg.topic == "ai:suggestion" && msg.data) {
            handleSuggestion(*msg.data);
        }
        else if (msg.topic == "notification:speak" && msg.data) {
            handleNotificationSpeak(*msg.data);
        }
        else if (msg.topic == "voice:speaking_started" && msg.data) {
            handleSpeakingStarted(*msg.data);
        }
        else if (msg.topic == "voice:speaking_ended" && msg.data) {
            handleSpeakingEnded(*msg.data);
        }
        else if (msg.topic == "voice:transcription" && msg.data) {
            handleTranscription(*msg.data);
        }
        // Tool command handler
        else if (msg.topic == "voice:command" && msg.data) {
            handleToolCommand(*msg.data);
        }
    }
}

void VoiceModule::handleToolCommand(const grove::IDataNode& request) {
    std::string action = request.getString("action", "");

    if (action == "speak") {
        std::string text = request.getString("text", "");
        std::string priority = request.getString("priority", "normal");

        if (!text.empty()) {
            bool isPriority = (priority == "high");
            requestSpeak(text, isPriority);
            m_logger->info("Tool speak: {} (priority={})", text.substr(0, 50), priority);
        }
    }
}

void VoiceModule::requestSpeak(const std::string& text, bool priority) {
    if (!m_io || !m_ttsEnabled || text.empty()) return;

    auto request = std::make_unique<grove::JsonDataNode>("speak");
    request->setString("text", text);
    request->setBool("priority", priority);
    m_io->publish("voice:speak", std::move(request));

    m_logger->debug("Speak request: {} (priority={})",
                   text.size() > 50 ? text.substr(0, 50) + "..." : text, priority);
}

void VoiceModule::handleAIResponse(const grove::IDataNode& data) {
    if (!m_ttsEnabled) return;

    std::string text = data.getString("text", "");
    if (!text.empty()) {
        requestSpeak(text, false);
    }
}

void VoiceModule::handleSuggestion(const grove::IDataNode& data) {
    if (!m_ttsEnabled) return;

    std::string message = data.getString("message", "");
    if (!message.empty()) {
        // Suggestions are priority messages
        requestSpeak(message, true);
    }
}

void VoiceModule::handleNotificationSpeak(const grove::IDataNode& data) {
    if (!m_ttsEnabled) return;

    std::string message = data.getString("message", "");
    if (!message.empty()) {
        requestSpeak(message, false);
    }
}

void VoiceModule::handleSpeakingStarted(const grove::IDataNode& data) {
    m_isSpeaking = true;
    m_totalSpoken++;
    std::string text = data.getString("text", "");
    m_logger->debug("Speaking started: {}", text.size() > 30 ? text.substr(0, 30) + "..." : text);
}

void VoiceModule::handleSpeakingEnded(const grove::IDataNode& data) {
    m_isSpeaking = false;
    m_logger->debug("Speaking ended");
}

void VoiceModule::handleTranscription(const grove::IDataNode& data) {
    std::string text = data.getString("text", "");
    float confidence = data.getDouble("confidence", 0.0);

    if (!text.empty()) {
        m_totalTranscribed++;
        m_logger->info("Transcription: {} (conf={:.2f})", text, confidence);

        // Forward to AI module
        if (m_io) {
            auto event = std::make_unique<grove::JsonDataNode>("query");
            event->setString("query", text);
            event->setString("source", "voice");
            m_io->publish("ai:query", std::move(event));
        }
    }
}

std::unique_ptr<grove::IDataNode> VoiceModule::getHealthStatus() {
    auto status = std::make_unique<grove::JsonDataNode>("status");
    status->setString("status", "running");
    status->setBool("ttsEnabled", m_ttsEnabled);
    status->setBool("sttEnabled", m_sttEnabled);
    status->setBool("isSpeaking", m_isSpeaking);
    status->setInt("totalSpoken", m_totalSpoken);
    status->setInt("totalTranscribed", m_totalTranscribed);
    return status;
}

void VoiceModule::shutdown() {
    m_logger->info("VoiceModule arrete. Spoken: {}, Transcribed: {}",
                  m_totalSpoken, m_totalTranscribed);
}

std::unique_ptr<grove::IDataNode> VoiceModule::getState() {
    auto state = std::make_unique<grove::JsonDataNode>("state");
    state->setInt("totalSpoken", m_totalSpoken);
    state->setInt("totalTranscribed", m_totalTranscribed);
    return state;
}

void VoiceModule::setState(const grove::IDataNode& state) {
    m_totalSpoken = state.getInt("totalSpoken", 0);
    m_totalTranscribed = state.getInt("totalTranscribed", 0);
    m_logger->info("Etat restore: spoken={}, transcribed={}", m_totalSpoken, m_totalTranscribed);
}

} // namespace celuna

#ifndef CELUNA_TEST_BUILD
extern "C" {

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

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

}
#endif
