import { spawn } from 'child_process';
import path from 'path';
import fs from 'fs';

export class SimpleTranscriptionService {
  private static instance: SimpleTranscriptionService;
  
  static getInstance(): SimpleTranscriptionService {
    if (!SimpleTranscriptionService.instance) {
      SimpleTranscriptionService.instance = new SimpleTranscriptionService();
    }
    return SimpleTranscriptionService.instance;
  }

  async transcribeAudio(audioPath: string): Promise<string> {
    try {
      console.log(`Audio transcription requested for: ${audioPath}`);
      
      // Primary: Use SimpleWhisper for local transcription
      try {
        const simpleWhisperResult = await this.transcribeWithSimpleWhisper(audioPath);
        if (simpleWhisperResult && simpleWhisperResult !== "Audio message (transcription unavailable)") {
          return simpleWhisperResult;
        }
      } catch (whisperError) {
        console.warn("SimpleWhisper transcription failed, trying OpenAI fallback:", whisperError);
      }
      
      // Fallback: Try OpenAI API if SimpleWhisper fails
      const apiKey = process.env.OPENAI_API_KEY;
      if (apiKey) {
        return await this.transcribeWithOpenAI(audioPath, apiKey);
      }
      
      // Final fallback for deployment without any transcription services
      return "Audio message (transcription unavailable)";
      
    } catch (error) {
      console.error("Transcription service error:", error);
      return "Audio message (transcription unavailable)";
    }
  }

  private async transcribeWithSimpleWhisper(audioPath: string): Promise<string> {
    return new Promise((resolve, reject) => {
      console.log(`Starting SimpleWhisper transcription for: ${audioPath}`);
      
      // Try multiple Python whisper approaches
      const whisperCommands = [
        ['python3', '-m', 'whisper', audioPath, '--model', 'base', '--output_format', 'txt', '--output_dir', '/tmp', '--language', 'auto'],
        ['python', '-m', 'whisper', audioPath, '--model', 'base', '--output_format', 'txt', '--output_dir', '/tmp', '--language', 'auto'],
        ['whisper', audioPath, '--model', 'base', '--output_format', 'txt', '--output_dir', '/tmp', '--language', 'auto']
      ];
      
      let attemptIndex = 0;
      
      const tryNextCommand = () => {
        if (attemptIndex >= whisperCommands.length) {
          reject(new Error('All whisper command attempts failed'));
          return;
        }
        
        const command = whisperCommands[attemptIndex];
        console.log(`Attempting whisper with command ${attemptIndex + 1}: ${command.join(' ')}`);
        
        const whisperProcess = spawn(command[0], command.slice(1), {
          stdio: ['ignore', 'pipe', 'pipe'],
          env: {
            ...process.env,
            PATH: `${process.env.HOME}/.local/bin:${process.env.PATH}:/usr/local/bin`
          }
        });

        let output = '';
        let errorOutput = '';

        whisperProcess.stdout.on('data', (data) => {
          output += data.toString();
        });

        whisperProcess.stderr.on('data', (data) => {
          errorOutput += data.toString();
        });

        whisperProcess.on('close', (code) => {
          if (code === 0) {
            // Try to read the output file
            const outputFileName = path.basename(audioPath, path.extname(audioPath)) + '.txt';
            const outputPath = path.join('/tmp', outputFileName);
            
            try {
              if (fs.existsSync(outputPath)) {
                const transcription = fs.readFileSync(outputPath, 'utf8').trim();
                // Clean up temp file
                fs.unlinkSync(outputPath);
                
                if (transcription && transcription.length > 0) {
                  console.log(`SimpleWhisper transcription successful with command ${attemptIndex + 1}`);
                  resolve(transcription);
                } else {
                  resolve("Audio message (empty transcription)");
                }
              } else {
                // Try to extract from stdout
                const cleanOutput = output.trim();
                if (cleanOutput && cleanOutput.length > 0) {
                  resolve(cleanOutput);
                } else {
                  resolve("Audio message (no output file)");
                }
              }
            } catch (fileError) {
              console.error('Error reading whisper output:', fileError);
              resolve("Audio message (transcription file error)");
            }
          } else {
            console.warn(`Command ${attemptIndex + 1} failed with code ${code}: ${errorOutput}`);
            attemptIndex++;
            tryNextCommand();
          }
        });

        whisperProcess.on('error', (error) => {
          console.warn(`Command ${attemptIndex + 1} error:`, error);
          attemptIndex++;
          tryNextCommand();
        });

        // Set timeout to prevent hanging
        setTimeout(() => {
          whisperProcess.kill();
          reject(new Error('SimpleWhisper transcription timeout'));
        }, 60000); // 60 second timeout
      };
      
      tryNextCommand();
    });
  }

  // OpenAI Whisper API implementation (no heavy dependencies)
  async transcribeWithOpenAI(audioPath: string, apiKey?: string): Promise<string> {
    if (!apiKey) {
      return "Audio message (OpenAI API key required for transcription)";
    }
    
    try {
      const fs = await import('fs');
      const formData = new FormData();
      
      // Read the audio file
      const audioBuffer = fs.readFileSync(audioPath);
      const audioBlob = new Blob([audioBuffer]);
      formData.append('file', audioBlob, 'audio.mp3');
      formData.append('model', 'whisper-1');
      
      const response = await fetch('https://api.openai.com/v1/audio/transcriptions', {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${apiKey}`,
        },
        body: formData,
      });
      
      if (!response.ok) {
        throw new Error(`OpenAI API error: ${response.status}`);
      }
      
      const result = await response.json();
      return result.text || "No speech detected";
      
    } catch (error) {
      console.error("OpenAI transcription error:", error);
      return "Audio message (transcription failed)";
    }
  }
}