import fs from 'fs';
import path from 'path';
import { exec } from 'child_process';
import { promisify } from 'util';
import { FFmpegProcessor } from '../../services/ffmpeg.processor';

const execAsync = promisify(exec);

export class AudioMerger {
  // 合并多个音频文件（支持 OSS URL）
  static async merge(inputFiles: string[], outputPath: string): Promise<string> {
    if (inputFiles.length === 0) {
      throw new Error('没有音频文件需要合并');
    }

    if (inputFiles.length === 1) {
      // 单个文件：远程URL直接用FFmpegProcessor上传
      if (inputFiles[0].startsWith('http')) {
        const outputExt = outputPath.split('.').pop() || 'mp3';
        return await FFmpegProcessor.mergeAudio(inputFiles, outputExt);
      }

      // 本地单文件：检查是否需要格式转换
      const inputExt = inputFiles[0].split('.').pop()?.toLowerCase();
      const outputExt = outputPath.split('.').pop()?.toLowerCase();

      if (inputExt !== outputExt) {
        // 格式不同（如 WAV→MP3），用 FFmpeg 转码
        let cmd: string;
        if (outputExt === 'mp3') {
          cmd = `ffmpeg -i "${inputFiles[0]}" -c:a libmp3lame -b:a 192k -y "${outputPath}"`;
        } else {
          cmd = `ffmpeg -i "${inputFiles[0]}" -c copy -y "${outputPath}"`;
        }
        await execAsync(cmd, { timeout: 120000 });
        console.log(`✅ 音频格式转换成功: ${inputExt} → ${outputExt}`);
      } else {
        // 格式相同，直接复制
        if (inputFiles[0] !== outputPath) {
          fs.copyFileSync(inputFiles[0], outputPath);
        }
      }
      return outputPath;
    }

    // 检测是否有远程 URL
    const hasRemoteFiles = inputFiles.some(f => f.startsWith('http'));

    if (hasRemoteFiles) {
      // 使用 FFmpegProcessor 处理远程文件
      const outputExt = outputPath.split('.').pop() || 'mp3';
      return await FFmpegProcessor.mergeAudio(inputFiles, outputExt);
    }

    // 本地文件，使用原有逻辑
    return this.mergeLocalFiles(inputFiles, outputPath);
  }

  // 合并本地音频文件（原有逻辑）
  private static async mergeLocalFiles(inputFiles: string[], outputPath: string): Promise<string> {
    try {
      // 在输出文件同目录创建临时列表文件（避免 Windows /tmp 路径问题）
      const outputDir = path.dirname(outputPath);
      const listFile = path.join(outputDir, 'ffmpeg_concat_list.txt');

      // 使用相对路径避免 Windows 反斜杠问题
      const listContent = inputFiles.map(f => {
        const relativePath = path.relative(outputDir, f).replace(/\\/g, '/');
        return `file '${relativePath}'`;
      }).join('\n');
      fs.writeFileSync(listFile, listContent);

      // 检查输出格式
      const outputExt = outputPath.split('.').pop()?.toLowerCase();

      // 构建 FFmpeg 命令（在工作目录中执行，使相对路径生效）
      let cmd: string;
      if (outputExt === 'mp3') {
        // MP3 需要转码（WAV/PCM -> MP3）
        cmd = `ffmpeg -f concat -safe 0 -i "${listFile}" -c:a libmp3lame -b:a 192k -y "${outputPath}"`;
      } else {
        // 其他格式直接复制
        cmd = `ffmpeg -f concat -safe 0 -i "${listFile}" -c copy -y "${outputPath}"`;
      }

      await execAsync(cmd, { timeout: 300000, cwd: outputDir });

      // 清理临时列表文件
      try { fs.unlinkSync(listFile); } catch {}

      console.log(`✅ 音频合并成功: ${outputPath}`);
      return outputPath;
    } catch (error) {
      console.error('❌ 音频合并失败:', error);
      throw new Error('音频合并失败');
    }
  }

  // 获取音频时长（支持 OSS URL）
  static async getDuration(filePath: string): Promise<number> {
    // 检测是否为远程 URL
    if (filePath.startsWith('http')) {
      return await FFmpegProcessor.getDuration(filePath);
    }

    // 本地文件，使用原有逻辑
    try {
      const cmd = `ffprobe -i "${filePath}" -show_entries format=duration -v quiet -of csv="p=0"`;
      const { stdout } = await execAsync(cmd, { timeout: 10000 });
      // 保留一位小数精度（不再 Math.round 丢失精度）
      return Math.round((parseFloat(stdout.trim()) || 0) * 10) / 10;
    } catch (error) {
      console.error('❌ 获取音频时长失败:', error);
      return 0;
    }
  }
}