<?php
// Filename: admin_system.php
// UPDATED: Added Folder Exclusion Logic to Backup

require 'config.php';
requireLogin();

// =================================================================================
// --- START 2FA PROTECTION BLOCK ---
// =================================================================================
$user_id = $_SESSION['user_id'];

$stmt_s = $pdo->prepare("SELECT setting_key, setting_value FROM system_settings WHERE setting_key IN ('security_2fa_enabled', 'security_2fa_system_page')");
$stmt_s->execute();
$sec_settings = $stmt_s->fetchAll(PDO::FETCH_KEY_PAIR);

$is_global_on = isset($sec_settings['security_2fa_enabled']) && $sec_settings['security_2fa_enabled'] === '1';
$is_page_on   = isset($sec_settings['security_2fa_system_page']) && $sec_settings['security_2fa_system_page'] === '1';

if ($is_global_on && $is_page_on) {
    if (empty($_SESSION['sys_2fa_verified'])) {
        $stmt = $pdo->prepare("SELECT telegram_chat_id FROM users WHERE id = ?");
        $stmt->execute([$user_id]);
        $chat_id = $stmt->fetchColumn();

        if (!empty($chat_id)) {
            $error = '';
            if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['verify_otp'])) {
                $user_otp = trim($_POST['otp_code'] ?? '');
                if ($user_otp !== '' && $user_otp === ($_SESSION['sys_2fa_code'] ?? '') && (time() - ($_SESSION['sys_2fa_time'] ?? 0) < 300)) {
                    $_SESSION['sys_2fa_verified'] = true;
                    unset($_SESSION['sys_2fa_code'], $_SESSION['sys_2fa_time']);
                    header("Location: admin_system.php"); 
                    exit;
                } else { 
                    $error = "Invalid or expired code."; 
                }
            }

            if (empty($_SESSION['sys_2fa_time']) || (time() - $_SESSION['sys_2fa_time'] > 60)) {
                $otp = rand(100000, 999999);
                $_SESSION['sys_2fa_code'] = strval($otp);
                $_SESSION['sys_2fa_time'] = time();
                $otpm = "?? <b>System Access Verification</b>\n\nCode: <code>$otp</code>\n\nValid for 5 minutes.";
                if (function_exists('sendTelegram')) sendTelegram($otpm, $chat_id, 'otp');
            }
            ?>
            <!DOCTYPE html>
            <html lang="en">
            <head>
                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
                <title>System Verify</title>
                <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
                <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
                <style>
                    :root { --danger-grad: linear-gradient(135deg, #ef4444 0%, #b91c1c 100%); }
                    body { background: #f8f9fd; height: 100dvh; display: flex; align-items: center; justify-content: center; font-family: sans-serif; margin: 0; }
                    .card { border: none; border-radius: 30px; padding: 40px 25px; box-shadow: 0 20px 40px rgba(0,0,0,0.08); max-width: 380px; width: 100%; text-align: center; }
                    .otp-container { display: flex; gap: 8px; justify-content: center; margin: 25px 0; }
                    .otp-digit { width: 45px; height: 55px; border: 2px solid #e2e8f0; border-radius: 12px; text-align: center; font-size: 1.5rem; font-weight: 700; background: #f8fafc; transition: all 0.2s; }
                    .otp-digit:focus { border-color: #ef4444; background: white; outline: none; box-shadow: 0 0 0 4px rgba(239, 68, 68, 0.1); }
                    .btn-unlock { background: var(--danger-grad); border: none; padding: 14px; border-radius: 16px; color: white; font-weight: 700; width: 100%; box-shadow: 0 10px 20px rgba(220, 38, 38, 0.2); }
                </style>
            </head>
            <body>
                <div class="card mx-3">
                    <div class="mb-3 text-danger"><i class="bi bi-cpu-fill display-1"></i></div>
                    <h4 class="fw-bold">System Lock</h4>
                    <p class="text-muted small">Enter the 6-digit code sent to your Telegram to unlock System Tools.</p>
                    <?php if($error): ?><div class="alert alert-danger py-2 small border-0 mb-3"><?= $error ?></div><?php endif; ?>
                    <form method="POST" id="otpForm">
                        <input type="hidden" name="otp_code" id="final_otp">
                        <div class="otp-container">
                            <?php for($i=0; $i<6; $i++): ?>
                            <input type="tel" maxlength="1" class="otp-digit" inputmode="numeric" pattern="[0-9]*" <?= ($i===0)?'autofocus':'' ?>>
                            <?php endfor; ?>
                        </div>
                        <button type="submit" name="verify_otp" class="btn-unlock">Unlock System</button>
                    </form>
                    <div class="mt-4 small text-muted">Didn't get a code? <a href="admin_system.php" class="text-danger fw-bold text-decoration-none">Resend</a></div>
                </div>
                <script>
                    const inputs = document.querySelectorAll('.otp-digit');
                    const finalInput = document.getElementById('final_otp');
                    inputs.forEach((input, index) => {
                        input.addEventListener('input', (e) => {
                            if (e.target.value.length > 1) e.target.value = e.target.value.slice(0, 1);
                            if (e.target.value !== "" && index < inputs.length - 1) inputs[index + 1].focus();
                            updateFinal();
                        });
                        input.addEventListener('keydown', (e) => {
                            if (e.key === 'Backspace' && e.target.value === "" && index > 0) inputs[index - 1].focus();
                        });
                    });
                    function updateFinal() {
                        let val = "";
                        inputs.forEach(i => val += i.value);
                        finalInput.value = val;
                    }
                </script>
            </body>
            </html>
            <?php 
            exit;
        }
    }
}
// =================================================================================
// --- END 2FA PROTECTION BLOCK ---
// =================================================================================

if (!function_exists('csrfToken')) {
    function csrfToken(): string {
        if (empty($_SESSION['csrf_token'])) {
            $_SESSION['csrf_token'] = bin2hex(random_bytes(32));
        }
        return $_SESSION['csrf_token'];
    }
}

if (!function_exists('requireCsrf')) {
    function requireCsrf(): void {
        if ($_SERVER['REQUEST_METHOD'] !== 'POST') return;
        $token = $_POST['csrf_token'] ?? '';
        if (!is_string($token) || empty($_SESSION['csrf_token']) || !hash_equals($_SESSION['csrf_token'], $token)) {
            http_response_code(403);
            die("Security Error: CSRF Token Validation Failed.");
        }
    }
}
$csrf = csrfToken();

$allowed_roles = ['admin', 'timetable_coord', 'principal', 'assistant'];
if (function_exists('hasRole')) {
    if (!hasRole($allowed_roles)) { header("Location: dashboard.php"); exit; }
} else {
    $user_roles = explode(',', $_SESSION['role'] ?? '');
    if (empty(array_intersect($user_roles, $allowed_roles))) { header("Location: dashboard.php"); exit; }
}

ini_set('memory_limit', '1024M'); 
ini_set('max_execution_time', 600); 
$msg = ''; $msg_type = '';

function formatBytes($bytes, $precision = 2) {
    $units = ['B', 'KB', 'MB', 'GB', 'TB'];
    $bytes = max($bytes, 0);
    $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
    $pow = min($pow, count($units) - 1);
    return round($bytes / pow(1024, $pow), $precision) . ' ' . $units[$pow];
}

function rrmdir($dir) {
    if (is_dir($dir)) {
        $objects = scandir($dir);
        foreach ($objects as $object) {
            if ($object != "." && $object != "..") {
                $path = $dir . DIRECTORY_SEPARATOR . $object;
                if (is_dir($path) && !is_link($path)) rrmdir($path);
                else @unlink($path);
            }
        }
    }
}

function safeClearCacheDir($dir) {
    $real = realpath($dir);
    $base = realpath(__DIR__);
    if ($real && $base && strpos($real, $base) === 0 && basename($real) === 'cache') {
        rrmdir($real);
    }
}

$directories = ['uploads', 'uploads/avatars', 'uploads/mc', 'cache'];

// --- 4. ACTIONS ---
if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {

    requireCsrf();

    // A. BACKUP DB
    if ($_POST['action'] === 'backup') {
        session_write_close();
        
        $mode = $_POST['mode'] ?? 'full';
        if ($mode === 'full') {
            $tables = $pdo->query("SHOW TABLES")->fetchAll(PDO::FETCH_COLUMN);
        } elseif ($mode === 'booking_users') {
            $tables = ['bookings', 'rooms', 'facilities', 'room_facilities', 'users'];
            $existing_tables = $pdo->query("SHOW TABLES")->fetchAll(PDO::FETCH_COLUMN);
            $tables = array_intersect($tables, $existing_tables);
        } else {
            $tables = $_POST['tables'] ?? [];
        }

        if (empty($tables)) {
            $msg = "Please select at least one table."; $msg_type = "warning";
        } else {
            while (ob_get_level()) ob_end_clean();
            header('Content-Type: application/octet-stream');
            header('Content-Transfer-Encoding: Binary');
            header('Content-Disposition: attachment; filename=sas_'.$mode.'_' . date('Y-m-d_H-i') . '.sql');

            echo "-- SAS System Backup (Mode: $mode)\n-- Generated: " . date('Y-m-d H:i:s') . "\n\n";
            echo "SET SQL_MODE = \"NO_AUTO_VALUE_ON_ZERO\";\nSTART TRANSACTION;\nSET time_zone = \"+00:00\";\n\n";
            echo "SET FOREIGN_KEY_CHECKS=0;\n\n";

            foreach ($tables as $t) {
                if (!preg_match('/^[a-zA-Z0-9_]+$/', $t)) continue;
                $row = $pdo->query("SHOW CREATE TABLE `$t`")->fetch(PDO::FETCH_NUM);
                echo "DROP TABLE IF EXISTS `$t`;\n" . $row[1] . ";\n\n";
                $stmt = $pdo->query("SELECT * FROM `$t`");
                $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);

                if (count($rows) > 0) {
                    echo "INSERT INTO `$t` VALUES\n";
                    $count = 0; $total = count($rows);
                    foreach ($rows as $r) {
                        $vals = array_map(function ($v) use ($pdo) {
                            if ($v === null) return "NULL";
                            return $pdo->quote((string)$v);
                        }, $r);
                        echo "(" . implode(',', $vals) . ")";
                        $count++;
                        echo ($count < $total) ? ",\n" : ";\n\n";
                    }
                }
            }
            echo "SET FOREIGN_KEY_CHECKS=1;\nCOMMIT;\n";
            exit;
        }
    }

    // B. ZIP AND DOWNLOAD FILES (WITH EXCLUSIONS)
    if ($_POST['action'] === 'backup_files') {
        session_write_close();
        $zipFile = 'site_backup_' . date('Y-m-d_H-i') . '.zip';
        $zip = new ZipArchive();
        
        $rootPath = realpath('/home/attendance/public_html');
        
        // --- CONFIG: FOLDERS TO EXCLUDE ---
        $excluded_folders = ['cache', '.git', 'node_modules', 'tmp', 'error_log']; 
        
        if (!$rootPath || !is_dir($rootPath)) {
            $msg = "Error: Root path /home/attendance/public_html not found."; $msg_type = "danger";
        } elseif ($zip->open($zipFile, ZipArchive::CREATE | ZipArchive::OVERWRITE) === TRUE) {
            
            $files = new RecursiveIteratorIterator(
                new RecursiveDirectoryIterator($rootPath, RecursiveDirectoryIterator::SKIP_DOTS),
                RecursiveIteratorIterator::LEAVES_ONLY
            );

            foreach ($files as $name => $file) {
                if (!$file->isDir()) {
                    $filePath = $file->getRealPath();
                    $relativePath = substr($filePath, strlen($rootPath) + 1);

                    // Skip the zip file itself
                    if (basename($filePath) == $zipFile) continue;
                    
                    // Skip error log file specifically
                    if (basename($filePath) == 'error_log') continue;

                    // CHECK FOLDER EXCLUSIONS
                    // Explode path to check if any parent folder matches exclusion list
                    $path_parts = explode(DIRECTORY_SEPARATOR, dirname($relativePath));
                    if (array_intersect($path_parts, $excluded_folders)) {
                        continue; // Skip this file
                    }

                    $zip->addFile($filePath, $relativePath);
                }
            }
            $zip->close();

            if (file_exists($zipFile)) {
                while (ob_get_level()) ob_end_clean();
                header('Content-Type: application/zip');
                header('Content-Disposition: attachment; filename="'.basename($zipFile).'"');
                header('Content-Length: ' . filesize($zipFile));
                readfile($zipFile);
                unlink($zipFile); // Remove server copy
                exit;
            } else {
                $msg = "Failed to generate zip file."; $msg_type = "danger";
            }
        } else {
            $msg = "Could not create zip archive."; $msg_type = "danger";
        }
    }

    // C. INTEGRITY SCAN
    if ($_POST['action'] === 'scan_integrity') {
        $issues = [];
        $checks = [
            ['type' => 'student_att', 'sql' => "SELECT COUNT(*) FROM student_attendance sa LEFT JOIN students s ON sa.student_id = s.id WHERE s.id IS NULL", 'label' => 'Orphaned Attendance Records'],
            ['type' => 'teacher_logs', 'sql' => "SELECT COUNT(*) FROM attendance_logs al LEFT JOIN users u ON al.user_id = u.id WHERE u.id IS NULL", 'label' => 'Orphaned Teacher Logs'],
            ['type' => 'discipline', 'sql' => "SELECT COUNT(*) FROM student_discipline sd LEFT JOIN students s ON sd.student_id = s.id WHERE s.id IS NULL", 'label' => 'Orphaned Discipline Cases']
        ];
        foreach($checks as $check) {
            $count = $pdo->query($check['sql'])->fetchColumn();
            if ($count > 0) $issues[] = ['type' => $check['type'], 'label' => $check['label'], 'count' => (int)$count, 'fix' => true];
        }
        header('Content-Type: application/json');
        echo json_encode(['success' => true, 'issues' => $issues]);
        exit;
    }

    // D. FIX INTEGRITY
    if ($_POST['action'] === 'fix_integrity') {
        $target = $_POST['target'] ?? '';
        try {
            if ($target === 'student_att') $pdo->exec("DELETE sa FROM student_attendance sa LEFT JOIN students s ON sa.student_id = s.id WHERE s.id IS NULL");
            elseif ($target === 'teacher_logs') $pdo->exec("DELETE al FROM attendance_logs al LEFT JOIN users u ON al.user_id = u.id WHERE u.id IS NULL");
            elseif ($target === 'discipline') $pdo->exec("DELETE sd FROM student_discipline sd LEFT JOIN students s ON sd.student_id = s.id WHERE s.id IS NULL");
            echo json_encode(['success' => true]);
        } catch (Exception $e) {
            echo json_encode(['success' => false, 'message' => $e->getMessage()]);
        }
        exit;
    }

    // E. CLEAR CACHE
    if ($_POST['action'] === 'clear_cache') {
        safeClearCacheDir('cache');
        $msg = "System cache cleared successfully."; $msg_type = "success";
    }

    // F. OPTIMIZE TABLES
    if ($_POST['action'] === 'optimize_tables') {
        try {
            $tables = $pdo->query("SHOW TABLES")->fetchAll(PDO::FETCH_COLUMN);
            foreach ($tables as $table) {
                if (preg_match('/^[a-zA-Z0-9_]+$/', $table)) {
                    $pdo->query("OPTIMIZE TABLE `$table`");
                }
            }
            $msg = "Database tables optimized and defragmented."; $msg_type = "success";
        } catch (Exception $e) {
            $msg = "Optimization Error: " . $e->getMessage(); $msg_type = "danger";
        }
    }

    // G. CHECK INDEXES
    if ($_POST['action'] === 'check_indexes') {
        $required = [
            'student_attendance' => ['idx_sa_student' => 'student_id', 'idx_sa_date' => 'date'],
            'attendance_logs' => ['idx_al_user' => 'user_id', 'idx_al_scan' => 'scan_time'],
            'student_discipline' => ['idx_sd_student' => 'student_id']
        ];
        $missing = [];
        foreach ($required as $table => $indexes) {
            try {
                $stmt = $pdo->query("SHOW INDEX FROM `$table`");
                $existing_keys = array_column($stmt->fetchAll(PDO::FETCH_ASSOC), 'Key_name');
                $stmt_cols = $pdo->query("SHOW COLUMNS FROM `$table`");
                $existing_cols = array_column($stmt_cols->fetchAll(PDO::FETCH_ASSOC), 'Field');

                foreach ($indexes as $keyName => $colName) {
                    if (in_array($colName, $existing_cols) && !in_array($keyName, $existing_keys, true)) {
                        $missing[] = ['table' => $table, 'key' => $keyName, 'col' => $colName];
                    }
                }
            } catch (Exception $e) { continue; }
        }
        header('Content-Type: application/json');
        echo json_encode(['success' => true, 'missing' => $missing]);
        exit;
    }

    // H. ADD INDEX
    if ($_POST['action'] === 'add_index') {
        $table = $_POST['table'] ?? ''; $key = $_POST['key'] ?? ''; $col = $_POST['col'] ?? '';
        try {
            if (preg_match('/^[a-zA-Z0-9_]+$/', $table) && preg_match('/^[a-zA-Z0-9_]+$/', $key) && preg_match('/^[a-zA-Z0-9_]+$/', $col)) {
                $pdo->exec("ALTER TABLE `$table` ADD INDEX `$key` (`$col`)");
                echo json_encode(['success' => true]);
            } else { throw new Exception("Invalid parameters"); }
        } catch (Exception $e) { echo json_encode(['success' => false, 'message' => $e->getMessage()]); }
        exit;
    }

    // I. RESTORE
    if ($_POST['action'] === 'import' && isset($_FILES['sql_file'])) {
        $isAdmin = function_exists('hasRole') ? hasRole('admin') : in_array('admin', explode(',', $_SESSION['role'] ?? ''));
        
        if (!$isAdmin) {
            $msg = "Only admin can restore backups."; $msg_type = "danger";
        } elseif (($_POST['confirm_restore'] ?? '') !== 'RESTORE') {
            $msg = "Type RESTORE to confirm database restore."; $msg_type = "warning";
        } else {
            $tmp = $_FILES['sql_file']['tmp_name'] ?? '';
            $name = $_FILES['sql_file']['name'] ?? '';
            $size = (int)($_FILES['sql_file']['size'] ?? 0);

            if (!$tmp || !is_uploaded_file($tmp)) {
                $msg = "Invalid upload."; $msg_type = "danger";
            } elseif ($size <= 0 || $size > 50 * 1024 * 1024) { 
                $msg = "SQL file too large (max 50MB)."; $msg_type = "danger";
            } elseif (!preg_match('/\.sql$/i', $name)) {
                $msg = "Only .sql files are allowed."; $msg_type = "danger";
            } else {
                ini_set('memory_limit', '512M'); set_time_limit(0);
                $pdo->exec("SET FOREIGN_KEY_CHECKS=0");
                $handle = fopen($tmp, "r");
                if ($handle) {
                    $query = '';
                    try {
                        while (($line = fgets($handle)) !== false) {
                            $trimLine = trim($line);
                            if ($trimLine === '' || str_starts_with($trimLine, '--') || str_starts_with($trimLine, '/*')) continue;
                            if (stripos($trimLine, 'DELIMITER ') === 0) throw new Exception("Unsupported SQL.");
                            $query .= $line;
                            if (substr(rtrim($trimLine), -1) === ';') { $pdo->exec($query); $query = ''; }
                        }
                        $msg = "Import successful."; $msg_type = "success";
                    } catch (Exception $e) { $msg = "Import Error: " . $e->getMessage(); $msg_type = "danger"; }
                    fclose($handle);
                }
                $pdo->exec("SET FOREIGN_KEY_CHECKS=1");
            }
        }
    }

    // J. RESET
    if ($_POST['action'] === 'reset' && ($_POST['confirm_code'] ?? '') === 'DELETE') {
        $pdo->exec("SET FOREIGN_KEY_CHECKS=0");
        $t = $_POST['targets'] ?? [];
        try {
            if (in_array('data', $t, true)) foreach (['attendance_logs','teacher_absences','relief_assignments','student_attendance','student_discipline','announcements','announcement_recipients','notifications','timetable_requests'] as $tbl) $pdo->exec("TRUNCATE $tbl");
            if (in_array('structure', $t, true)) foreach (['timetable','classes','subjects','students','class_transfer_requests'] as $tbl) $pdo->exec("TRUNCATE $tbl");
            if (in_array('users', $t, true)) { $stmt = $pdo->prepare("DELETE FROM users WHERE id != ?"); $stmt->execute([$_SESSION['user_id']]); }
            if (in_array('bookings', $t, true)) foreach (['bookings', 'room_facilities'] as $tbl) $pdo->exec("TRUNCATE $tbl");
            $msg = "System reset complete."; $msg_type = "success";
        } catch (Exception $e) { $msg = "Error: " . $e->getMessage(); $msg_type = "danger"; }
        $pdo->exec("SET FOREIGN_KEY_CHECKS=1");
    }

    // K. RESET BOOKINGS ONLY
    if ($_POST['action'] === 'reset_bookings') {
        try {
            $pdo->exec("SET FOREIGN_KEY_CHECKS=0");
            $pdo->exec("TRUNCATE bookings");
            $pdo->exec("SET FOREIGN_KEY_CHECKS=1");
            $msg = "Booking history cleared successfully."; $msg_type = "success";
        } catch (Exception $e) {
            $msg = "Error: " . $e->getMessage(); $msg_type = "danger";
        }
    }

    // L. FIX DIRECTORIES
    if ($_POST['action'] === 'fix_directories') {
        $results = [];
        foreach ($directories as $dir) {
            $status = "OK";
            if (!is_dir($dir)) {
                if (!@mkdir($dir, 0777, true)) $status = "Failed to create";
                else $status = "Created";
            }
            if (is_dir($dir) && !is_writable($dir)) {
                if (!@chmod($dir, 0777)) $status = "Failed to chmod";
                else $status = "Permissions fixed";
            }
            if ($status !== "OK") $results[] = "$dir: $status";
        }
        if (empty($results)) {
            $msg = "All directories are present and writable."; $msg_type = "success";
        } else {
            $msg = "Fix report: " . implode(", ", $results);
            $msg_type = strpos($msg, 'Failed') !== false ? "warning" : "success";
        }
    }

    // F. LIST UPDATE BACKUPS
    if ($_POST['action'] === 'list_update_backups') {
        $backups = [];
        if (is_dir('backups')) {
            $files = glob('backups/backup_*.zip');
            foreach ($files as $file) {
                $backups[] = [
                    'filename' => basename($file),
                    'filepath' => $file,
                    'size' => filesize($file),
                    'size_mb' => round(filesize($file) / 1048576, 2),
                    'created' => date('Y-m-d H:i:s', filemtime($file)),
                    'timestamp' => filemtime($file),
                    'age_days' => round((time() - filemtime($file)) / 86400, 1)
                ];
            }
            usort($backups, function($a, $b) {
                return $b['timestamp'] - $a['timestamp'];
            });
        }
        header('Content-Type: application/json');
        echo json_encode(['success' => true, 'backups' => $backups]);
        exit;
    }

    // G. RESTORE UPDATE BACKUP
    if ($_POST['action'] === 'restore_backup') {
        $backupFile = basename($_POST['backup_file'] ?? '');
        $backupPath = 'backups/' . $backupFile;
        
        if (!file_exists($backupPath)) {
            header('Content-Type: application/json');
            echo json_encode(['success' => false, 'message' => 'Backup file not found']);
            exit;
        }
        
        try {
            // Create pre-restore backup
            $preRestoreBackup = 'backups/pre_restore_' . date('Ymd_His') . '.zip';
            $zip = new ZipArchive;
            if ($zip->open($preRestoreBackup, ZipArchive::CREATE) === TRUE) {
                $criticalFiles = ['admin_settings.php', 'dashboard.php', 'check_updates.php', 'perform_update.php', 'index.php'];
                foreach ($criticalFiles as $file) {
                    if (file_exists($file)) {
                        $zip->addFile($file, $file);
                    }
                }
                $zip->close();
            }
            
            // Extract backup
            $extractZip = new ZipArchive;
            if ($extractZip->open($backupPath) === TRUE) {
                $extractZip->extractTo('.');
                $extractZip->close();
                
                header('Content-Type: application/json');
                echo json_encode([
                    'success' => true, 
                    'message' => 'Backup restored successfully',
                    'pre_restore_backup' => basename($preRestoreBackup)
                ]);
                exit;
            } else {
                throw new Exception('Failed to open backup ZIP file');
            }
        } catch (Exception $e) {
            header('Content-Type: application/json');
            echo json_encode(['success' => false, 'message' => $e->getMessage()]);
            exit;
        }
    }

    // H. DELETE UPDATE BACKUP
    if ($_POST['action'] === 'delete_backup') {
        $backupFile = basename($_POST['backup_file'] ?? '');
        $backupPath = 'backups/' . $backupFile;
        
        if (file_exists($backupPath)) {
            if (unlink($backupPath)) {
                header('Content-Type: application/json');
                echo json_encode(['success' => true, 'message' => 'Backup deleted']);
                exit;
            }
        }
        
        header('Content-Type: application/json');
        echo json_encode(['success' => false, 'message' => 'Failed to delete backup']);
        exit;
    }

    // I. CLEANUP OLD UPDATE BACKUPS
    if ($_POST['action'] === 'cleanup_old_backups') {
        $daysToKeep = intval($_POST['days_to_keep'] ?? 30);
        $cutoffTime = time() - ($daysToKeep * 86400);
        $deleted = 0;
        
        if (is_dir('backups')) {
            $files = glob('backups/backup_*.zip');
            foreach ($files as $file) {
                if (filemtime($file) < $cutoffTime) {
                    if (unlink($file)) {
                        $deleted++;
                    }
                }
            }
        }
        
        header('Content-Type: application/json');
        echo json_encode(['success' => true, 'deleted' => $deleted, 'message' => "Deleted $deleted old backups"]);
        exit;
    }
}

// --- STATS ---
$db_stats = $pdo->query("SHOW TABLE STATUS")->fetchAll(PDO::FETCH_ASSOC);
$db_size = 0; $db_rows = 0;
foreach ($db_stats as $tbl) { $db_size += ($tbl['Data_length'] ?? 0) + ($tbl['Index_length'] ?? 0); $db_rows += ($tbl['Rows'] ?? 0); }

$disk_total = function_exists('disk_total_space') ? disk_total_space(".") : 0;
$disk_free  = function_exists('disk_free_space')  ? disk_free_space(".")  : 0;
$disk_used  = $disk_total - $disk_free;
$all_php_files = glob("*.php"); $file_count = count($all_php_files);
?>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
    <title>System Maintenance</title>
    <link href="https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600;700&display=swap" rel="stylesheet">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.1/font/bootstrap-icons.css">
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css">
    <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
    <style>
        :root { --primary-grad: <?= getHeaderTheme() ?>; --bg-color: #f8f9fd; --text-dark: #1e293b; --text-gray: #64748b; }
        body { font-family: 'Plus Jakarta Sans', sans-serif; background-color: var(--bg-color); padding-bottom: 90px; }
        .app-header { background: var(--primary-grad); padding: 30px 20px 80px 20px; border-radius: 0 0 35px 35px; color: white; text-align: center; }
        .floating-card { background: white; margin: -60px 20px 20px 20px; border-radius: 24px; padding: 20px; box-shadow: 0 15px 35px rgba(0,0,0,0.08); position: relative; z-index: 10; }
        .nav-pills { background: #f1f5f9; padding: 4px; border-radius: 12px; display: flex; width: 100%; margin-bottom: 20px; }
        .nav-pills .nav-link { flex: 1; border-radius: 10px; color: var(--text-gray); font-weight: 700; padding: 10px 0; border: none; font-size: 0.8rem; transition: 0.2s; background: transparent; text-align: center; }
        .nav-pills .nav-link.active { background: white; color: #8B5CF6; box-shadow: 0 2px 5px rgba(0,0,0,0.05); }
        .stat-card { background: #f8fafc; border-radius: 16px; padding: 15px; text-align: center; border: 1px solid #f1f5f9; height: 100%; }
        .stat-card h3 { font-weight: 800; margin: 0; color: var(--text-dark); font-size: 1.4rem; }
        .stat-card small { font-weight: 700; font-size: 0.65rem; text-transform: uppercase; color: var(--text-gray); letter-spacing: 0.5px; }
        .file-item { display: flex; justify-content: space-between; align-items: center; padding: 10px 0; border-bottom: 1px solid #f1f5f9; }
        .action-box { border-radius: 16px; padding: 20px; margin-bottom: 20px; border: 1px solid #f1f5f9; background: #fff; }
        .box-title { font-weight: 800; font-size: 1rem; margin-bottom: 10px; display: flex; align-items: center; }
    </style>
</head>
<body>
    <div class="app-header">
        <div class="d-flex justify-content-between align-items-center mb-3">
            <a href="admin_dashboard.php" class="text-white"><i class="bi bi-arrow-left fs-4"></i></a>
            <div class="fw-bold fs-5">System</div>
            <div style="width: 24px;"></div>
        </div>
        <div class="opacity-75 small">Maintenance & Security</div>
    </div>

    <div class="floating-card">
        <?php if($msg): ?><div class="alert alert-<?= $msg_type ?> border-0 shadow-sm rounded-3 text-center small mb-4 fw-bold"><?= $msg ?></div><?php endif; ?>

        <div class="nav nav-pills" id="sysTabs" role="tablist">
            <button class="nav-link active" data-bs-toggle="tab" data-bs-target="#overview">Overview</button>
            <button class="nav-link" data-bs-toggle="tab" data-bs-target="#tools">Tools</button>
            <button class="nav-link text-danger" data-bs-toggle="tab" data-bs-target="#danger">Reset</button>
        </div>

        <div class="tab-content">
            <div class="tab-pane fade show active" id="overview">
                <div class="row g-2 mb-4">
                    <div class="col-6">
                        <form method="POST" class="mb-2">
                            <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($csrf) ?>">
                            <input type="hidden" name="action" value="backup"><input type="hidden" name="mode" value="full">
                            <button class="btn btn-success w-100 rounded-pill fw-bold shadow-sm py-3 small"><i class="bi bi-database-down me-2 fs-5"></i><br>DB Backup</button>
                        </form>
                    </div>
                    <div class="col-6">
                        <form method="POST" class="mb-2">
                            <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($csrf) ?>">
                            <input type="hidden" name="action" value="backup_files">
                            <button class="btn btn-primary w-100 rounded-pill fw-bold shadow-sm py-3 small"><i class="bi bi-file-earmark-zip me-2 fs-5"></i><br>Source Code</button>
                        </form>
                    </div>
                </div>

                <div class="row g-2 mb-4">
                    <div class="col-6"><div class="stat-card"><h3><?= formatBytes($db_size) ?></h3><small>DB Size</small></div></div>
                    <div class="col-6"><div class="stat-card"><h3 class="text-primary"><?= $db_rows ?></h3><small>Records</small></div></div>
                </div>

                <div class="action-box">
                    <div class="box-title text-dark"><i class="bi bi-hdd-fill me-2 text-secondary"></i> Storage Usage</div>
                    <div class="d-flex align-items-center justify-content-center py-2">
                        <div style="width: 100px; height: 100px;"><canvas id="diskChart"></canvas></div>
                        <div class="ms-4">
                            <div class="small fw-bold text-muted text-uppercase">Free Space</div>
                            <div class="h4 text-success fw-bold mb-0"><?= formatBytes($disk_free) ?></div>
                        </div>
                    </div>
                </div>
                
                <div class="action-box">
                    <div class="d-flex justify-content-between align-items-center mb-2">
                        <div class="box-title text-dark m-0">System Check</div>
                        <form method="POST">
                            <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($csrf) ?>">
                            <input type="hidden" name="action" value="fix_directories">
                            <button class="btn btn-sm btn-outline-primary rounded-pill fw-bold"><i class="bi bi-magic me-1"></i> Auto-Fix</button>
                        </form>
                    </div>
                    <?php foreach($directories as $dir): $ex = is_dir($dir); $wr = is_writable($dir); ?>
                    <div class="file-item">
                        <div class="d-flex align-items-center"><i class="bi bi-folder-fill text-warning me-2 fs-5"></i><span class="fw-bold text-dark small"><?= $dir ?></span></div>
                        <?= ($ex && $wr) ? '<span class="badge bg-success rounded-pill">OK</span>' : '<span class="badge bg-danger rounded-pill">Error</span>' ?>
                    </div>
                    <?php endforeach; ?>
                </div>
            </div>

            <div class="tab-pane fade" id="tools">
                <div class="action-box border-primary bg-primary bg-opacity-10">
                    <div class="box-title text-primary"><i class="bi bi-lightning-charge-fill me-2"></i>Index Optimization</div>
                    <p class="small text-muted mb-3">Scan and generate database indexes to speed up queries.</p>
                    <button class="btn btn-primary w-100 rounded-pill fw-bold btn-sm shadow-sm mb-2" onclick="runIndexScan()" id="indexBtn">Scan Missing Indexes</button>
                    <div id="indexResults" class="mt-3" style="display:none;"></div>
                </div>

                <div class="action-box border-success bg-success bg-opacity-10">
                    <div class="box-title text-success"><i class="bi bi-calendar-check-fill me-2"></i>Booking & User Export</div>
                    <p class="small text-muted mb-3">Backup only Rooms, Facilities, Bookings, and User tables.</p>
                    <form method="POST">
                        <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($csrf) ?>">
                        <input type="hidden" name="action" value="backup">
                        <input type="hidden" name="mode" value="booking_users">
                        <button class="btn btn-success w-100 rounded-pill fw-bold btn-sm shadow-sm">Export Booking Data</button>
                    </form>
                </div>

                <div class="action-box border-info border-opacity-25 bg-info bg-opacity-10">
                    <div class="box-title text-info"><i class="bi bi-bandaid-fill me-2"></i>Data Doctor</div>
                    <button class="btn btn-info w-100 rounded-pill fw-bold btn-sm text-white" onclick="runIntegrityScan()" id="scanBtn">Scan Records</button>
                    <div id="scanResults" class="mt-3" style="display:none;"></div>
                </div>

                <div class="action-box border-warning border-opacity-25">
                    <div class="box-title text-dark"><i class="bi bi-stars me-2 text-warning"></i>Cache Management</div>
                    <form method="POST">
                        <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($csrf) ?>">
                        <input type="hidden" name="action" value="clear_cache">
                        <button class="btn btn-warning w-100 rounded-pill fw-bold btn-sm text-dark">Clear All Cache</button>
                    </form>
                </div>

                <div class="action-box border-danger border-opacity-25 bg-danger bg-opacity-10">
                    <div class="box-title text-danger"><i class="bi bi-calendar-x-fill me-2"></i>Reset Booking Data</div>
                    <p class="small text-muted mb-3">Clear all booking history. Rooms and Facilities will NOT be deleted.</p>
                    <form method="POST" onsubmit="return confirm('Are you sure? This will delete ALL booking records.');">
                        <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($csrf) ?>">
                        <input type="hidden" name="action" value="reset_bookings">
                        <button class="btn btn-danger w-100 rounded-pill fw-bold btn-sm shadow-sm">Clear Booking History</button>
                    </form>
                </div>

                <div class="action-box border-primary border-opacity-25">
                    <div class="box-title text-primary"><i class="bi bi-box-arrow-in-down me-2"></i>Import SQL File</div>
                    <form method="POST" enctype="multipart/form-data">
                        <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($csrf) ?>">
                        <input type="hidden" name="action" value="import">
                        <input type="file" name="sql_file" class="form-control form-control-sm mb-2" accept=".sql" required>
                        <input type="text" name="confirm_restore" class="form-control form-control-sm mb-2" placeholder="Type RESTORE to confirm" required>
                        <button class="btn btn-primary w-100 rounded-pill fw-bold btn-sm">Start Restore</button>
                    </form>
                </div>

                <!-- Update Backups Manager -->
                <div class="action-box border-secondary border-opacity-25">
                    <div class="box-title text-dark"><i class="bi bi-archive-fill me-2 text-secondary"></i>Update Backups</div>
                    <p class="small text-muted mb-3">Manage backups created by the update system. Restore previous versions or clean up old backups.</p>
                    <button class="btn btn-secondary w-100 rounded-pill fw-bold btn-sm shadow-sm mb-2" onclick="loadUpdateBackups()">
                        <i class="bi bi-list-ul me-2"></i>View All Backups
                    </button>
                    <div id="updateBackupsContainer" class="mt-3" style="display:none;">
                        <div id="updateBackupsList"></div>
                        <div id="backupStats" class="small text-muted mt-2 text-center"></div>
                    </div>
                    <div class="mt-3 pt-3 border-top">
                        <label class="form-label small text-muted">Cleanup Old Backups</label>
                        <div class="d-flex gap-2">
                            <select id="cleanupDays" class="form-select form-select-sm">
                                <option value="7">7 days</option>
                                <option value="14">14 days</option>
                                <option value="30" selected>30 days</option>
                                <option value="60">60 days</option>
                                <option value="90">90 days</option>
                            </select>
                            <button class="btn btn-warning btn-sm" onclick="cleanupOldBackups()">
                                <i class="bi bi-trash"></i> Cleanup
                            </button>
                        </div>
                    </div>
                </div>
            </div>

            <div class="tab-pane fade" id="danger">
                <div class="action-box border-danger border-opacity-25 bg-danger bg-opacity-10">
                    <div class="box-title text-danger"><i class="bi bi-exclamation-triangle-fill me-2"></i>Factory Reset</div>
                    <form method="POST">
                        <input type="hidden" name="csrf_token" value="<?= htmlspecialchars($csrf) ?>">
                        <input type="hidden" name="action" value="reset">
                        <div class="mb-3">
                            <div class="form-check"><input class="form-check-input" type="checkbox" name="targets[]" value="data"><label class="small fw-bold">Logs & Activity</label></div>
                            <div class="form-check"><input class="form-check-input" type="checkbox" name="targets[]" value="bookings"><label class="small fw-bold text-primary">Booking History Only</label></div>
                            <div class="form-check"><input class="form-check-input" type="checkbox" name="targets[]" value="structure"><label class="small fw-bold">Academic Structure</label></div>
                        </div>
                        <input type="text" name="confirm_code" class="form-control mb-2" placeholder="Type 'DELETE' to confirm">
                        <button class="btn btn-danger w-100 rounded-pill fw-bold btn-sm">Confirm Reset</button>
                    </form>
                </div>
            </div>
        </div>
    </div>

    <?php include 'menu.php'; ?>

    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
    <script>
        const CSRF_TOKEN = <?= json_encode($csrf) ?>;
        
        // Disk Usage Chart
        new Chart(document.getElementById('diskChart'), { 
            type: 'doughnut', 
            data: { 
                labels: ['Used', 'Free'], 
                datasets: [{ 
                    data: [<?= $disk_used ?>, <?= $disk_free ?>], 
                    backgroundColor: ['#ef4444', '#10b981'], 
                    borderWidth: 0 
                }] 
            }, 
            options: { 
                responsive: true, 
                maintainAspectRatio: false, 
                plugins: { legend: { display: false } }, 
                cutout: '70%' 
            } 
        });

        // Index Scanning Tool
        function runIndexScan() {
            const btn = document.getElementById('indexBtn'), res = document.getElementById('indexResults');
            btn.disabled = true; btn.innerHTML = '<span class="spinner-border spinner-border-sm me-2"></span>Scanning...';
            const fd = new FormData(); fd.append('csrf_token', CSRF_TOKEN); fd.append('action', 'check_indexes');
            fetch('admin_system.php', { method: 'POST', body: fd }).then(r => r.json()).then(data => {
                btn.disabled = false; btn.innerText = 'Scan Again'; res.style.display = 'block';
                if (!data.missing || data.missing.length === 0) res.innerHTML = '<div class="alert alert-success small border-0 mb-0">Indexes are optimized!</div>';
                else {
                    let html = '<div class="small fw-bold mb-2">Missing Indexes Found:</div><ul class="list-group small">';
                    data.missing.forEach(m => html += `<li class="list-group-item d-flex justify-content-between align-items-center"><div><b>${m.table}</b>: ${m.col}</div><button class="btn btn-sm btn-primary py-0" onclick="addIndex('${m.table}', '${m.key}', '${m.col}', this)">Generate</button></li>`);
                    res.innerHTML = html + '</ul>';
                }
            });
        }

        function addIndex(table, key, col, btn) {
            btn.disabled = true; btn.innerText = 'Wait...';
            const fd = new FormData(); fd.append('csrf_token', CSRF_TOKEN); fd.append('action', 'add_index'); fd.append('table', table); fd.append('key', key); fd.append('col', col);
            fetch('admin_system.php', { method: 'POST', body: fd }).then(r=>r.json()).then(d => {
                if(d.success) btn.parentElement.classList.add('bg-success', 'bg-opacity-10', 'text-success'), btn.remove();
                else alert(d.message);
            });
        }

        // Integrity Scanning Tool
        function runIntegrityScan() {
            const btn = document.getElementById('scanBtn'), res = document.getElementById('scanResults');
            btn.disabled = true; btn.innerHTML = '<span class="spinner-border spinner-border-sm me-2"></span>Scanning...';
            const fd = new FormData(); fd.append('csrf_token', CSRF_TOKEN); fd.append('action', 'scan_integrity');
            fetch('admin_system.php', { method: 'POST', body: fd }).then(r => r.json()).then(data => {
                btn.disabled = false; btn.innerText = 'Scan Again'; res.style.display = 'block';
                if (!data.issues || data.issues.length === 0) res.innerHTML = '<div class="alert alert-success small border-0 mb-0">Database is healthy!</div>';
                else {
                    let html = '<ul class="list-group small">';
                    data.issues.forEach(i => html += `<li class="list-group-item d-flex justify-content-between align-items-center"><div>${i.label} (${i.count})</div><button class="btn btn-sm btn-outline-danger py-0" onclick="fixIntegrity('${i.type}', this)">Fix</button></li>`);
                    res.innerHTML = html + '</ul>';
                }
            });
        }
        
        function fixIntegrity(type, btn) {
            if(!confirm("Are you sure you want to delete orphaned records?")) return;
            const fd = new FormData(); fd.append('csrf_token', CSRF_TOKEN); fd.append('action', 'fix_integrity'); fd.append('target', type);
            fetch('admin_system.php', { method: 'POST', body: fd }).then(r=>r.json()).then(d => {
                if(d.success) btn.parentElement.remove();
            });
        }

        // Update Backups Management
        function loadUpdateBackups() {
            const container = document.getElementById('updateBackupsContainer');
            const listDiv = document.getElementById('updateBackupsList');
            const statsDiv = document.getElementById('backupStats');
            
            listDiv.innerHTML = '<div class="text-center py-3"><span class="spinner-border spinner-border-sm"></span> Loading...</div>';
            container.style.display = 'block';
            
            const fd = new FormData();
            fd.append('csrf_token', CSRF_TOKEN);
            fd.append('action', 'list_update_backups');
            
            fetch('admin_system.php', { method: 'POST', body: fd })
                .then(r => r.json())
                .then(data => {
                    if (!data.backups || data.backups.length === 0) {
                        listDiv.innerHTML = '<div class="alert alert-info small mb-0">No update backups found.</div>';
                        statsDiv.innerHTML = '';
                        return;
                    }
                    
                    // Calculate stats
                    let totalSize = 0;
                    data.backups.forEach(b => totalSize += b.size);
                    
                    // Build backup list
                    let html = '<div class="list-group list-group-flush small">';
                    data.backups.forEach((backup, index) => {
                        const ageClass = backup.age_days < 1 ? 'success' : backup.age_days < 7 ? 'info' : backup.age_days < 30 ? 'warning' : 'secondary';
                        const ageBadge = backup.age_days < 1 ? 'Today' : backup.age_days + ' days';
                        
                        html += `
                            <div class="list-group-item px-2 py-2" id="backup_${index}">
                                <div class="d-flex justify-content-between align-items-start">
                                    <div class="flex-grow-1">
                                        <div class="fw-bold small">${backup.filename}</div>
                                        <div class="text-muted" style="font-size: 0.75rem;">
                                            ${backup.size_mb} MB • ${backup.created}
                                            ${index === 0 ? '<span class="badge bg-success ms-1">Latest</span>' : ''}
                                            ${backup.age_days > 30 ? '<span class="badge bg-warning ms-1">Old</span>' : ''}
                                        </div>
                                    </div>
                                    <div class="btn-group btn-group-sm ms-2">
                                        <a href="${backup.filepath}" class="btn btn-outline-primary btn-sm py-0 px-2" download title="Download">
                                            <i class="bi bi-download"></i>
                                        </a>
                                        <button class="btn btn-outline-success btn-sm py-0 px-2" onclick="restoreBackup('${backup.filename}')" title="Restore">
                                            <i class="bi bi-arrow-counterclockwise"></i>
                                        </button>
                                        <button class="btn btn-outline-danger btn-sm py-0 px-2" onclick="deleteBackup('${backup.filename}', ${index})" title="Delete">
                                            <i class="bi bi-trash"></i>
                                        </button>
                                    </div>
                                </div>
                            </div>
                        `;
                    });
                    html += '</div>';
                    
                    listDiv.innerHTML = html;
                    statsDiv.innerHTML = `${data.backups.length} backups • ${(totalSize / 1048576).toFixed(2)} MB total`;
                });
        }

        function restoreBackup(filename) {
            if (!confirm('⚠️ WARNING: This will restore files from this backup and overwrite current files!\n\nA pre-restore backup will be created automatically.\n\nContinue?')) {
                return;
            }
            
            const fd = new FormData();
            fd.append('csrf_token', CSRF_TOKEN);
            fd.append('action', 'restore_backup');
            fd.append('backup_file', filename);
            
            fetch('admin_system.php', { method: 'POST', body: fd })
                .then(r => r.json())
                .then(data => {
                    if (data.success) {
                        alert('✅ Backup restored successfully!\n\nPre-restore backup created: ' + data.pre_restore_backup + '\n\nPage will reload...');
                        location.reload();
                    } else {
                        alert('❌ Restore failed: ' + data.message);
                    }
                });
        }

        function deleteBackup(filename, index) {
            if (!confirm('Delete backup: ' + filename + '?\n\nThis cannot be undone!')) {
                return;
            }
            
            const fd = new FormData();
            fd.append('csrf_token', CSRF_TOKEN);
            fd.append('action', 'delete_backup');
            fd.append('backup_file', filename);
            
            fetch('admin_system.php', { method: 'POST', body: fd })
                .then(r => r.json())
                .then(data => {
                    if (data.success) {
                        document.getElementById('backup_' + index).remove();
                        loadUpdateBackups(); // Refresh list
                    } else {
                        alert('❌ Delete failed: ' + data.message);
                    }
                });
        }

        function cleanupOldBackups() {
            const days = document.getElementById('cleanupDays').value;
            
            if (!confirm(`Delete all backups older than ${days} days?\n\nThis cannot be undone!`)) {
                return;
            }
            
            const fd = new FormData();
            fd.append('csrf_token', CSRF_TOKEN);
            fd.append('action', 'cleanup_old_backups');
            fd.append('days_to_keep', days);
            
            fetch('admin_system.php', { method: 'POST', body: fd })
                .then(r => r.json())
                .then(data => {
                    if (data.success) {
                        alert('✅ ' + data.message);
                        loadUpdateBackups(); // Refresh list
                    } else {
                        alert('❌ Cleanup failed');
                    }
                });
        }
    </script>
</body>
</html>