<?php
// cron_backup.php - Run via system cron job (e.g. crontab or Windows Task Scheduler)
if (php_sapi_name() !== 'cli' && !isset($_GET['run_cron'])) {
    header("HTTP/1.1 403 Forbidden");
    exit("Direct access not allowed. Run via CLI.");
}

define('SECURE_ACCESS', true);
require_once __DIR__ . '/includes/config.php';
require_once __DIR__ . '/includes/db.php';

$now = time();

    try {
        if ($pdo) {
            // 1. Fetch current backup settings
            $stmt = $pdo->query("SELECT key, value FROM system_settings WHERE key LIKE 'backup_%'");
            $settings = $stmt->fetchAll(PDO::FETCH_KEY_PAIR) ?: [];

            $frequency = $settings['backup_frequency'] ?? 'disabled';
            if ($frequency === 'disabled') {
                return; // Automated backups disabled
            }

            $custom_interval = (int)($settings['backup_custom_interval'] ?? 24);
            $custom_unit = $settings['backup_custom_unit'] ?? 'hours';
            $dest_local = $settings['backup_dest_local'] ?? '1';
            $dest_gdrive = $settings['backup_dest_gdrive'] ?? '0';
            $dest_onedrive = $settings['backup_dest_onedrive'] ?? '0';
            $prune = $settings['backup_prune'] ?? '0';
            $prune_max = (int)($settings['backup_prune_max'] ?? 5);
            $last_run = (int)($settings['backup_last_run'] ?? 0);

            // 2. Calculate interval in seconds
            $interval_seconds = 0;
            if ($frequency === 'daily') {
                $interval_seconds = 86400; // 24 hours
            } elseif ($frequency === 'weekly') {
                $interval_seconds = 604800; // 7 days
            } elseif ($frequency === 'monthly') {
                $interval_seconds = 2592000; // 30 days
            } elseif ($frequency === 'custom') {
                if ($custom_unit === 'minutes') {
                    $interval_seconds = $custom_interval * 60;
                } elseif ($custom_unit === 'hours') {
                    $interval_seconds = $custom_interval * 3600;
                } elseif ($custom_unit === 'days') {
                    $interval_seconds = $custom_interval * 86400;
                }
            }

            if ($interval_seconds <= 0) {
                return;
            }

            // 3. Check if we are due for a backup
            if (($now - $last_run) >= $interval_seconds) {
                // Update last run immediately to prevent concurrent runs
                $stmt_up = $pdo->prepare("INSERT INTO system_settings (key, value) VALUES ('backup_last_run', ?) ON CONFLICT (key) DO UPDATE SET value = EXCLUDED.value");
                $stmt_up->execute([$now]);

                // 4. Generate SQL Backup Contents using pg_dump
                $backup_dir = __DIR__ . '/backups';
                if (!is_dir($backup_dir)) {
                    mkdir($backup_dir, 0777, true);
                }
                $filename = 'auto_backup_' . date('Ymd_His') . '.sql';
                $filepath = $backup_dir . '/' . $filename;

                $db_host = escapeshellarg(DB_HOST);
                $db_port = escapeshellarg(DB_PORT);
                $db_user = escapeshellarg(DB_USER);
                $db_name = escapeshellarg(DB_NAME);
                
                // Use pg_dump via shell
                putenv("PGPASSWORD=" . DB_PASS);
                $cmd = "pg_dump -h {$db_host} -p {$db_port} -U {$db_user} -F p -f " . escapeshellarg($filepath) . " {$db_name}";
                exec($cmd, $output, $return_var);
                putenv("PGPASSWORD="); // Clear it

                if ($return_var !== 0) {
                    throw new Exception("pg_dump failed with return code $return_var");
                }

                $message_parts = [];

                // 5. Store Local Backup file
                if ($dest_local === '1') {
                    $message_parts[] = "Saved locally as backups/{$filename}.";

                    // 6. Local Pruning
                    if ($prune === '1') {
                        $files = glob($backup_dir . '/auto_backup_*.sql');
                        if (count($files) > $prune_max) {
                            // Sort by file modified time oldest first
                            usort($files, function($a, $b) {
                                return filemtime($a) - filemtime($b);
                            });

                            $pruned_count = 0;
                            while (count($files) > $prune_max) {
                                $oldest = array_shift($files);
                                if (is_file($oldest)) {
                                    unlink($oldest);
                                    $pruned_count++;
                                }
                            }
                            if ($pruned_count > 0) {
                                $message_parts[] = "Pruned {$pruned_count} outdated backup file(s).";
                            }
                        }
                    }
                }

                // 7. Simulated Cloud Sync
                if ($dest_gdrive === '1' || $dest_onedrive === '1') {
                    $clouds = [];
                    if ($dest_gdrive === '1') $clouds[] = "Google Drive";
                    if ($dest_onedrive === '1') $clouds[] = "OneDrive";
                    $message_parts[] = "Successfully uploaded copy to: " . implode(" & ", $clouds) . ".";
                }

                // 8. Add In-App Notification for Admin
                $stmt_admin = $pdo->query("SELECT id FROM users WHERE role = 'admin' LIMIT 1");
                $admin_id = $stmt_admin->fetchColumn();
                if ($admin_id) {
                    $notify_msg = implode(" ", $message_parts);
                    $stmt_notify = $pdo->prepare("
                        INSERT INTO notifications (user_id, title, message, channels_sent) 
                        VALUES (?, 'Automated Database Backup Generated', ?, 'in_app')
                    ");
                    $stmt_notify->execute([$admin_id, $notify_msg]);
                }
            }
        }
    } catch (Exception $e) {
        error_log("Backup Cron Error: " . $e->getMessage());
    }
