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 { AliyunRealtimeTtsProvider } from './aliyun-realtime.provider';
import { MockTtsProvider } from './mock.provider';
import { AudioMerger } from './audio-merger';
import { aiSummaryService } from './ai-summary.service';

// 日志文件路径
const LOG_FILE = path.join(process.cwd(), 'tts-debug.log');

function logToFile(msg: string) {
  const timestamp = new Date().toISOString();
  fs.appendFileSync(LOG_FILE, `[${timestamp}] ${msg}\n`);
}

// 可用音色列表（使用阿里云官方音色）
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';
}

// 判断是否使用长文本模式（>5000字符且启用realtime）
// 注意：WebSocket realtime 模式需要特殊的API权限和配置，如果连接失败会导致生成失败。
// 暂时强制禁用，使用 HTTP 分段模式
export function shouldUseLongText(text: string): boolean {
  return false; // 强制返回 false，禁用 realtime 模式
}

// 文本分段 - 阿里云 TTS 限制 600 字符，增加到 550 留安全余量
export function splitText(text: string, maxLength: number = 550): string[] {
  const segments: string[] = [];
  let current = '';

  // 清理文本，移除可能导致问题的字符
  const cleanText = text.replace(/\r/g, '');

  // 按段落分割
  const paragraphs = cleanText.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.match(/[^。！？；]+[。！？；]?/g) || [para];
        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);

  // 验证每段长度不超过限制（安全检查）
  const safeLimit = 550;
  const validatedSegments = segments.map((seg, idx) => {
    if (seg.length > safeLimit) {
      console.warn(`⚠️ 段落 ${idx + 1} 长度 ${seg.length} 超过限制，强制截断`);
      return seg.substring(0, safeLimit);
    }
    return seg;
  });

  return validatedSegments;
}

// TTS Provider 工厂
function getTtsProvider(text: string, voiceId: string) {
  const useLongText = shouldUseLongText(text);

  // 文本超长时使用 WebSocket 实时合成
  if (useLongText && config.dashscope.apiKey) {
    console.log('🔊 文本超过5000字符，使用 Qwen Realtime TTS 流式合成');
    return { provider: new AliyunRealtimeTtsProvider(), type: 'realtime' as const };
  }

  // 优先使用阿里云百炼 Qwen TTS
  if (config.dashscope.apiKey) {
    console.log('🔊 使用阿里云百炼 Qwen TTS 服务');
    return { provider: new AliyunTtsProvider(), type: 'http' as const };
  }

  // 降级到模拟服务
  console.log('🔊 使用模拟 TTS 服务（无 API Key）');
  return { provider: new MockTtsProvider(), type: 'mock' as const };
}

// 随机选择 TTS 模型
function getRandomModel(): string {
  const models = config.dashscope.ttsModels;
  const model = models[Math.floor(Math.random() * models.length)];
  console.log(`🎲 随机选择 TTS 模型: ${model}`);
  return model;
}

// 生成音频（异步模式）
export async function generateAudio(
  userId: string,
  text: string,
  voiceId: string,
  voiceParams: VoiceParams
): Promise<{
  audioId: string;
  status: string;
}> {
  // 创建音频记录（待处理状态）
  const audioId = uuidv4();
  const audioDir = path.join(config.upload.dir, audioId);

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

  let audio;
  try {
    audio = await prisma.audio.create({
      data: {
        userId: userId ? parseInt(userId) : undefined,
        title: '处理中...',
        text,
        summary: '',
        tags: '[]',
        audioUrl: '',
        audioDuration: 0,
        audioSize: 0,
        wordCount: text.length,
        voiceId,
        voiceParams: JSON.stringify(voiceParams),
        status: 'pending',
      },
    });
    console.log('📝 创建音频记录:', audio.id, '状态: pending');
  } catch (error) {
    console.error('❌ 音频记录创建失败:', error);
    throw error;
  }

  // 异步处理音频生成
  processAudioGeneration(audio.id, text, voiceId, voiceParams, audioDir).catch(error => {
    const errMsg = `❌ 异步音频生成失败: ${error.message}`;
    console.error(errMsg);
    console.error('❌ 错误堆栈:', error.stack);
    logToFile(errMsg + '\n' + error.stack);
    prisma.audio.update({
      where: { id: audio.id },
      data: { status: 'failed' },
    }).catch(err => console.error('❌ 更新数据库状态失败:', err));
  });

  // 立即返回音频ID和状态
  return {
    audioId: audio.id.toString(),
    status: 'pending',
  };
}

/**
 * 异步处理音频生成
 */
async function processAudioGeneration(
  audioRecordId: number,
  text: string,
  voiceId: string,
  voiceParams: VoiceParams,
  audioDir: string
) {
  const logMsg = `🔄 开始处理音频 ID: ${audioRecordId}, 文本长度: ${text.length}, voiceId: ${voiceId}`;
  console.log(logMsg);
  logToFile(logMsg);
  
  try {
    const { provider, type } = getTtsProvider(text, voiceId);
    console.log(`🔧 Provider type: ${type}, voiceName: ${voiceId}`);
    logToFile(`Provider type: ${type}, voiceId: ${voiceId}`);
    const voiceName = getAliyunVoice(voiceId);
    const selectedModel = (type !== 'mock') ? getRandomModel() : undefined;
    console.log(`🎲 selectedModel: ${selectedModel}`);

    // 根据 Provider 类型决定分段策略
    let segments: string[];
    if (type === 'realtime') {
      segments = [text];
      console.log(`📝 使用 Qwen Realtime TTS，文本长度 ${text.length} 字符（不需分段）`);
    } else {
      segments = splitText(text);
      console.log(`📝 文本已分段: ${segments.length} 段`);
    }

    segments.forEach((seg, i) => {
      console.log(`   段落 ${i + 1}: ${seg.length} 字符`);
    });

    // 并行生成各段音频
    const audioFiles: string[] = [];
    const cloudUrls: string[] = [];
    const concurrency = type === 'realtime' ? 1 : 2;

    for (let i = 0; i < segments.length; i += concurrency) {
      const batch = segments.slice(i, i + concurrency);
      
      // 根据类型选择调用方式
      let results: string[];
      if (type === 'mock') {
        results = await Promise.all(
          batch.map((segment, idx) =>
            (provider as any).synthesize(segment, voiceName, voiceParams, path.join(audioDir, `segment_${i + idx}.mp3`))
          )
        );
      } else {
        results = await Promise.all(
          batch.map((segment, idx) =>
            (provider as any).synthesize(segment, voiceName, voiceParams, path.join(audioDir, `segment_${i + idx}.mp3`), 3, selectedModel)
          )
        );
      }
      results.forEach(r => {
        if (r.startsWith('cloud:')) {
          cloudUrls.push(r.substring(6));
        } else {
          audioFiles.push(r);
        }
      });
    }

    console.log(`📁 生成了 ${audioFiles.length} 个音频文件, ${cloudUrls.length} 个云端URL`);

    let audioUrl = '';
    let duration = 0;
    let size = 0;

    if (cloudUrls.length > 0) {
      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/${audioDir.split(/[/\\]/).pop()}/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] : audioUrl;

    // 更新数据库记录
    await prisma.audio.update({
      where: { id: audioRecordId },
      data: {
        title,
        summary,
        tags: JSON.stringify(tags),
        audioUrl: finalAudioUrl,
        audioDuration: duration,
        audioSize: size,
        status: 'completed',
      },
    });

    console.log('✅ 音频生成完成:', audioRecordId);
  } catch (error) {
    console.error('❌ processAudioGeneration 错误:', error);
    throw error;
  }
}

/**
 * 获取音频状态
 */
export async function getAudioStatus(audioId: string): Promise<{ status: string; audio?: any }> {
  const id = parseInt(audioId);
  if (isNaN(id)) {
    return { status: 'not_found' };
  }

  const audio = await prisma.audio.findUnique({ where: { id } });
  if (!audio) {
    return { status: 'not_found' };
  }

  return { status: audio.status, audio };
}

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