import { Readable, PassThrough } from 'stream';
import * as os from 'os';
import * as path from 'path';
import * as fs from 'fs';

// Lazy-load ffmpeg pour éviter les side-effects au moment de l'import
// (les packages @ffmpeg-installer/* cherchent des binaires natifs, ce qui peut bloquer le build SSR)
let _ffmpeg: typeof import('fluent-ffmpeg').default | null = null;

async function getFfmpeg() {
	if (!_ffmpeg) {
		const ffmpegModule = await import('fluent-ffmpeg');
		const ffmpegPath = await import('@ffmpeg-installer/ffmpeg');
		const ffprobePath = await import('@ffprobe-installer/ffprobe');
		_ffmpeg = ffmpegModule.default;
		_ffmpeg.setFfmpegPath(ffmpegPath.default.path);
		_ffmpeg.setFfprobePath(ffprobePath.default.path);
	}
	return _ffmpeg;
}

/**
 * Génère une thumbnail depuis une vidéo
 * @param videoBuffer Buffer de la vidéo
 * @param timeInSeconds Moment de capture (en secondes)
 * @returns Buffer de l'image thumbnail (JPEG)
 */
export async function generateThumbnail(
	videoBuffer: Buffer,
	timeInSeconds: number = 1
): Promise<Buffer> {
	const ffmpeg = await getFfmpeg();
	return new Promise((resolve, reject) => {
		// Créer un fichier temporaire pour la vidéo
		const tempDir = os.tmpdir();
		const tempVideoPath = path.join(tempDir, `video_${Date.now()}.tmp`);
		const tempThumbPath = path.join(tempDir, `thumb_${Date.now()}.jpg`);
		
		try {
			// Écrire le buffer dans un fichier temporaire
			fs.writeFileSync(tempVideoPath, videoBuffer);
			
			ffmpeg(tempVideoPath)
				.screenshots({
					timestamps: [timeInSeconds],
					filename: path.basename(tempThumbPath),
					folder: path.dirname(tempThumbPath),
					size: '640x360'
				})
				.on('end', () => {
					try {
						// Lire le thumbnail généré
						const thumbnailBuffer = fs.readFileSync(tempThumbPath);
						
						// Nettoyer les fichiers temporaires
						fs.unlinkSync(tempVideoPath);
						fs.unlinkSync(tempThumbPath);
						
						resolve(thumbnailBuffer);
					} catch (err) {
						reject(new Error(`Erreur lecture thumbnail: ${err}`));
					}
				})
				.on('error', (err) => {
					// Nettoyer les fichiers temporaires en cas d'erreur
					if (fs.existsSync(tempVideoPath)) fs.unlinkSync(tempVideoPath);
					if (fs.existsSync(tempThumbPath)) fs.unlinkSync(tempThumbPath);
					reject(new Error(`Erreur génération thumbnail: ${err.message}`));
				});
		} catch (err) {
			// Nettoyer en cas d'erreur initiale
			if (fs.existsSync(tempVideoPath)) fs.unlinkSync(tempVideoPath);
			reject(new Error(`Erreur création fichier temporaire: ${err}`));
		}
	});
}

/**
 * Extrait les métadonnées d'une vidéo
 * @param videoBuffer Buffer de la vidéo
 * @returns Métadonnées (durée, résolution, codec, etc.)
 */
export async function getVideoMetadata(videoBuffer: Buffer): Promise<{
	duration: number;
	width: number;
	height: number;
	codec: string;
	bitrate: number;
	fps: number;
}> {
	const ffmpeg = await getFfmpeg();
	return new Promise((resolve, reject) => {
		const videoStream = Readable.from(videoBuffer);
		
		ffmpeg.ffprobe(videoStream, (err, metadata) => {
			if (err) {
				reject(new Error(`Erreur lecture métadonnées: ${err.message}`));
				return;
			}
			
			const videoStream = metadata.streams.find(s => s.codec_type === 'video');
			
			if (!videoStream) {
				reject(new Error('Aucun stream vidéo trouvé'));
				return;
			}
			
			resolve({
				duration: metadata.format.duration || 0,
				width: videoStream.width || 0,
				height: videoStream.height || 0,
				codec: videoStream.codec_name || 'unknown',
				bitrate: metadata.format.bit_rate || 0,
				fps: eval(videoStream.r_frame_rate || '0') || 0
			});
		});
	});
}

/**
 * Génère une thumbnail et la retourne en base64
 * @param videoBuffer Buffer de la vidéo
 * @param timeInSeconds Moment de capture
 * @returns Data URL (base64) de la thumbnail
 */
export async function generateThumbnailBase64(
	videoBuffer: Buffer,
	timeInSeconds: number = 1
): Promise<string> {
	const thumbnailBuffer = await generateThumbnail(videoBuffer, timeInSeconds);
	return `data:image/jpeg;base64,${thumbnailBuffer.toString('base64')}`;
}
