#pragma once

#include "ISTTEngine.hpp"
#include "../http/HttpClient.hpp"
#include <spdlog/spdlog.h>
#include <fstream>
#include <memory>

namespace celuna {

/**
 * @brief OpenAI Whisper API Speech-to-Text engine
 */
class WhisperAPIEngine : public ISTTEngine {
public:
    explicit WhisperAPIEngine(const std::string& apiKey)
        : m_apiKey(apiKey) {
        m_logger = spdlog::get("WhisperAPI");
        if (!m_logger) {
            m_logger = spdlog::stdout_color_mt("WhisperAPI");
        }

        m_client = std::make_unique<HttpClient>("https://api.openai.com", 60);
        m_client->setBearerToken(m_apiKey);

        m_available = !m_apiKey.empty();
        if (m_available) {
            m_logger->info("Whisper API STT initialized");
        } else {
            m_logger->warn("Whisper API not available (no API key)");
        }
    }

    std::string transcribe(const std::vector<float>& audioData) override {
        if (!m_available || audioData.empty()) return "";

        // Write audio data to temporary WAV file
        std::string tempPath = "/tmp/aissia_audio_" + std::to_string(std::time(nullptr)) + ".wav";
        if (!writeWavFile(tempPath, audioData)) {
            m_logger->error("Failed to write temp audio file");
            return "";
        }

        std::string result = transcribeFile(tempPath);

        // Cleanup temp file
        std::remove(tempPath.c_str());

        return result;
    }

    std::string transcribeFile(const std::string& filePath) override {
        if (!m_available) return "";

        // Read file contents
        std::ifstream file(filePath, std::ios::binary);
        if (!file.is_open()) {
            m_logger->error("Failed to open audio file: {}", filePath);
            return "";
        }

        std::vector<char> fileData((std::istreambuf_iterator<char>(file)),
                                    std::istreambuf_iterator<char>());
        file.close();

        // Prepare multipart form data
        httplib::MultipartFormDataItems items = {
            {"file", std::string(fileData.begin(), fileData.end()),
             filePath.substr(filePath.find_last_of("/\\") + 1), "audio/wav"},
            {"model", "whisper-1", "", ""},
            {"language", m_language, "", ""},
            {"response_format", "text", "", ""}
        };

        auto response = m_client->postMultipart("/v1/audio/transcriptions", items);

        if (!response.success) {
            m_logger->error("Whisper API error: {}", response.error);
            return "";
        }

        m_logger->debug("Transcription: {}", response.body.substr(0, 100));
        return response.body;
    }

    void setLanguage(const std::string& language) override {
        m_language = language;
    }

    bool isAvailable() const override {
        return m_available;
    }

    std::string getEngineName() const override {
        return "whisper-api";
    }

private:
    std::string m_apiKey;
    std::string m_language = "fr";
    bool m_available = false;
    std::unique_ptr<HttpClient> m_client;
    std::shared_ptr<spdlog::logger> m_logger;

    bool writeWavFile(const std::string& path, const std::vector<float>& samples) {
        // Simple WAV file writer for 16-bit mono 16kHz audio
        std::ofstream file(path, std::ios::binary);
        if (!file.is_open()) return false;

        const int sampleRate = 16000;
        const int bitsPerSample = 16;
        const int numChannels = 1;
        const int byteRate = sampleRate * numChannels * bitsPerSample / 8;
        const int blockAlign = numChannels * bitsPerSample / 8;
        const int dataSize = samples.size() * sizeof(int16_t);

        // RIFF header
        file.write("RIFF", 4);
        int32_t fileSize = 36 + dataSize;
        file.write(reinterpret_cast<const char*>(&fileSize), 4);
        file.write("WAVE", 4);

        // fmt chunk
        file.write("fmt ", 4);
        int32_t fmtSize = 16;
        file.write(reinterpret_cast<const char*>(&fmtSize), 4);
        int16_t audioFormat = 1;  // PCM
        file.write(reinterpret_cast<const char*>(&audioFormat), 2);
        int16_t channels = numChannels;
        file.write(reinterpret_cast<const char*>(&channels), 2);
        int32_t sr = sampleRate;
        file.write(reinterpret_cast<const char*>(&sr), 4);
        int32_t br = byteRate;
        file.write(reinterpret_cast<const char*>(&br), 4);
        int16_t ba = blockAlign;
        file.write(reinterpret_cast<const char*>(&ba), 2);
        int16_t bps = bitsPerSample;
        file.write(reinterpret_cast<const char*>(&bps), 2);

        // data chunk
        file.write("data", 4);
        int32_t ds = dataSize;
        file.write(reinterpret_cast<const char*>(&ds), 4);

        // Convert float samples to 16-bit
        for (float sample : samples) {
            int16_t s = static_cast<int16_t>(std::max(-1.0f, std::min(1.0f, sample)) * 32767.0f);
            file.write(reinterpret_cast<const char*>(&s), 2);
        }

        file.close();
        return true;
    }
};

} // namespace celuna
