<?php
/**
 * Checklist Instance Generator — runs daily via cron
 *
 * Scheduling windows:
 *   - daily   → 1 month ahead (rolling 30 days)
 *   - weekly  → rest of current calendar month
 *   - monthly → current month only (1 instance)
 *   - once    → single instance on starts_at date
 *
 * Cron: 0 2 * * * php /path/to/site/cron/generate_checklists.php
 */

define('RUNNING_CRON', true);
require_once __DIR__ . '/../api/config/db.php';

$startTime = microtime(true);
$today     = new DateTime();
$todayStr  = $today->format('Y-m-d');

echo "[" . date('Y-m-d H:i:s') . "] Checklist generator starting...\n";

try {
    $db = getDB();

    // ── 1. Mark overdue instances as missed ─────────────────
    $missed = $db->prepare("
        UPDATE checklist_instances SET status = 'missed'
        WHERE status IN ('pending', 'in_progress') AND due_date < ?
    ");
    $missed->execute([$todayStr]);
    echo "[" . date('Y-m-d H:i:s') . "] Marked " . $missed->rowCount() . " overdue as missed.\n";

    // ── 2. Load active recurring templates ──────────────────
    $templates = $db->prepare("
        SELECT * FROM checklist_templates
        WHERE is_active = 1
          AND frequency IN ('daily', 'weekly', 'monthly')
          AND (starts_at IS NULL OR starts_at <= ?)
          AND (ends_at   IS NULL OR ends_at   >= ?)
    ");
    $templates->execute([$todayStr, $todayStr]);
    $allTemplates = $templates->fetchAll();

    echo "[" . date('Y-m-d H:i:s') . "] Processing " . count($allTemplates) . " template(s)...\n";

    $totalCreated = 0;
    $totalSkipped = 0;

    foreach ($allTemplates as $tpl) {
        $templateId = (int)$tpl['id'];
        $assignedTo = $tpl['assigned_to'] ? (int)$tpl['assigned_to'] : 0;
        $vehicleId  = $tpl['fleet_vehicle_id'] ? (int)$tpl['fleet_vehicle_id'] : null;
        $frequency  = $tpl['frequency'];

        // Determine dates to generate
        $datesToGenerate = [];

        if ($frequency === 'daily') {
            // Rolling 1 month ahead
            $window = clone $today;
            $window->modify('+1 month');
            if ($tpl['ends_at'] && new DateTime($tpl['ends_at']) < $window) {
                $window = new DateTime($tpl['ends_at']);
            }
            $cursor = clone $today;
            while ($cursor <= $window) {
                $datesToGenerate[] = $cursor->format('Y-m-d');
                $cursor->modify('+1 day');
            }

        } elseif ($frequency === 'weekly') {
            // All weekly occurrences for the rest of the current calendar month
            // Starting from today's weekday, fill out the month
            $endOfMonth = new DateTime(date('Y-m-t')); // last day of this month
            if ($tpl['ends_at'] && new DateTime($tpl['ends_at']) < $endOfMonth) {
                $endOfMonth = new DateTime($tpl['ends_at']);
            }
            // Find the day-of-week to schedule on (based on starts_at or today)
            $anchorDate = $tpl['starts_at'] ? new DateTime($tpl['starts_at']) : $today;
            $targetDow  = (int)$anchorDate->format('N'); // 1=Mon, 7=Sun

            // Find first occurrence >= today
            $cursor = clone $today;
            $curDow = (int)$cursor->format('N');
            $diff   = ($targetDow - $curDow + 7) % 7;
            if ($diff > 0) $cursor->modify("+{$diff} days");

            while ($cursor <= $endOfMonth) {
                $datesToGenerate[] = $cursor->format('Y-m-d');
                $cursor->modify('+1 week');
            }

        } elseif ($frequency === 'monthly') {
            // Just one instance this month on the correct day
            $anchorDate = $tpl['starts_at'] ? new DateTime($tpl['starts_at']) : $today;
            $targetDay  = (int)$anchorDate->format('j'); // day of month
            $thisMonth  = new DateTime(date('Y-m-') . str_pad($targetDay, 2, '0', STR_PAD_LEFT));
            // If that day has passed this month, don't generate it again
            if ($thisMonth >= $today) {
                $datesToGenerate[] = $thisMonth->format('Y-m-d');
            }
        }

        foreach ($datesToGenerate as $dateStr) {
            $exists = $db->prepare("
                SELECT id FROM checklist_instances WHERE template_id = ? AND due_date = ? LIMIT 1
            ");
            $exists->execute([$templateId, $dateStr]);

            if (!$exists->fetch()) {
                $db->prepare("
                    INSERT INTO checklist_instances (template_id, user_id, vehicle_id, due_date, status)
                    VALUES (?, ?, ?, ?, 'pending')
                ")->execute([$templateId, $assignedTo, $vehicleId, $dateStr]);
                $totalCreated++;
            } else {
                $totalSkipped++;
            }
        }
    }

    // ── 3. One-time templates ────────────────────────────────
    $onceTemplates = $db->prepare("
        SELECT * FROM checklist_templates
        WHERE is_active = 1 AND frequency = 'once'
          AND starts_at IS NOT NULL AND starts_at >= ?
          AND id NOT IN (SELECT DISTINCT template_id FROM checklist_instances)
    ");
    $onceTemplates->execute([$todayStr]);
    foreach ($onceTemplates->fetchAll() as $tpl) {
        $db->prepare("
            INSERT INTO checklist_instances (template_id, user_id, vehicle_id, due_date, status)
            VALUES (?, ?, ?, ?, 'pending')
        ")->execute([
            $tpl['id'], $tpl['assigned_to'] ?: 0,
            $tpl['fleet_vehicle_id'] ?: null, $tpl['starts_at'],
        ]);
        $totalCreated++;
    }

    $elapsed = round(microtime(true) - $startTime, 2);
    echo "[" . date('Y-m-d H:i:s') . "] Done in {$elapsed}s — Created: $totalCreated, Skipped: $totalSkipped\n";

} catch (Exception $e) {
    echo "[" . date('Y-m-d H:i:s') . "] FATAL ERROR: " . $e->getMessage() . "\n";
    if (defined("RUNNING_AS_INCLUDE")) throw new CronExitException(1); else exit(1);
}