#include "ISTTEngine.hpp"
#include "WhisperAPIEngine.hpp"
#include "VoskSTTEngine.hpp"
#include "PocketSphinxEngine.hpp"
#include "WhisperCppEngine.hpp"
#include <spdlog/spdlog.h>
#include <filesystem>

namespace celuna {

// Stub STT for when API key is not available
class StubSTTEngine : public ISTTEngine {
public:
    std::string transcribe(const std::vector<float>& audioData) override {
        spdlog::info("[STT Stub] Would transcribe {} samples", audioData.size());
        return "";
    }
    std::string transcribeFile(const std::string& filePath) override {
        spdlog::info("[STT Stub] Would transcribe file: {}", filePath);
        return "";
    }
    void setLanguage(const std::string& language) override {}
    bool isAvailable() const override { return false; }
    std::string getEngineName() const override { return "stub"; }
};

// Legacy factory method (backward compatibility)
std::unique_ptr<ISTTEngine> STTEngineFactory::create(const std::string& apiKey) {
    auto logger = spdlog::get("STTFactory");
    if (!logger) {
        logger = spdlog::stdout_color_mt("STTFactory");
    }

    if (!apiKey.empty()) {
        auto engine = std::make_unique<WhisperAPIEngine>(apiKey);
        if (engine->isAvailable()) {
            logger->info("Using Whisper API STT engine");
            return engine;
        }
    }

    logger->warn("No STT engine available (API key missing), using stub");
    return std::make_unique<StubSTTEngine>();
}

// New factory method with engine type selection
std::unique_ptr<ISTTEngine> STTEngineFactory::create(
    const std::string& type,
    const std::string& modelPath,
    const std::string& apiKey) {

    auto logger = spdlog::get("STTFactory");
    if (!logger) {
        logger = spdlog::stdout_color_mt("STTFactory");
    }

    logger->info("Creating STT engine: type={}, model={}", type, modelPath);

    // 1. Try PocketSphinx (lightweight keyword spotting)
    if (type == "pocketsphinx") {
        if (!modelPath.empty() && std::filesystem::exists(modelPath)) {
            auto engine = std::make_unique<PocketSphinxEngine>(modelPath);
            if (engine->isAvailable()) {
                logger->info("Using PocketSphinx STT engine (model: {})", modelPath);
                return engine;
            } else {
                logger->warn("PocketSphinx engine not available (check if libpocketsphinx is installed)");
            }
        } else {
            logger->debug("PocketSphinx model not found at: {}", modelPath);
        }
    }

    // 2. Try Vosk (good local STT for full transcription)
    if (type == "vosk" || type == "auto") {
        if (!modelPath.empty() && std::filesystem::exists(modelPath)) {
            auto engine = std::make_unique<VoskSTTEngine>(modelPath);
            if (engine->isAvailable()) {
                logger->info("Using Vosk STT engine (model: {})", modelPath);
                return engine;
            } else {
                logger->warn("Vosk engine not available (check if libvosk is installed)");
            }
        } else {
            logger->debug("Vosk model not found at: {}", modelPath);
        }
    }

    // 3. Try Whisper.cpp (high-quality local STT)
    if (type == "whisper-cpp" || type == "auto") {
        if (!modelPath.empty() && std::filesystem::exists(modelPath)) {
            auto engine = std::make_unique<WhisperCppEngine>(modelPath);
            if (engine->isAvailable()) {
                logger->info("Using Whisper.cpp STT engine (model: {})", modelPath);
                return engine;
            } else {
                logger->warn("Whisper.cpp engine not available (check if whisper.cpp is compiled)");
            }
        } else {
            logger->debug("Whisper.cpp model not found at: {}", modelPath);
        }
    }

    // 4. Fallback to Whisper API if apiKey provided
    if (type == "whisper-api" || type == "auto") {
        if (!apiKey.empty()) {
            auto engine = std::make_unique<WhisperAPIEngine>(apiKey);
            if (engine->isAvailable()) {
                logger->info("Using Whisper API STT engine (fallback)");
                return engine;
            }
        }
    }

    // No engine available
    logger->warn("No STT engine available, using stub");
    return std::make_unique<StubSTTEngine>();
}

} // namespace celuna
