#!/usr/bin/env node
/**
 * Forecast Pipeline Orchestrator
 *
 * Spawns the Python forecast engine with database credentials from the
 * environment. Can be run manually, via cron, or integrated into the
 * existing metrics pipeline.
 *
 * Usage:
 *   node run_forecast.js
 *
 * Environment:
 *   Reads DB_HOST, DB_USER, DB_PASSWORD, DB_NAME, DB_PORT from
 *   /var/www/inventory/.env (or current process env).
 */

// Run in business time (see docs/TIME.md); the spawned Python engine and any
// incidental Date math inherit it.
process.env.TZ = process.env.TZ || 'America/Chicago';

const { spawn } = require('child_process');
const path = require('path');
const fs = require('fs');

// Load .env file if it exists (production path)
const envPaths = [
    '/var/www/inventory/.env',
    path.join(__dirname, '../../.env'),
];

for (const envPath of envPaths) {
    if (fs.existsSync(envPath)) {
        const envContent = fs.readFileSync(envPath, 'utf-8');
        for (const line of envContent.split('\n')) {
            const trimmed = line.trim();
            if (!trimmed || trimmed.startsWith('#')) continue;
            const eqIndex = trimmed.indexOf('=');
            if (eqIndex === -1) continue;
            const key = trimmed.slice(0, eqIndex);
            const value = trimmed.slice(eqIndex + 1);
            if (!process.env[key]) {
                process.env[key] = value;
            }
        }
        console.log(`Loaded env from ${envPath}`);
        break;
    }
}

// Verify required env vars
const required = ['DB_HOST', 'DB_USER', 'DB_PASSWORD', 'DB_NAME'];
const missing = required.filter(k => !process.env[k]);
if (missing.length > 0) {
    console.error(`Missing required environment variables: ${missing.join(', ')}`);
    process.exit(1);
}

const SCRIPT_DIR = __dirname;
const PYTHON_SCRIPT = path.join(SCRIPT_DIR, 'forecast_engine.py');
const VENV_DIR = path.join(SCRIPT_DIR, 'venv');
const REQUIREMENTS = path.join(SCRIPT_DIR, 'requirements.txt');

// Determine python binary (prefer venv if it exists)
function getPythonBin() {
    const venvPython = path.join(VENV_DIR, 'bin', 'python');
    if (fs.existsSync(venvPython)) return venvPython;

    // Fall back to system python
    return 'python3';
}

// Ensure venv and dependencies are installed
async function ensureDependencies() {
    if (!fs.existsSync(path.join(VENV_DIR, 'bin', 'python'))) {
        console.log('Creating virtual environment...');
        await runCommand('python3', ['-m', 'venv', VENV_DIR]);
    }

    // Always run pip install — idempotent, fast when packages already present
    console.log('Checking dependencies...');
    const python = path.join(VENV_DIR, 'bin', 'python');
    await runCommand(python, ['-m', 'pip', 'install', '--quiet', '-r', REQUIREMENTS]);
}

function runCommand(cmd, args, options = {}) {
    return new Promise((resolve, reject) => {
        const proc = spawn(cmd, args, {
            stdio: 'inherit',
            ...options,
        });
        proc.on('close', code => {
            if (code === 0) resolve();
            else reject(new Error(`${cmd} exited with code ${code}`));
        });
        proc.on('error', reject);
    });
}

async function main() {
    const startTime = Date.now();
    console.log('='.repeat(60));
    console.log(`Forecast Pipeline - ${new Date().toISOString()}`);
    console.log('='.repeat(60));

    try {
        await ensureDependencies();

        const pythonBin = getPythonBin();
        console.log(`Using Python: ${pythonBin}`);
        console.log(`Running: ${PYTHON_SCRIPT}`);
        console.log('');

        await runCommand(pythonBin, [PYTHON_SCRIPT], {
            env: {
                ...process.env,
                PYTHONUNBUFFERED: '1',  // Real-time output
            },
        });

        const duration = ((Date.now() - startTime) / 1000).toFixed(1);
        console.log('');
        console.log('='.repeat(60));
        console.log(`Forecast pipeline completed in ${duration}s`);
        console.log('='.repeat(60));
    } catch (err) {
        const duration = ((Date.now() - startTime) / 1000).toFixed(1);
        console.error(`Forecast pipeline FAILED after ${duration}s:`, err.message);
        process.exit(1);
    }
}

main();
