"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AliyunTtsProvider = void 0;
const axios_1 = __importDefault(require("axios"));
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const config_1 = require("../../config");
// 阿里云百炼 Qwen TTS Provider
// 文档: https://help.aliyun.com/zh/model-studio/qwen-tts
class AliyunTtsProvider {
    apiKey;
    model;
    voice;
    baseUrl = 'https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation';
    constructor() {
        this.apiKey = config_1.config.dashscope.apiKey;
        this.model = config_1.config.dashscope.model;
        this.voice = config_1.config.dashscope.voice;
    }
    // 语音合成（带重试机制）
    async synthesize(text, voiceId, params, outputPath, retries = 3, modelOverride) {
        const activeModel = modelOverride || this.model;
        let lastError = null;
        for (let attempt = 1; attempt <= retries; attempt++) {
            try {
                // 构建请求
                const requestBody = {
                    model: activeModel,
                    input: {
                        text: text,
                        voice: voiceId || this.voice,
                        language_type: 'Chinese',
                    },
                };
                console.log(`📤 [Aliyun TTS] 尝试 ${attempt}/${retries}`);
                console.log(`   model: ${activeModel}, voice: ${voiceId || this.voice}`);
                console.log(`   text length: ${text.length}`);
                console.log(`   params: ${JSON.stringify(params)}`);
                // 使用 instruct 模型时支持指令控制
                if (activeModel.includes('instruct')) {
                    const instructions = [];
                    if (params.speed !== 1) {
                        const speedDesc = params.speed > 1 ? '较快' : '较慢';
                        instructions.push(`语速${speedDesc}`);
                    }
                    if (params.pitch !== 0) {
                        const pitchDesc = params.pitch > 0 ? '较高' : '较低';
                        instructions.push(`音调${pitchDesc}`);
                    }
                    if (instructions.length > 0) {
                        requestBody.parameters = {
                            instructions: instructions.join('，'),
                        };
                    }
                }
                // 发送请求
                const response = await axios_1.default.post(this.baseUrl, requestBody, {
                    headers: {
                        'Authorization': `Bearer ${this.apiKey}`,
                        'Content-Type': 'application/json',
                    },
                    timeout: 60000,
                });
                // 检查响应
                if (response.status !== 200) {
                    throw new Error(`Qwen TTS 请求失败: ${response.status}`);
                }
                const data = response.data;
                if (data.code) {
                    throw new Error(`Qwen TTS 错误: ${data.message || JSON.stringify(data)}`);
                }
                // 获取音频 URL
                const audioUrl = data.output?.audio?.url;
                console.log('🔗 音频 URL:', audioUrl);
                if (!audioUrl) {
                    throw new Error('Qwen TTS 未返回音频 URL');
                }
                // 尝试下载音频文件，如果失败则返回 URL
                try {
                    const audioResponse = await axios_1.default.get(audioUrl, {
                        responseType: 'arraybuffer',
                        timeout: 60000,
                    });
                    // 保存文件
                    const dir = path_1.default.dirname(outputPath);
                    if (!fs_1.default.existsSync(dir)) {
                        fs_1.default.mkdirSync(dir, { recursive: true });
                    }
                    // 确保输出路径以 .wav 结尾
                    const finalPath = outputPath.endsWith('.wav') ? outputPath : outputPath.replace(/\.[^.]+$/, '.wav');
                    fs_1.default.writeFileSync(finalPath, audioResponse.data);
                    console.log(`✅ Qwen TTS 生成成功: ${finalPath}`);
                    return finalPath;
                }
                catch (downloadError) {
                    console.warn('⚠️ 音频下载失败，返回云端 URL:', downloadError.message);
                    // 返回一个特殊的路径标记，表示使用云端 URL
                    return `cloud:${audioUrl}`;
                }
            }
            catch (error) {
                const errorDetails = error.response?.data || error.message;
                const isRateLimit = error.response?.status === 429 || errorDetails?.code === 'Throttling.RateQuota';
                const isServerError = error.response?.status >= 500;
                console.error(`❌ Qwen TTS 调用失败 (尝试 ${attempt}/${retries}):`, JSON.stringify(errorDetails, null, 2));
                if (isRateLimit && attempt < retries) {
                    // 速率限制：等待后重试（指数退避）
                    const waitTime = Math.pow(2, attempt) * 1000;
                    console.warn(`⏳ 速率限制，等待 ${waitTime}ms 后重试...`);
                    await new Promise(resolve => setTimeout(resolve, waitTime));
                    lastError = new Error(`Qwen TTS 速率限制: ${error.message}`);
                    continue;
                }
                if (isServerError && attempt < retries) {
                    // 服务器错误：等待后重试
                    const waitTime = Math.pow(2, attempt) * 1000;
                    console.warn(`⏳ 服务器错误，等待 ${waitTime}ms 后重试...`);
                    await new Promise(resolve => setTimeout(resolve, waitTime));
                    lastError = new Error(`Qwen TTS 服务器错误: ${error.message}`);
                    continue;
                }
                // 达到最大重试次数或不可重试的错误
                throw new Error(`Qwen TTS 服务调用失败: ${error.message}, 详情: ${JSON.stringify(errorDetails)}`);
            }
        }
        // 理论上不会到达这里，但为了类型安全
        throw lastError || new Error('Qwen TTS 服务调用失败');
    }
}
exports.AliyunTtsProvider = AliyunTtsProvider;
