"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.VoiceManager = void 0;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const child_process = __importStar(require("child_process"));
const util_1 = require("util");
const openai_1 = __importDefault(require("openai"));
const VoiceRouter_1 = require("./VoiceRouter");
const ToolsetGuard_1 = require("./toolset/ToolsetGuard");
const execFile = (0, util_1.promisify)(child_process.execFile);
class VoiceManager {
    elevenLabsApiKey;
    voiceRouter;
    openai = null;
    constructor() {
        this.elevenLabsApiKey = process.env.ELEVENLABS_API_KEY;
        this.voiceRouter = new VoiceRouter_1.VoiceRouter();
        const openAIKey = process.env.OPENAI_API_KEY;
        if (openAIKey && openAIKey.trim() !== '') {
            this.openai = new openai_1.default({ apiKey: openAIKey });
        }
    }
    async processAudioInput(fileLink) {
        const sttOrder = this.voiceRouter.getSttOrder();
        let lastError = null;
        for (const provider of sttOrder) {
            try {
                switch (provider) {
                    case 'gemini':
                        return await this.transcribeWithGemini(fileLink);
                    case 'openai':
                        return await this.transcribeWithOpenAI(fileLink);
                    default:
                        throw new Error(`[VOICE] Provider de STT desconhecido: ${provider}`);
                }
            }
            catch (error) {
                lastError = error instanceof Error ? error : new Error(String(error));
                const msg = lastError.message;
                console.log(`[VOICE] Falha no provider STT ${provider}:`, msg);
                this.logMediaRoute('stt', provider, 'failed', msg);
            }
        }
        throw lastError || new Error('[VOICE] Nenhum provider de STT disponível.');
    }
    async generateSpeech(text, voiceId) {
        (0, ToolsetGuard_1.assertToolsetAllowed)('tts', 'VoiceManager.generateSpeech');
        const ttsOrder = this.voiceRouter.getTtsOrder();
        const selectedVoice = voiceId || this.voiceRouter.getDefaultVoice() || 'EXAVITQu4vr4xnSDxMaL';
        let lastError = null;
        for (const provider of ttsOrder) {
            try {
                switch (provider) {
                    case 'gemini':
                        return await this.generateSpeechWithGemini(text);
                    case 'elevenlabs':
                        return await this.generateSpeechWithElevenLabs(text, selectedVoice);
                    case 'piper':
                        throw new Error('[VOICE] Piper ainda não implementado no runtime atual.');
                    case 'openai':
                        return await this.generateSpeechWithOpenAI(text, selectedVoice);
                    default:
                        throw new Error(`[VOICE] Provider de TTS desconhecido: ${provider}`);
                }
            }
            catch (error) {
                lastError = error instanceof Error ? error : new Error(String(error));
                const msg = lastError.message;
                console.log(`[VOICE] Falha no provider ${provider}:`, msg);
                this.logMediaRoute('tts', provider, 'failed', msg);
            }
        }
        throw lastError || new Error('[VOICE] Nenhum provider de TTS disponível.');
    }
    async transcribeWithGemini(fileLink) {
        const candidates = ['gemini-3.1-flash-lite-preview', 'gemini-2.5-flash', 'gemini-3.1-pro-preview'];
        let lastError = null;
        for (const model of candidates) {
            try {
                const args = ['-o', 'json', '-m', model, '-p', `Transcreva fielmente este áudio em português do Brasil: @${fileLink}`, '-y'];
                const { stdout } = await execFile('gemini', args, { maxBuffer: 1024 * 1024 * 10, timeout: 120000 });
                const jsonStart = stdout.indexOf('{');
                if (jsonStart === -1)
                    throw new Error('Resposta Gemini inválida para STT.');
                const parsed = JSON.parse(stdout.slice(jsonStart));
                const text = String(parsed.response || parsed.text || '').trim();
                if (!text)
                    throw new Error('Transcrição vazia no Gemini STT.');
                this.logMediaRoute('stt', `gemini:${model}`, 'success');
                return text;
            }
            catch (error) {
                lastError = error instanceof Error ? error : new Error(String(error));
                const reason = lastError.message.toLowerCase();
                this.logMediaRoute('stt', `gemini:${model}`, 'failed', lastError.message);
                if (!/429|resource_exhausted|capacity|rate limit|quota/.test(reason))
                    break;
            }
        }
        throw new Error(`Falha STT Gemini fallback-chain: ${lastError?.message || 'unknown error'}`);
    }
    async transcribeWithOpenAI(_fileLink) {
        throw new Error('OpenAI STT fallback ainda não implementado neste runtime.');
    }
    async generateSpeechWithGemini(_text) {
        throw new Error('Gemini TTS indisponível neste runtime; acionando fallback controlado.');
    }
    async generateSpeechWithOpenAI(text, voiceId = 'nova') {
        if (!this.openai) {
            throw new Error('[VOICE] OPENAI_API_KEY não configurada.');
        }
        const response = await this.openai.audio.speech.create({
            model: 'gpt-4o-mini-tts',
            voice: voiceId,
            input: text
        });
        const buffer = Buffer.from(await response.arrayBuffer());
        const outputDir = path.join(process.cwd(), '.temp_audio');
        if (!fs.existsSync(outputDir)) {
            fs.mkdirSync(outputDir, { recursive: true });
        }
        const fileName = `speech_openai_${Date.now()}.mp3`;
        const filePath = path.join(outputDir, fileName);
        fs.writeFileSync(filePath, buffer);
        this.logMediaRoute('tts', 'openai', 'success');
        return filePath;
    }
    async generateSpeechWithElevenLabs(text, voiceId) {
        if (!this.elevenLabsApiKey) {
            throw new Error('[VOICE] ELEVENLABS_API_KEY não configurada.');
        }
        const url = `https://api.elevenlabs.io/v1/text-to-speech/${voiceId}`;
        const response = await fetch(url, {
            method: 'POST',
            headers: {
                'Accept': 'audio/mpeg',
                'Content-Type': 'application/json',
                'xi-api-key': this.elevenLabsApiKey
            },
            body: JSON.stringify({
                text,
                model_id: 'eleven_multilingual_v2',
                voice_settings: { stability: 0.5, similarity_boost: 0.75 }
            })
        });
        if (!response.ok) {
            throw new Error(`[VOICE] Erro ElevenLabs: ${response.statusText}`);
        }
        const buffer = await response.arrayBuffer();
        const outputDir = path.join(process.cwd(), '.temp_audio');
        if (!fs.existsSync(outputDir)) {
            fs.mkdirSync(outputDir, { recursive: true });
        }
        const fileName = `speech_${Date.now()}.mp3`;
        const filePath = path.join(outputDir, fileName);
        fs.writeFileSync(filePath, Buffer.from(buffer));
        this.logMediaRoute('tts', 'elevenlabs', 'success');
        return filePath;
    }
    logMediaRoute(kind, provider, status, detail) {
        const file = path.join(process.cwd(), '.openlife', 'media-routing.log.jsonl');
        fs.mkdirSync(path.dirname(file), { recursive: true });
        fs.appendFileSync(file, JSON.stringify({ ts: new Date().toISOString(), kind, provider, status, detail: detail || '' }) + '\n', 'utf-8');
    }
}
exports.VoiceManager = VoiceManager;
