// CRITICAL ORDER: Include system headers first
#include <nlohmann/json.hpp>
#include <cstdlib>
#include <memory>
#include <string>

// Include local headers before spdlog
#include "STTService.hpp"
#include "../shared/audio/ISTTEngine.hpp"

// Include spdlog after local headers
#include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_color_sinks.h>

namespace celuna {

STTService::STTService(const nlohmann::json& config)
    : m_config(config)
{
    m_logger = spdlog::get("STTService");
    if (!m_logger) {
        m_logger = spdlog::stdout_color_mt("STTService");
    }

    // Extract language from config
    if (config.contains("active_mode") && config["active_mode"].contains("language")) {
        m_language = config["active_mode"]["language"].get<std::string>();
    }

    m_logger->info("STTService created");
}

STTService::~STTService() {
    stop();
}

bool STTService::start() {
    m_logger->info("Starting STT service");

    loadEngines();

    if (!m_activeEngine || !m_activeEngine->isAvailable()) {
        m_logger->error("No active STT engine available");
        return false;
    }

    m_logger->info("STT service started");
    return true;
}

void STTService::stop() {
    m_logger->info("Stopping STT service");
    stopListening();
    m_activeEngine.reset();
}

void STTService::setMode(STTMode mode) {
    if (m_currentMode == mode) {
        return;
    }

    m_logger->info("Switching STT mode");
    m_currentMode = mode;
}

std::string STTService::transcribeFile(const std::string& filePath) {
    if (!m_activeEngine || !m_activeEngine->isAvailable()) {
        m_logger->warn("No STT engine available for transcription");
        return "";
    }

    m_logger->info("Transcribing file");

    try {
        std::string result = m_activeEngine->transcribeFile(filePath);
        m_logger->info("Transcription complete");
        return result;
    } catch (const std::exception& e) {
        m_logger->error("Transcription failed");
        return "";
    }
}

std::string STTService::transcribe(const std::vector<float>& audioData) {
    if (!m_activeEngine || !m_activeEngine->isAvailable()) {
        return "";
    }

    if (audioData.empty()) {
        return "";
    }

    try {
        std::string result = m_activeEngine->transcribe(audioData);

        if (!result.empty() && m_listening && m_onTranscription) {
            m_onTranscription(result, m_currentMode);
        }

        return result;
    } catch (const std::exception& e) {
        m_logger->error("Transcription failed");
        return "";
    }
}

void STTService::startListening(TranscriptionCallback onTranscription,
                                KeywordCallback onKeyword) {
    m_logger->info("Start listening");

    m_onTranscription = onTranscription;
    m_onKeyword = onKeyword;
    m_listening = true;

    m_logger->warn("Streaming microphone capture not yet implemented");
}

void STTService::stopListening() {
    if (!m_listening) {
        return;
    }

    m_logger->info("Stop listening");
    m_listening = false;
}

void STTService::setLanguage(const std::string& language) {
    m_logger->info("Setting language");
    m_language = language;

    if (m_activeEngine) {
        m_activeEngine->setLanguage(language);
    }
}

bool STTService::isAvailable() const {
    return m_activeEngine && m_activeEngine->isAvailable();
}

std::string STTService::getCurrentEngine() const {
    if (m_activeEngine) {
        return m_activeEngine->getEngineName();
    }
    return "none";
}

void STTService::loadEngines() {
    m_logger->info("Loading STT engines");

    std::string engineType = "auto";
    if (m_config.contains("active_mode")) {
        const auto& activeMode = m_config["active_mode"];
        if (activeMode.contains("engine")) {
            engineType = activeMode["engine"];
        }
    }

    std::string modelPath;
    if (m_config.contains("active_mode")) {
        const auto& activeMode = m_config["active_mode"];
        if (activeMode.contains("model_path")) {
            modelPath = activeMode["model_path"];
        }
    }

    std::string apiKey;
    if (m_config.contains("whisper_api")) {
        const auto& whisperApi = m_config["whisper_api"];
        std::string apiKeyEnv = "OPENAI_API_KEY";
        if (whisperApi.contains("api_key_env")) {
            apiKeyEnv = whisperApi["api_key_env"];
        }
        const char* envVal = std::getenv(apiKeyEnv.c_str());
        if (envVal) {
            apiKey = envVal;
        }
    }

    m_activeEngine = STTEngineFactory::create(engineType, modelPath, apiKey);

    if (m_activeEngine && m_activeEngine->isAvailable()) {
        m_activeEngine->setLanguage(m_language);
        m_logger->info("STT engine loaded successfully");
    } else {
        m_logger->warn("No active STT engine available");
    }
}

} // namespace celuna
