<?php
/**
 * Cron-driven schedule runner. Iterates active scheduled_reports,
 * computes next-due based on cron_expression, and emails matching ones.
 *
 * Add to Windows Task Scheduler (every 1 min):
 *   "C:\xampp\php\php.exe" "C:\Users\Admin\Desktop\Software\medmecs\bin\run-schedules.php"
 *
 * Note: this uses PHP's built-in mail() function. Configure SMTP in
 * php.ini or replace with a PHPMailer call (drop-in if you later add
 * PHPMailer.phar to the includes/ folder).
 */
require_once __DIR__ . '/../includes/config.php';

$pdo = db();
$now = time();

function cron_due(string $cron, int $now): bool
{
    $parts = preg_split('/\s+/', trim($cron));
    if (count($parts) < 5) return false;
    [$min,$hour,$dom,$mon,$dow] = $parts;
    $check = function (string $field, int $value): bool {
        if ($field === '*') return true;
        foreach (explode(',', $field) as $part) {
            if (preg_match('|^\*/(\d+)$|', $part, $m)) {
                if ($value % (int)$m[1] === 0) return true;
            } elseif (preg_match('|^(\d+)-(\d+)$|', $part, $m)) {
                if ($value >= (int)$m[1] && $value <= (int)$m[2]) return true;
            } elseif ((int)$part === $value) return true;
        }
        return false;
    };
    return $check($min, (int) date('i', $now))
        && $check($hour, (int) date('G', $now))
        && $check($dom, (int) date('j', $now))
        && $check($mon, (int) date('n', $now))
        && $check($dow, (int) date('w', $now));
}

$schedules = $pdo->query("SELECT * FROM scheduled_reports WHERE status = 'active'")->fetchAll();

foreach ($schedules as $s) {
    if (!cron_due($s['cron_expression'], $now)) continue;
    // Don't re-fire within the same minute
    if ($s['last_run_at'] && abs(strtotime($s['last_run_at']) - $now) < 60) continue;

    try {
        $report = $pdo->query("SELECT * FROM reports WHERE id = " . (int)$s['report_id'])->fetch();
        $body = strtr($s['body_template'], [
            '{report_name}'  => $report['name'] ?? '',
            '{period}'       => date('Y-m'),
            '{generated_at}' => date('Y-m-d H:i'),
        ]);
        $subject = strtr($s['subject_template'], [
            '{report_name}'  => $report['name'] ?? '',
            '{period}'       => date('Y-m'),
        ]);
        $recipients = json_decode($s['recipients'], true) ?: [];

        // Generate CSV bodies
        // (Phase: simple. Inline CSV; SMTP+attachment requires PHPMailer.)
        foreach ($recipients as $rcpt) {
            mail($rcpt, $subject, $body, 'From: ' . SMTP_FROM_ADDR);
        }
        $pdo->prepare("UPDATE scheduled_reports SET last_run_at=NOW(), last_run_status='success', consecutive_failures=0 WHERE id=?")
            ->execute([$s['id']]);
        echo "[ok] sent " . $s['name'] . " to " . count($recipients) . " recipient(s)\n";
    } catch (Throwable $t) {
        $pdo->prepare("UPDATE scheduled_reports SET last_run_at=NOW(), last_run_status='failed', consecutive_failures = consecutive_failures+1 WHERE id=?")
            ->execute([$s['id']]);
        fwrite(STDERR, "[fail] " . $s['name'] . ": " . $t->getMessage() . "\n");
    }
}
