#!/usr/bin/env php
<?php
/**
 * Schedule proposal — generates cron (Linux) or schtasks (Windows) commands
 * for daily backup, log rotation, and ASH charge collection.
 *
 * Usage:
 *   php exploitation/schedule.php [options]
 *
 * Options:
 *   -i, --install         Execute the commands (install the schedule)
 *   -u, --uninstall       Remove the scheduled tasks
 *   -q, --quiet           Suppress output except errors
 *   -h, --help            Show this help
 *
 * Without -i, the script only DISPLAYS the commands to run.
 *
 * Default schedule:
 *   Log rotate    — daily at 00:05, retention 8 days
 *   Backup        — daily at 02:00, retention 8 days
 *   Collect ASH   — daily at 06:00, 30 days depth
 *   Collect CMDB  — 1st of each month at 06:30
 *   Collect RMAN  — daily at 05:00, 13:00 and 21:00 (RMAN backup catalogs)
 *   Collect users — daily at 01:00 (Oracle user inventory)
 *   Schedule rpts — daily at 00:05 (report email orchestrator)
 *   Remediate    — daily at 20:00 (Oracle user remediation ALTER USER)
 */

require_once dirname(__DIR__) . '/shared/cli_bootstrap.php';

$opts = getopt('iuqh', ['install', 'uninstall', 'quiet', 'help']);

if (isset($opts['h']) || isset($opts['help'])) cli_show_help(__FILE__);

$install   = isset($opts['i']) || isset($opts['install']);
$uninstall = isset($opts['u']) || isset($opts['uninstall']);
$quiet     = isset($opts['q']) || isset($opts['quiet']);

$isWindows = PHP_OS_FAMILY === 'Windows';
$phpBin    = PHP_BINARY;
$appDir    = realpath(ROOT_PATH);

function out(string $msg): void {
    global $quiet;
    if (!$quiet) echo $msg . PHP_EOL;
}

/* ══════════════════════════════════════════════════════════════════════
 *  Linux — crontab
 * ══════════════════════════════════════════════════════════════════════ */
if (!$isWindows) {

    $marker = '# sw-app-exploitation';

    // Jobs = cœur + modules actifs (source unique ScheduleRegistry), scripts présents.
    // $cronJobs : [ligne cron complète, jeton de dédup/désinstallation (basename)].
    $cronJobs = [];
    foreach (ScheduleRegistry::jobs($moduleRegistry) as $j) {
        $line       = "{$j['cron']} cd {$appDir} && {$phpBin} {$j['script']} {$j['args']}";
        $cronJobs[] = [$line, basename($j['script'])];
    }

    if ($uninstall) {
        /* Remove our lines from crontab : toute ligne marquée, ou contenant un
           script connu (couvre aussi les anciens chemins, basenames identiques). */
        $tokens   = array_map(fn($j) => $j[1], $cronJobs);
        $existing = shell_exec('crontab -l 2>/dev/null') ?? '';
        $lines = array_filter(explode("\n", $existing), function ($line) use ($marker, $tokens) {
            if (str_contains($line, $marker)) return false;
            foreach ($tokens as $t) {
                if ($t !== '' && str_contains($line, $t)) return false;
            }
            return true;
        });
        $new = implode("\n", $lines);
        $tmp = tempnam(sys_get_temp_dir(), 'cron_');
        file_put_contents($tmp, trim($new) . "\n");
        exec("crontab {$tmp}", $output, $rc);
        unlink($tmp);
        out($rc === 0 ? 'OK: Crontab entries removed.' : 'ERROR: Could not update crontab.');
        exit($rc === 0 ? 0 : 1);
    }

    if (!$install) {
        /* Display only */
        out('');
        out('=== Proposition d\'ordonnancement (Linux crontab) ===');
        out('');
        out('Ajoutez les lignes suivantes à votre crontab (crontab -e) :');
        out('');
        foreach ($cronJobs as $j) { out("  {$j[0]}"); }
        out('');
        out('Ou lancez ce script avec --install pour les ajouter automatiquement :');
        out('');
        out("  {$phpBin} exploitation/schedule.php --install");
        out('');
        out('Pour supprimer les entrées :');
        out('');
        out("  {$phpBin} exploitation/schedule.php --uninstall");
        out('');
        exit(0);
    }

    /* Install — append to crontab if not already present */
    $existing = shell_exec('crontab -l 2>/dev/null') ?? '';

    $toAdd = [];
    foreach ($cronJobs as $j) {
        [$line, $token] = $j;
        if (!str_contains($existing, $token)) {
            $toAdd[] = $line . "  {$marker}";
        } else {
            out("SKIP: {$token} entry already in crontab.");
        }
    }

    if (empty($toAdd)) {
        out('Nothing to add — all entries already present.');
        exit(0);
    }

    $new = trim($existing) . "\n" . implode("\n", $toAdd) . "\n";
    $tmp = tempnam(sys_get_temp_dir(), 'cron_');
    file_put_contents($tmp, $new);
    exec("crontab {$tmp}", $output, $rc);
    unlink($tmp);

    if ($rc === 0) {
        out('OK: ' . count($toAdd) . ' crontab entry(ies) added.');
    } else {
        out('ERROR: Could not update crontab (exit code ' . $rc . ').');
    }
    exit($rc === 0 ? 0 : 1);
}

/* ══════════════════════════════════════════════════════════════════════
 *  Windows — schtasks
 * ══════════════════════════════════════════════════════════════════════ */

// Jobs Windows = cœur + modules actifs (source unique), scripts présents.
// [tâche, commande, heure (win_st), fréquence (win_sc)].
$winJobs = [];
foreach (ScheduleRegistry::jobs($moduleRegistry) as $j) {
    $cmd = "{$phpBin} {$appDir}\\" . str_replace('/', '\\', $j['script']) . " {$j['args']}";
    $winJobs[] = [$j['task'], $cmd, $j['win_st'], $j['win_sc']];
}

if ($uninstall) {
    foreach ($winJobs as [$tn]) {
        exec("schtasks /delete /tn \"{$tn}\" /f 2>NUL", $o, $rc);
        out($rc === 0 ? "OK: Task {$tn} removed." : "SKIP: Task {$tn} not found.");
    }
    exit(0);
}

if (!$install) {
    /* Display only */
    out('');
    out('=== Proposition d\'ordonnancement (Windows Task Scheduler) ===');
    out('');
    out('Executez les commandes suivantes dans un invite de commandes Administrateur :');
    out('');
    foreach ($winJobs as [$tn, $cmd, $st, $sc]) {
        out("  schtasks /create /tn \"{$tn}\" /tr \"{$cmd}\" /sc {$sc} /st {$st} /f");
    }
    out('');
    out('Ou lancez ce script avec --install pour les creer automatiquement :');
    out('');
    out("  {$phpBin} exploitation\\schedule.php --install");
    out('');
    out('Pour supprimer les taches :');
    out('');
    out("  {$phpBin} exploitation\\schedule.php --uninstall");
    out('');
    exit(0);
}

/* Install */
$ok    = 0;
$total = count($winJobs);

foreach ($winJobs as [$tn, $cmd, $st, $sc]) {
    $schtask = "schtasks /create /tn \"{$tn}\" /tr \"{$cmd}\" /sc {$sc} /st {$st} /f";
    exec($schtask, $o, $rc);
    if ($rc === 0) { out("OK: Task {$tn} created ({$sc} {$st})."); $ok++; }
    else { out("ERROR: Could not create task {$tn} (exit code {$rc}). Run as Administrator?"); }
}

exit($ok === $total ? 0 : 1);
