import 'dotenv/config';
import axios from 'axios';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const API_KEY = process.env.ASSEMBLYAI_API_KEY;
const BASE_URL = 'https://api.assemblyai.com/v2';

/**
 * Uploads audio file to AssemblyAI
 */
async function uploadAudio(audioPath: string): Promise<string> {
  const audioData = fs.readFileSync(audioPath);
  
  const response = await axios.post<{ upload_url: string }>(`${BASE_URL}/upload`, audioData, {
    headers: {
      'authorization': API_KEY,
      'content-type': 'application/octet-stream'
    }
  });
  
  return response.data.upload_url;
}

/**
 * Extract a session id (basename without extension) from a local path or a URL
 */
function getSessionId(inputPath: string): string {
  try {
    const parsed = new URL(inputPath);
    const base = path.basename(parsed.pathname);
    return base.replace(/\.[^.]+$/, '');
  } catch (err) {
    // not a URL, treat as local path
    return path.basename(inputPath, path.extname(inputPath));
  }
}

/**
 * Creates transcription job with speaker diarization
 */
async function createTranscript(audioUrl: string): Promise<string> {
  const response = await axios.post<{ id: string }>(`${BASE_URL}/transcript`, {
    audio_url: audioUrl,
    speaker_labels: true,
    language_detection: true
  }, {
    headers: {
      'authorization': API_KEY,
      'content-type': 'application/json'
    }
  });
  
  return response.data.id;
}

/**
 * Polls transcript status until completed
 */
async function pollTranscript(transcriptId: string): Promise<any> {
  while (true) {
    const response = await axios.get<any>(`${BASE_URL}/transcript/${transcriptId}`, {
      headers: { 'authorization': API_KEY }
    });
    
    const status = response.data.status;
    
    if (status === 'completed') {
      return response.data;
    } else if (status === 'error') {
      throw new Error(`Transcription failed: ${response.data.error}`);
    }
    
    // Wait 3 seconds before next poll
    await new Promise(resolve => setTimeout(resolve, 3000));
  }
}

/**
 * Saves transcript to storage
 */
function saveTranscript(transcript: any, sessionId: string): void {
  const outputDir = path.join(__dirname, '..', '..', '..', 'storage', 'transcripts');
  
  if (!fs.existsSync(outputDir)) {
    fs.mkdirSync(outputDir, { recursive: true });
  }
  
  const outputPath = path.join(outputDir, `${sessionId}.json`);
  fs.writeFileSync(outputPath, JSON.stringify(transcript, null, 2));
  
  console.log(`✅ Transcript saved: ${outputPath}`);
}

export default {
  name: "assembly",
  type: "transcription",
  displayname: "AssemblyAI",
  run: async (audioPath: string) => {
    try {
      // Determine if audioPath is an external URL or a local file
      let audioUrl: string;
      if (/^https?:\/\//i.test(audioPath)) {
        console.log('🔗 Using external audio URL...');
        audioUrl = audioPath;
      } else {
        console.log('🔄 Uploading local audio...');
        if (!fs.existsSync(audioPath)) {
          throw new Error(`Audio file not found: ${audioPath}`);
        }
        audioUrl = await uploadAudio(audioPath);
      }
      
      console.log('🔄 Creating transcript job...');
      const transcriptId = await createTranscript(audioUrl);
      
      console.log('⏳ Waiting for transcription...');
      const transcript = await pollTranscript(transcriptId);
      
  const sessionId = getSessionId(audioPath);
      saveTranscript(transcript, sessionId);
      
      return transcript;
    } catch (error: any) {
      console.error('❌ Transcription error:', error.message);
      throw error;
    }
  }
};