import path from 'path';
import fs from 'fs';
import { v4 as uuidv4 } from 'uuid';
import { config } from '../../config';
import { prisma } from '../../models';
import { VoiceParams, Voice } from '../../types';
import { AliyunTtsProvider } from './aliyun.provider';
import { MockTtsProvider } from './mock.provider';
import { AudioMerger } from './audio-merger';
import { aiSummaryService } from './ai-summary.service';

// 可用音色列表（使用阿里云官方音色）
export const VOICES: Voice[] = [
  { id: 'cherry', name: '芊悦', gender: 'female', description: '阳光积极、亲切自然' },
  { id: 'serena', name: '苏瑶', gender: 'female', description: '温柔女声' },
  { id: 'ethan', name: '晨煦', gender: 'male', description: '阳光温暖、活力男声' },
  { id: 'chelsie', name: '千雪', gender: 'female', description: '二次元虚拟女友' },
  { id: 'momo', name: '茉兔', gender: 'female', description: '撒娇搞怪' },
  { id: 'vivian', name: '十三', gender: 'female', description: '可爱小暴躁' },
  { id: 'moon', name: '月白', gender: 'male', description: '率性帅气' },
  { id: 'maia', name: '四月', gender: 'female', description: '知性温柔' },
  { id: 'kai', name: '凯', gender: 'male', description: '舒缓放松' },
  { id: 'nofish', name: '不吃鱼', gender: 'male', description: '不会翘舌音' },
];

// 前端音色 ID 到阿里云音色的映射
const VOICE_MAPPING: Record<string, string> = {
  cherry: 'Cherry',
  serena: 'Serena',
  ethan: 'Ethan',
  chelsie: 'Chelsie',
  momo: 'Momo',
  vivian: 'Vivian',
  moon: 'Moon',
  maia: 'Maia',
  kai: 'Kai',
  nofish: 'Nofish',
};

// 获取阿里云音色名称
export function getAliyunVoice(voiceId: string): string {
  return VOICE_MAPPING[voiceId] || 'Cherry';
}

// 文本分段
export function splitText(text: string, maxLength: number = 500): string[] {
  const segments: string[] = [];
  let current = '';

  // 按段落分割
  const paragraphs = text.split(/\n+/);

  for (const para of paragraphs) {
    if ((current + para).length <= maxLength) {
      current += (current ? '\n' : '') + para;
    } else {
      if (current) segments.push(current);

      // 如果段落本身超长，按句子分割
      if (para.length > maxLength) {
        const sentences = para.split(/[。！？；]/g);
        current = '';

        for (const sentence of sentences) {
          if (sentence.length === 0) continue;

          if ((current + sentence).length <= maxLength) {
            current += sentence;
          } else {
            if (current) segments.push(current);
            // 如果句子本身超长，强制分割
            if (sentence.length > maxLength) {
              for (let i = 0; i < sentence.length; i += maxLength) {
                segments.push(sentence.slice(i, i + maxLength));
              }
              current = '';
            } else {
              current = sentence;
            }
          }
        }
      } else {
        current = para;
      }
    }
  }

  if (current) segments.push(current);
  return segments;
}

// TTS Provider 工厂
function getTtsProvider() {
  // 优先使用阿里云百炼 Qwen TTS
  if (config.dashscope.apiKey) {
    console.log('🔊 使用阿里云百炼 Qwen TTS 服务');
    return new AliyunTtsProvider();
  }
  // 降级到模拟服务
  console.log('🔊 使用模拟 TTS 服务');
  return new MockTtsProvider();
}

// 生成音频
export async function generateAudio(
  userId: string,
  text: string,
  voiceId: string,
  voiceParams: VoiceParams
): Promise<{
  audioId: string;
  audioUrl: string;
  duration: number;
  size: number;
}> {
  const provider = getTtsProvider();

  // 分段
  const segments = splitText(text);
  console.log(`📝 文本已分段: ${segments.length} 段`);

  // 创建音频记录
  const audioId = uuidv4();
  const audioDir = path.join(config.upload.dir, audioId);

  if (!fs.existsSync(audioDir)) {
    fs.mkdirSync(audioDir, { recursive: true });
  }

  // 并行生成各段音频
  const audioFiles: string[] = [];
  const cloudUrls: string[] = [];
  const concurrency = 5; // 并发数

  for (let i = 0; i < segments.length; i += concurrency) {
    const batch = segments.slice(i, i + concurrency);
    const results = await Promise.all(
      batch.map((segment, idx) =>
        provider.synthesize(segment, getAliyunVoice(voiceId), voiceParams, path.join(audioDir, `segment_${i + idx}.mp3`))
      )
    );
    // 检查是否有云端 URL
    results.forEach(r => {
      if (r.startsWith('cloud:')) {
        cloudUrls.push(r.substring(6));
      } else {
        audioFiles.push(r);
      }
    });
  }

  // 如果有云端 URL，直接返回（单段文本情况）
  let audioUrl = '';
  let duration = 0;
  let size = 0;

  if (cloudUrls.length > 0) {
    // 使用第一个云端 URL（简化处理）
    audioUrl = cloudUrls[0];
    console.log('☁️ 使用云端音频 URL:', audioUrl);
  } else if (audioFiles.length > 0) {
    // 合并音频
    const outputPath = path.join(audioDir, 'output.mp3');
    const mergedFile = await AudioMerger.merge(audioFiles, outputPath);

    // 获取文件信息
    const stats = fs.statSync(mergedFile);
    size = stats.size;
    duration = await AudioMerger.getDuration(mergedFile);
    audioUrl = `/uploads/${audioId}/output.mp3`;
  }

  // 使用 AI 生成标题、摘要和标签
  console.log('🤖 使用 AI 生成标题、摘要和标签...');
  const [title, summary, tags] = await Promise.all([
    aiSummaryService.generateTitle(text),
    aiSummaryService.generateSummary(text, 200),
    aiSummaryService.extractTags(text),
  ]);

  // 创建数据库记录
  const finalAudioUrl = cloudUrls.length > 0 ? cloudUrls[0] : `/uploads/${audioId}/output.mp3`;
  console.log('📝 创建音频记录:', {
    userId,
    title,
    text: text.substring(0, 50),
    summary,
    tags,
    audioUrl: finalAudioUrl,
    audioDuration: duration,
    audioSize: size,
    wordCount: text.length,
    voiceId,
    voiceParams,
    status: 'completed',
  });

  let audio;
  try {
    audio = await prisma.audio.create({
      data: {
        userId: userId ? parseInt(userId) : undefined,
        title,
        text,
        summary,
        tags: JSON.stringify(tags),
        audioUrl: finalAudioUrl,
        audioDuration: duration,
        audioSize: size,
        wordCount: text.length,
        voiceId,
        voiceParams: JSON.stringify(voiceParams),
        status: 'completed',
      },
    });
    console.log('✅ 音频记录创建成功:', audio.id);
  } catch (error) {
    console.error('❌ 音频记录创建失败:', error);
    throw error;
  }

  return {
    audioId: audio.id.toString(),
    audioUrl: audio.audioUrl,
    duration,
    size,
  };
}

// 获取可用音色
export function getVoices(): Voice[] {
  return VOICES;
}