const fs = require('fs');
const path = require('path');
const { exec } = require('child_process');
const { logSnapshot } = require('./log');


function snapshot(outDir, cam0, cam1, ws){
    
    if (!fs.existsSync(outDir)) fs.mkdirSync(outDir, { recursive: true });
    const picDate = Date.now();
    const name0 = `snapshot_video0_${picDate}.jpg`;
    const name1 = `snapshot_video1_${picDate}.jpg`;
    cam0.snapshot(path.join(outDir, name0));
    cam1.snapshot(path.join(outDir, name1));
    

    strFile0 = path.join(outDir, name0);
    strFile1 = path.join(outDir, name1);

    const relUrl = `/snapshots/${name0}`;
    const relUrlApp = `/snapshots/${name0.replace('.jpg','_two_cam_annotated.jpg')}`;
    // The Python postprocessor writes an overlay named "_two_cam_overlay.png" and a CSV named "_two_cam.csv"
    const relOverlay = `/snapshots/${name0.replace('.jpg','_two_cam_overlay.png')}`;
    const relOverlayCSV = `/snapshots/${name0.replace('.jpg','_two_cam.csv')}`;

    const annotatedPath = path.join(outDir, name0.replace('.jpg','_two_cam_annotated.jpg'));
    const overlayPath = path.join(outDir, name0.replace('.jpg','_two_cam_overlay.png'));
    const csvPath = path.join(outDir, name0.replace('.jpg','_two_cam.csv'));
    
    

    const command = `python3 /usr/src/app/programs/readTwoImages.py -i ${strFile0} -i ${strFile1} -npz /usr/src/app/data/settings/callibration_cam0.npz -npz /usr/src/app/data/settings/callibration_cam1.npz -settings /usr/src/app/data/settings/settings.json`;
    console.log("Executing Python " + command);

    // Run the Python post-processing and send the snapshot response only
    // after the annotated files are present to avoid transient 404s in the browser.
    exec(command, (error, stdout, stderr) => {
        try {
            if (error) {
                console.error(`Error: ${error.message}`);
                // Capture which generated files actually exist for debugging
                const files = {
                    annotated: fs.existsSync(annotatedPath),
                    overlay: fs.existsSync(overlayPath),
                    csv: fs.existsSync(csvPath)
                };
                // Log full details server-side for diagnosis
                const detailed = {
                    type: 'snapshot',
                    ok: false,
                    error: error.message,
                    stdout: String(stdout).slice(0, 4096),
                    stderr: String(stderr).slice(0, 4096),
                    files
                };
                logSnapshot(command, JSON.stringify(detailed));

                // Send a short, user-friendly error to the client (no large stdout/stderr)
                const shortError = String(stderr || error.message || '').includes('Corrupt JPEG')
                    ? 'postprocessor failed: corrupt JPEG input'
                    : 'postprocessor failed';
                try { ws.send(JSON.stringify({ type: 'snapshot', ok: false, error: shortError })); } catch (e) {}
                return;
            }

            if (stderr) {
                // Log stderr but don't fail outright; sometimes tools output warnings on stderr.
                if (String(stderr).trim()) console.error(`Stderr: ${stderr}`);
            }

            console.log(`Output:\n${stdout}`);

            // Wait up to ~1s (10 * 100ms) for the generated files to appear on disk.
            const waitForFiles = (paths, attempts = 10, delayMs = 100) => new Promise((resolve) => {
                let tries = 0;
                (function poll() {
                    const ok = paths.every(p => fs.existsSync(p));
                    if (ok || tries >= attempts) return resolve(ok);
                    tries++;
                    setTimeout(poll, delayMs);
                })();
            });

            waitForFiles([annotatedPath, overlayPath, csvPath]).then((found) => {
                if (!found) {
                    const files = {
                        annotated: fs.existsSync(annotatedPath),
                        overlay: fs.existsSync(overlayPath),
                        csv: fs.existsSync(csvPath)
                    };
                    // Log details server-side
                    const detailed = {
                        type: 'snapshot',
                        ok: false,
                        url: relUrl,
                        urlApp: relUrlApp,
                        overlay: relOverlay,
                        overlayCSV: relOverlayCSV,
                        files
                    };
                    logSnapshot(command, JSON.stringify(detailed));
                    // Send a concise error to the client
                    try { ws.send(JSON.stringify({ type: 'snapshot', ok: false, error: 'postprocessor incomplete (missing outputs)' })); } catch (e) {}
                    return;
                }

                const response = JSON.stringify({
                    type: 'snapshot',
                    ok: found,
                    url: relUrl,
                    urlApp: relUrlApp,
                    overlay: relOverlay,
                    overlayCSV: relOverlayCSV
                });
                logSnapshot(command, response);
                try { ws.send(response); } catch (e) {}
            }).catch((waitErr) => {
                console.error('waitForFiles failed:', waitErr);
                const response = JSON.stringify({ type: 'snapshot', ok: false, error: String(waitErr) });
                logSnapshot(command, response);
                try { ws.send(response); } catch (e) {}
            });
        } catch (handlerErr) {
            console.error('snapshot handler error:', handlerErr);
            const response = JSON.stringify({ type: 'snapshot', ok: false, error: String(handlerErr) });
            logSnapshot(command, response);
            try { ws.send(response); } catch (e) {}
        }
    });
    

}


module.exports = { snapshot };