/**
 * src/media/index.ts
 * منسق الوسائط — Media pipeline orchestrator
 * Unified entry point for all incoming/outgoing media processing
 */
import { execFile } from 'node:child_process';
import { promisify } from 'node:util';
import { mkdir } from 'node:fs/promises';
import { join } from 'node:path';
import { createChildLogger } from '../utils/logger.js';
import { describeImage, readTextFromImage, analyzeDocument } from './vision.js';
import { transcribeAudio, synthesizeSpeech, processVoiceNote } from './voice.js';
import { generatePDF, markdownToHTML } from './pdf.js';
const log = createChildLogger('media:orchestrator');
const execFileAsync = promisify(execFile);
// ─── Re-exports ──────────────────────────────────────────────────────
export { describeImage, readTextFromImage, analyzeDocument, transcribeAudio, synthesizeSpeech, processVoiceNote, generatePDF, markdownToHTML, };
export { generateReport, generateInvoice } from './pdf.js';
// ─── Incoming Media Processing ───────────────────────────────────────
/**
 * معالجة الوسائط الواردة — Unified entry point for incoming media
 */
export async function processIncomingMedia(type, filePath, context) {
    log.info({ type, filePath, context }, 'Processing incoming media');
    try {
        switch (type) {
            case 'image': {
                const result = await describeImage(filePath, context);
                return {
                    processedContent: result.description,
                    mediaType: 'image',
                    metadata: { tokensUsed: result.tokensUsed, cost: result.cost },
                };
            }
            case 'audio': {
                const result = await transcribeAudio(filePath);
                return {
                    processedContent: result.text,
                    mediaType: 'audio',
                    metadata: {
                        language: result.language,
                        duration: result.duration,
                    },
                };
            }
            case 'video': {
                // Basic: extract first frame → describe
                const framePath = await extractVideoFrame(filePath);
                if (framePath) {
                    const result = await describeImage(framePath, context || 'صف محتوى هذا الفيديو من الإطار الأول');
                    return {
                        processedContent: result.description,
                        mediaType: 'video',
                        metadata: {
                            tokensUsed: result.tokensUsed,
                            cost: result.cost,
                            note: 'Based on first frame only',
                        },
                    };
                }
                return {
                    processedContent: 'لم أتمكن من معالجة هذا الفيديو. Could not process this video.',
                    mediaType: 'video',
                    metadata: { error: 'Frame extraction failed' },
                };
            }
            case 'document': {
                const result = await analyzeDocument(filePath);
                return {
                    processedContent: result.description,
                    mediaType: 'document',
                    metadata: { tokensUsed: result.tokensUsed, cost: result.cost },
                };
            }
            default: {
                log.warn({ type }, 'Unknown media type');
                return {
                    processedContent: `نوع الوسائط غير مدعوم: ${type}`,
                    mediaType: type,
                };
            }
        }
    }
    catch (error) {
        log.error({ error, type, filePath }, 'Failed to process incoming media');
        const errorMsg = error instanceof Error ? error.message : String(error);
        return {
            processedContent: `خطأ في معالجة الوسائط: ${errorMsg}`,
            mediaType: type,
            metadata: { error: errorMsg },
        };
    }
}
// ─── Outgoing Media Preparation ──────────────────────────────────────
/**
 * تحضير الوسائط الصادرة — Prepare media for sending
 */
export async function prepareOutgoingMedia(type, content, options) {
    log.info({ type, contentLength: content.length }, 'Preparing outgoing media');
    try {
        switch (type) {
            case 'voice': {
                const speechResult = await synthesizeSpeech(content, {
                    voice: options?.voice,
                    speed: options?.speed,
                });
                return {
                    processedContent: content,
                    mediaPath: speechResult.filePath,
                    mediaType: 'audio/mpeg',
                };
            }
            case 'pdf': {
                const htmlContent = markdownToHTML(content, options?.rtl ?? true);
                const outputPath = options?.outputPath || join('/tmp/muassis-pdf', `doc-${Date.now()}.pdf`);
                await mkdir('/tmp/muassis-pdf', { recursive: true });
                const pdfPath = await generatePDF(htmlContent, outputPath);
                return {
                    processedContent: content,
                    mediaPath: pdfPath,
                    mediaType: 'application/pdf',
                };
            }
            case 'excel': {
                // Placeholder — not yet implemented
                log.warn('Excel generation not yet implemented');
                return {
                    processedContent: content,
                    mediaType: 'text/plain',
                };
            }
            default: {
                return {
                    processedContent: content,
                };
            }
        }
    }
    catch (error) {
        log.error({ error, type }, 'Failed to prepare outgoing media');
        return {
            processedContent: content,
            metadata: { error: error instanceof Error ? error.message : String(error) },
        };
    }
}
// ─── Video Frame Extraction ──────────────────────────────────────────
/**
 * Extract first frame from a video using ffmpeg
 */
async function extractVideoFrame(videoPath) {
    const tmpDir = '/tmp/muassis-vision';
    await mkdir(tmpDir, { recursive: true });
    const outputPath = join(tmpDir, `frame-${Date.now()}.jpg`);
    try {
        await execFileAsync('ffmpeg', [
            '-i', videoPath,
            '-vframes', '1',
            '-q:v', '2',
            '-y',
            outputPath,
        ], { timeout: 15_000 });
        log.debug({ videoPath, outputPath }, 'Video frame extracted');
        return outputPath;
    }
    catch (error) {
        log.warn({ error, videoPath }, 'Failed to extract video frame (ffmpeg may not be installed)');
        return null;
    }
}
//# sourceMappingURL=index.js.map