#include "VoiceService.hpp"

#include <spdlog/sinks/stdout_color_sinks.h>
#include <cstdlib>

namespace aissia {

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

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

    // Create TTS engine
    m_ttsEngine = TTSEngineFactory::create();
    if (m_ttsEngine && m_ttsEngine->isAvailable()) {
        m_ttsEngine->setRate(m_ttsRate);
        m_ttsEngine->setVolume(m_ttsVolume);
        m_logger->info("TTS engine: {}", m_ttsEngine->getEngineName());
    } else {
        m_logger->warn("TTS engine not available");
    }

    if (m_io) {
        grove::SubscriptionConfig config;
        m_io->subscribe("voice:speak", config);
        m_io->subscribe("voice:stop", config);
        m_io->subscribe("voice:listen", config);
    }

    m_logger->info("VoiceService initialized");
    return true;
}

void VoiceService::configureTTS(bool enabled, int rate, int volume) {
    m_ttsEnabled = enabled;
    m_ttsRate = rate;
    m_ttsVolume = volume;

    if (m_ttsEngine) {
        m_ttsEngine->setRate(rate);
        m_ttsEngine->setVolume(volume);
    }
}

void VoiceService::configureSTT(bool enabled, const std::string& language,
                                const std::string& apiKey) {
    m_sttEnabled = enabled;
    m_language = language;

    if (!apiKey.empty()) {
        m_sttEngine = STTEngineFactory::create(apiKey);
        if (m_sttEngine) {
            m_sttEngine->setLanguage(language);
            m_logger->info("STT engine: {}", m_sttEngine->getEngineName());
        }
    }
}

void VoiceService::process() {
    processMessages();
    processSpeakQueue();
}

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

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

        if (msg.topic == "voice:speak" && msg.data) {
            handleSpeakRequest(*msg.data);
        }
        else if (msg.topic == "voice:stop") {
            if (m_ttsEngine) {
                m_ttsEngine->stop();
            }
            // Clear queue
            while (!m_speakQueue.empty()) m_speakQueue.pop();
        }
        else if (msg.topic == "voice:listen" && m_sttEnabled && m_sttEngine) {
            // STT would be handled here
            // For now just log
            m_logger->debug("STT listen requested");
        }
    }
}

void VoiceService::handleSpeakRequest(const grove::IDataNode& data) {
    std::string text = data.getString("text", "");
    bool priority = data.getBool("priority", false);

    if (text.empty()) return;

    if (priority) {
        // Clear queue and stop current speech
        while (!m_speakQueue.empty()) m_speakQueue.pop();
        if (m_ttsEngine) m_ttsEngine->stop();
    }

    m_speakQueue.push(text);
}

void VoiceService::processSpeakQueue() {
    if (!m_ttsEnabled || !m_ttsEngine || m_speakQueue.empty()) return;

    // Only speak if not currently speaking
    if (!m_ttsEngine->isSpeaking() && !m_speakQueue.empty()) {
        std::string text = m_speakQueue.front();
        m_speakQueue.pop();
        speak(text);
    }
}

void VoiceService::speak(const std::string& text) {
    if (!m_ttsEngine || !m_ttsEnabled) return;

    // Publish speaking started
    if (m_io) {
        auto event = std::make_unique<grove::JsonDataNode>("event");
        event->setString("text", text.size() > 100 ? text.substr(0, 100) + "..." : text);
        m_io->publish("voice:speaking_started", std::move(event));
    }

    m_ttsEngine->speak(text, true);
    m_totalSpoken++;

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

void VoiceService::shutdown() {
    if (m_ttsEngine) {
        m_ttsEngine->stop();
    }

    m_logger->info("VoiceService shutdown. Total spoken: {}", m_totalSpoken);
}

} // namespace aissia
