import ffmpegInstaller from '@ffmpeg-installer/ffmpeg';
import ffmpeg from 'fluent-ffmpeg';
import fs from 'fs';
import YTDlpWrap from 'yt-dlp-wrap';
import { logger } from '../server-utils/logger.js';

ffmpeg.setFfmpegPath(ffmpegInstaller.path);
const ytDlpWrap = new (YTDlpWrap as any).default();

export const getAudioMetadataFromUrl = async (url: string) => {
  try {
    return await ytDlpWrap.getVideoInfo([url, '--no-playlist', '--format', 'bestaudio']);
  } catch (error) {
    logger.error('Error getting video info:', error);
    throw new Error(error);
  }
};

const getAudioFromVideoUrl = async (url: string, uuid: string, s3Key: string): Promise<Buffer> => {
  return new Promise(async (resolve, reject) => {
    if (url.includes('suno.com/song/')) {
      const sunoId = url.split('suno.com/song/')[1];
      const sunoMp3Url = `https://cdn1.suno.ai/${sunoId}.mp3`;
      const songResp = await fetch(sunoMp3Url);
      const reader = songResp.body.getReader();

      const data = [];
      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        data.push(value);
      }
      const buffer = Buffer.concat(data);
      resolve(buffer);
      return;
    }

    ytDlpWrap
      .exec([url, '--no-playlist', '--format', 'bestaudio', '-o', `/tmp/${uuid}`])
      .on('ytDlpEvent', (eventType, eventData) => console.log(eventType, eventData))
      .on('error', (error) => {
        console.error(error);
        reject(error);
      })
      .on('close', () => {
        const rx = new RegExp(`^${uuid}(\.[0-9a-zA-Z]+)?$`); // skips temporary files created by yt-dlp
        const file = fs.readdirSync('/tmp').find((file) => rx.test(file));
        if (file === undefined) {
          reject('No file found');
          return;
        }
        ffmpeg(`/tmp/${file}`)
          .noVideo()
          .audioCodec('libopus')
          .audioBitrate('160k')
          .save(`/tmp/${s3Key}`)
          .on('end', () => {
            console.log('Audio extraction complete');
            fs.unlinkSync(`/tmp/${file}`);
            fs.readFile(`/tmp/${s3Key}`, (err, data) => {
              resolve(data);
              fs.unlinkSync(`/tmp/${s3Key}`);
            });
          })
          .on('error', (err) => {
            console.error('Error extracting audio:', err);
            reject(err);
          });
      });
  });
};

export default getAudioFromVideoUrl;
