<?php
/**
 * Enhanced Database Backup Engine
 * Reads configuration from backup_config.json and performs automated backups
 */

// Include the WAMP detector
require_once 'functions/wamp_detector.php';

class DatabaseBackupEngine {
    private $config;
    private $logFile;
    private $db;
    private $dbCredentials;
    
    public function __construct() {
        // Load database credentials safely
        $this->loadDatabaseCredentials();
        
        // Create direct connection without timezone helper complications
        $this->db = new mysqli(
            $this->dbCredentials['host'],
            $this->dbCredentials['username'],
            $this->dbCredentials['password'],
            $this->dbCredentials['database']
        );
        
        if ($this->db->connect_error) {
            throw new Exception("Database connection failed: " . $this->db->connect_error);
        }
        
        // Load configuration
        $this->loadConfiguration();
        
        // Setup logging
        $this->logFile = $this->config['storage']['local_path'] . 'backup_log.txt';
        $this->ensureBackupDirectory();
    }
    
    private function loadDatabaseCredentials() {
        // Default credentials
        $this->dbCredentials = [
            'host' => 'localhost',
            'username' => 'itresources', 
            'password' => 'ITResources@786',
            'database' => 'itrpos'
        ];
        
        // Try to read from db.php safely
        if (file_exists('db.php')) {
            $dbContent = file_get_contents('db.php');
            
            // Extract database variables using regex (safer than include)
            if (preg_match('/\$host\s*=\s*[\'"]([^\'"]+)[\'"]/', $dbContent, $matches)) {
                $this->dbCredentials['host'] = $matches[1];
            }
            if (preg_match('/\$db_name\s*=\s*[\'"]([^\'"]+)[\'"]/', $dbContent, $matches)) {
                $this->dbCredentials['database'] = $matches[1];
            }
            if (preg_match('/\$username\s*=\s*[\'"]([^\'"]+)[\'"]/', $dbContent, $matches)) {
                $this->dbCredentials['username'] = $matches[1];
            }
            if (preg_match('/\$password\s*=\s*[\'"]([^\'"]+)[\'"]/', $dbContent, $matches)) {
                $this->dbCredentials['password'] = $matches[1];
            }
        }
    }
    
    private function loadConfiguration() {
        $configFile = 'backup_config.json';
        
        // Get recommended backup path based on WAMP installation
        $recommendedBackupPath = WampDetector::getRecommendedBackupPath();
        
        $defaultConfig = [
            'frequency' => ['enabled' => true, 'type' => 'daily'],
            'retention' => ['daily_keep' => 30, 'weekly_keep' => 12, 'monthly_keep' => 12, 'auto_cleanup' => true],
            'storage' => ['local_enabled' => true, 'local_path' => $recommendedBackupPath, 'local_secondary_path' => ''],
            'backup_options' => ['compression' => true, 'verification' => true, 'include_structure' => true, 'include_data' => true],
            'notifications' => ['email_enabled' => false, 'email_on_success' => false, 'email_on_failure' => true],
            'monitoring' => ['log_level' => 'info']
        ];
        
        if (file_exists($configFile)) {
            $config = json_decode(file_get_contents($configFile), true);
            $this->config = array_replace_recursive($defaultConfig, $config ?? []);
            
            // Always update to the recommended path if it's different from current
            if (isset($this->config['storage']['local_path']) && 
                $this->config['storage']['local_path'] !== $recommendedBackupPath) {
                
                $this->config['storage']['local_path'] = $recommendedBackupPath;
                $this->saveConfiguration(); // Save the updated path
            }
        } else {
            $this->config = $defaultConfig;
            $this->saveConfiguration(); // Save the default configuration
        }
    }
    
    private function saveConfiguration() {
        $configFile = 'backup_config.json';
        file_put_contents($configFile, json_encode($this->config, JSON_PRETTY_PRINT));
    }
    
    private function ensureBackupDirectory() {
        $dir = $this->config['storage']['local_path'];
        
        $this->log("Ensuring backup directory exists: {$dir}", 'INFO');
        
        if (!is_dir($dir)) {
            $this->log("Backup directory does not exist, creating: {$dir}", 'INFO');
            if (!mkdir($dir, 0755, true)) {
                $error = "Cannot create backup directory: {$dir}";
                $this->log($error, 'ERROR');
                throw new Exception($error);
            }
            $this->log("Backup directory created successfully: {$dir}", 'SUCCESS');
        } else {
            $this->log("Backup directory already exists: {$dir}", 'INFO');
        }
        
        // Ensure writable
        if (!is_writable($dir)) {
            $error = "Backup directory is not writable: {$dir}";
            $this->log($error, 'ERROR');
            throw new Exception($error);
        }
        
        $this->log("Backup directory is writable: {$dir}", 'INFO');
        
        // Create secondary directory if specified
        $secondaryDir = $this->config['storage']['local_secondary_path'];
        if (!empty($secondaryDir) && !is_dir($secondaryDir)) {
            $this->log("Creating secondary backup directory: {$secondaryDir}", 'INFO');
            if (!mkdir($secondaryDir, 0755, true)) {
                $this->log("Warning: Could not create secondary backup directory: {$secondaryDir}", 'WARNING');
            } else {
                $this->log("Secondary backup directory created: {$secondaryDir}", 'SUCCESS');
            }
        }
    }
    
    public function createBackup($type = 'manual') {
        $startTime = microtime(true);
        $timestamp = date('Y-m-d_H-i-s');
        $filename = "itrpos_backup_{$type}_{$timestamp}.sql";
        $filepath = $this->config['storage']['local_path'] . $filename;
        
        try {
            $this->log("Starting {$type} backup: {$filename}", 'INFO');
            
            // Check if backups are enabled
            if (!$this->config['frequency']['enabled'] && $type !== 'manual') {
                throw new Exception("Automated backups are disabled");
            }
            
            // Create mysqldump command
            $command = $this->buildMysqldumpCommand($filepath);
            
            // Log the command being executed (for debugging - remove password)
            $safeCommand = str_replace($this->dbCredentials['password'], '****', $command);
            $this->log("Executing backup command: {$safeCommand}", 'DEBUG');
            
            // Execute backup
            exec($command . ' 2>&1', $output, $returnCode);
            
            if ($returnCode !== 0) {
                $errorOutput = implode("\n", $output);
                $this->log("Mysqldump command failed. Return code: {$returnCode}, Output: {$errorOutput}", 'ERROR');
                
                // Provide more helpful error messages
                $errorMessage = "Mysqldump failed with return code: {$returnCode}";
                if (empty($errorOutput)) {
                    $errorMessage .= ". No output captured. Check if mysqldump is installed and accessible.";
                } else {
                    $errorMessage .= ". Output: {$errorOutput}";
                }
                
                throw new Exception($errorMessage);
            }
            
            // Check if backup file was created and has content
            if (!file_exists($filepath) || filesize($filepath) === 0) {
                throw new Exception("Backup file was not created or is empty");
            }
            
            $originalSize = filesize($filepath);
            
            // Compress if enabled
            if ($this->config['backup_options']['compression']) {
                $this->compressBackup($filepath);
                $filepath .= '.gz';
                $filename .= '.gz';
            }
            
            // Verify backup integrity
            if ($this->config['backup_options']['verification']) {
                $this->verifyBackup($filepath);
            }
            
            // Copy to secondary location if specified
            $this->copyToSecondaryLocation($filepath, $filename);
            
            // Upload to cloud if enabled
            if ($this->config['storage']['cloud_enabled']) {
                $this->uploadToCloud($filepath, $filename);
            }
            
            // Get final file size and calculate stats
            $finalSize = filesize($filepath);
            $formattedSize = $this->formatBytes($finalSize);
            $duration = round(microtime(true) - $startTime, 2);
            $compressionRatio = $this->config['backup_options']['compression'] ? 
                round(($originalSize - $finalSize) / $originalSize * 100, 1) : 0;
            
            $message = "Backup completed successfully: {$filename} ({$formattedSize}) in {$duration}s";
            if ($compressionRatio > 0) {
                $message .= " (Compressed: {$compressionRatio}%)";
            }
            
            $this->log($message, 'SUCCESS');
            
            // Send success notification
            if ($this->config['notifications']['email_enabled'] && 
                $this->config['notifications']['email_on_success']) {
                $this->sendNotification($message, 'success', [
                    'type' => $type,
                    'filename' => $filename,
                    'size' => $formattedSize,
                    'duration' => $duration,
                    'compression' => $compressionRatio
                ]);
            }
            
            // Cleanup old backups
            if ($this->config['retention']['auto_cleanup']) {
                $this->cleanupOldBackups($type);
            }
            
            return [
                'success' => true,
                'message' => $message,
                'filepath' => $filepath,
                'filename' => $filename,
                'size' => $formattedSize,
                'duration' => $duration,
                'compression_ratio' => $compressionRatio
            ];
            
        } catch (Exception $e) {
            $error = "Backup failed: " . $e->getMessage();
            $this->log($error, 'ERROR');
            
            // Clean up failed backup file
            if (file_exists($filepath)) {
                unlink($filepath);
            }
            if (file_exists($filepath . '.gz')) {
                unlink($filepath . '.gz');
            }
            
            // Send failure notification
            if ($this->config['notifications']['email_enabled'] && 
                $this->config['notifications']['email_on_failure']) {
                $this->sendNotification($error, 'error', [
                    'type' => $type,
                    'error_details' => $e->getMessage()
                ]);
            }
            
            return [
                'success' => false,
                'message' => $error,
                'error' => $e->getMessage()
            ];
        }
    }
    
    private function buildMysqldumpCommand($filepath) {
        // Use stored database credentials
        $host = $this->dbCredentials['host'];
        $username = $this->dbCredentials['username'];
        $password = $this->dbCredentials['password'];
        $db_name = $this->dbCredentials['database'];
        
        // Use WAMP detector to find mysqldump
        $mysqldump = WampDetector::getMysqldumpPath();
        
        if (empty($mysqldump)) {
            throw new Exception("MySQL dump utility not found. Please ensure WAMP/XAMPP is properly installed.");
        }
        
        // Verify the mysqldump is accessible
        if ($mysqldump !== 'mysqldump' && !file_exists($mysqldump)) {
            throw new Exception("MySQL dump utility path is invalid: {$mysqldump}");
        }
        
        $command = escapeshellarg($mysqldump);
        $command .= " --host=" . escapeshellarg($host);
        $command .= " --user=" . escapeshellarg($username);
        $command .= " --password=" . escapeshellarg($password);
        
        // Add backup options
        if ($this->config['backup_options']['include_structure']) {
            // Include CREATE TABLE statements
        } else {
            $command .= " --no-create-info";
        }
        
        if (!$this->config['backup_options']['include_data']) {
            $command .= " --no-data";
        }
        
        // Add additional mysqldump options for better compatibility
        $command .= " --single-transaction"; // For InnoDB consistency
        $command .= " --routines"; // Include stored procedures and functions
        $command .= " --triggers"; // Include triggers
        $command .= " --add-drop-table"; // Add DROP TABLE before CREATE TABLE
        $command .= " --complete-insert"; // Use complete INSERT statements
        $command .= " --extended-insert"; // Use multiple-row INSERT syntax
        $command .= " --quick"; // Retrieve rows one at a time
        $command .= " --lock-tables=false"; // Don't lock tables
        
        $command .= " " . escapeshellarg($db_name);
        $command .= " > " . escapeshellarg($filepath);
        
        return $command;
    }
    
    public function testMysqldump() {
        // Test function to help diagnose mysqldump issues using WAMP detector
        $result = [];
        
        // Get detailed diagnostics from WAMP detector
        $diagnostics = WampDetector::getDiagnostics();
        
        // Extract detection results
        if (isset($diagnostics['detection_result'])) {
            $detection = $diagnostics['detection_result'];
            
            $result['wamp_detection'] = [
                'server_type' => $detection['server_type'],
                'wamp_root' => $detection['wamp_root'],
                'mysql_version' => $detection['mysql_version'],
                'mysql_bin_path' => $detection['mysql_bin_path']
            ];
        }
        
        // Test mysqldump specifically
        if (isset($diagnostics['mysqldump_test'])) {
            $test = $diagnostics['mysqldump_test'];
            
            $result['mysqldump_path'] = $test['path'];
            $result['mysqldump_executable'] = $test['executable'] ? 'Yes' : 'No';
            $result['mysqldump_version'] = $test['version_output'];
        } else {
            $result['mysqldump_path'] = 'Not found';
            $result['mysqldump_executable'] = 'No';
            $result['mysqldump_version'] = 'N/A';
        }
        
        // Test basic command
        $mysqldumpPath = WampDetector::getMysqldumpPath();
        if ($mysqldumpPath) {
            $testCommand = ($mysqldumpPath === 'mysqldump') ? 
                'mysqldump --version 2>&1' : 
                escapeshellarg($mysqldumpPath) . ' --version 2>&1';
            
            exec($testCommand, $versionOutput, $versionReturnCode);
            $result['version_test'] = [
                'command' => $testCommand,
                'return_code' => $versionReturnCode,
                'output' => implode("\n", $versionOutput)
            ];
        } else {
            $result['version_test'] = [
                'command' => 'N/A - mysqldump not found',
                'return_code' => 1,
                'output' => 'WAMP detector could not locate mysqldump'
            ];
        }
        
        return $result;
    }
    
    /**
     * Test database connection
     * @return array Connection test results
     */
    public function testDatabaseConnection() {
        $result = [];
        
        if ($this->db && !$this->db->connect_error) {
            $result['connected'] = true;
            $result['server_info'] = $this->db->server_info;
            $result['host_info'] = $this->db->host_info;
            $result['client_info'] = $this->db->client_info;
            $result['database'] = $this->dbCredentials['database'];
            $result['host'] = $this->dbCredentials['host'];
            $result['username'] = $this->dbCredentials['username'];
        } else {
            $result['connected'] = false;
            $result['error'] = $this->db ? $this->db->connect_error : 'Database object not initialized';
        }
        
        return $result;
    }
    
    private function compressBackup($filepath) {
        if (!function_exists('gzopen')) {
            throw new Exception("PHP GZ extension not available for compression");
        }
        
        $this->log("Compressing backup file", 'INFO');
        
        $gz = gzopen($filepath . '.gz', 'wb9');
        if (!$gz) {
            throw new Exception("Cannot create compressed file");
        }
        
        $file = fopen($filepath, 'rb');
        if (!$file) {
            gzclose($gz);
            throw new Exception("Cannot read original backup file for compression");
        }
        
        while (!feof($file)) {
            gzwrite($gz, fread($file, 8192));
        }
        
        fclose($file);
        gzclose($gz);
        
        // Remove original uncompressed file
        unlink($filepath);
        
        $this->log("Backup compressed successfully", 'INFO');
    }
    
    private function verifyBackup($filepath) {
        $this->log("Verifying backup integrity", 'INFO');
        
        if ($this->config['backup_options']['compression']) {
            // Verify compressed file can be read
            $gz = gzopen($filepath, 'rb');
            if (!$gz) {
                throw new Exception("Cannot open compressed backup file for verification");
            }
            
            // Read first few lines to find actual SQL content (skip warnings)
            $lines = [];
            $linesRead = 0;
            while (($line = gzgets($gz)) !== false && $linesRead < 10) {
                $lines[] = $line;
                $linesRead++;
            }
            gzclose($gz);
            
            // More flexible verification - check for common SQL dump headers
            $validHeaders = [
                '-- MySQL dump',
                '-- phpMyAdmin SQL Dump', 
                '-- Dump',
                'SET @@',
                'CREATE DATABASE',
                'USE `',
                '/*!40101 SET'
            ];
            
            $isValid = false;
            $validLine = '';
            
            // Check each line for valid SQL dump content, skip warnings
            foreach ($lines as $line) {
                $trimmedLine = trim($line);
                
                // Skip warning lines
                if (strpos($trimmedLine, 'mysqldump: [Warning]') !== false ||
                    strpos($trimmedLine, 'Warning:') !== false ||
                    empty($trimmedLine)) {
                    continue;
                }
                
                foreach ($validHeaders as $header) {
                    if (strpos($trimmedLine, $header) !== false) {
                        $isValid = true;
                        $validLine = $trimmedLine;
                        break 2;
                    }
                }
            }
            
            if (!$isValid) {
                $this->log("First few lines of backup: " . implode(' | ', array_map('trim', array_slice($lines, 0, 3))), 'DEBUG');
                throw new Exception("Backup file verification failed - no valid SQL dump content found in first 10 lines");
            } else {
                $this->log("Valid SQL dump detected: " . trim(substr($validLine, 0, 50)), 'DEBUG');
            }
        } else {
            // Verify uncompressed file
            $file = fopen($filepath, 'r');
            if (!$file) {
                throw new Exception("Cannot open backup file for verification");
            }
            
            // Read first few lines to find actual SQL content (skip warnings)
            $lines = [];
            $linesRead = 0;
            while (($line = fgets($file)) !== false && $linesRead < 10) {
                $lines[] = $line;
                $linesRead++;
            }
            fclose($file);
            
            // More flexible verification - check for common SQL dump headers
            $validHeaders = [
                '-- MySQL dump',
                '-- phpMyAdmin SQL Dump', 
                '-- Dump',
                'SET @@',
                'CREATE DATABASE',
                'USE `',
                '/*!40101 SET'
            ];
            
            $isValid = false;
            $validLine = '';
            
            // Check each line for valid SQL dump content, skip warnings
            foreach ($lines as $line) {
                $trimmedLine = trim($line);
                
                // Skip warning lines
                if (strpos($trimmedLine, 'mysqldump: [Warning]') !== false ||
                    strpos($trimmedLine, 'Warning:') !== false ||
                    empty($trimmedLine)) {
                    continue;
                }
                
                foreach ($validHeaders as $header) {
                    if (strpos($trimmedLine, $header) !== false) {
                        $isValid = true;
                        $validLine = $trimmedLine;
                        break 2;
                    }
                }
            }
            
            if (!$isValid) {
                $this->log("First few lines of backup: " . implode(' | ', array_map('trim', array_slice($lines, 0, 3))), 'DEBUG');
                throw new Exception("Backup file verification failed - no valid SQL dump content found in first 10 lines");
            } else {
                $this->log("Valid SQL dump detected: " . trim(substr($validLine, 0, 50)), 'DEBUG');
            }
        }
        
        $this->log("Backup verification completed successfully", 'INFO');
    }
    
    private function copyToSecondaryLocation($filepath, $filename) {
        $secondaryPath = $this->config['storage']['local_secondary_path'];
        if (empty($secondaryPath)) {
            return;
        }
        
        $this->log("Copying backup to secondary location", 'INFO');
        
        if (!is_dir($secondaryPath)) {
            mkdir($secondaryPath, 0755, true);
        }
        
        $secondaryFile = $secondaryPath . '/' . $filename;
        if (!copy($filepath, $secondaryFile)) {
            $this->log("Failed to copy backup to secondary location", 'WARNING');
        } else {
            $this->log("Backup copied to secondary location successfully", 'INFO');
        }
    }
    
    private function uploadToCloud($filepath, $filename) {
        // Placeholder for cloud upload functionality
        $provider = $this->config['storage']['cloud_provider'];
        
        switch ($provider) {
            case 'gdrive':
                $this->uploadToGoogleDrive($filepath, $filename);
                break;
            case 'dropbox':
                $this->uploadToDropbox($filepath, $filename);
                break;
            case 'ftp':
                $this->uploadToFTP($filepath, $filename);
                break;
            case 'aws_s3':
                $this->uploadToAWS($filepath, $filename);
                break;
            default:
                $this->log("Unknown cloud provider: {$provider}", 'WARNING');
        }
    }
    
    private function uploadToGoogleDrive($filepath, $filename) {
        $this->log("Google Drive upload not yet implemented", 'INFO');
        // Implementation for Google Drive upload will be added
    }
    
    private function uploadToDropbox($filepath, $filename) {
        $this->log("Dropbox upload not yet implemented", 'INFO');
        // Implementation for Dropbox upload will be added
    }
    
    private function uploadToFTP($filepath, $filename) {
        $this->log("FTP upload not yet implemented", 'INFO');
        // Implementation for FTP upload will be added
    }
    
    private function uploadToAWS($filepath, $filename) {
        $this->log("AWS S3 upload not yet implemented", 'INFO');
        // Implementation for AWS S3 upload will be added
    }
    
    private function cleanupOldBackups($type) {
        $this->log("Starting backup cleanup", 'INFO');
        
        $backupDir = $this->config['storage']['local_path'];
        $pattern = $backupDir . 'itrpos_backup_*.sql*';
        $files = glob($pattern);
        
        if (empty($files)) {
            return;
        }
        
        // Organize files by type and date
        $backupsByType = ['daily' => [], 'weekly' => [], 'monthly' => []];
        
        foreach ($files as $file) {
            $basename = basename($file);
            $mtime = filemtime($file);
            
            // Determine backup type and age
            if (strpos($basename, '_daily_') !== false) {
                $backupsByType['daily'][] = ['file' => $file, 'time' => $mtime];
            } elseif (strpos($basename, '_weekly_') !== false) {
                $backupsByType['weekly'][] = ['file' => $file, 'time' => $mtime];
            } elseif (strpos($basename, '_monthly_') !== false) {
                $backupsByType['monthly'][] = ['file' => $file, 'time' => $mtime];
            } else {
                // Treat unknown types as daily
                $backupsByType['daily'][] = ['file' => $file, 'time' => $mtime];
            }
        }
        
        // Sort each type by date (newest first)
        foreach ($backupsByType as &$backups) {
            usort($backups, function($a, $b) {
                return $b['time'] - $a['time'];
            });
        }
        
        // Clean up old backups based on retention policy
        $retention = $this->config['retention'];
        $deletedCount = 0;
        
        // Daily backups
        if (count($backupsByType['daily']) > $retention['daily_keep']) {
            $toDelete = array_slice($backupsByType['daily'], $retention['daily_keep']);
            foreach ($toDelete as $backup) {
                if (unlink($backup['file'])) {
                    $deletedCount++;
                    $this->log("Deleted old daily backup: " . basename($backup['file']), 'INFO');
                }
            }
        }
        
        // Weekly backups
        if (count($backupsByType['weekly']) > $retention['weekly_keep']) {
            $toDelete = array_slice($backupsByType['weekly'], $retention['weekly_keep']);
            foreach ($toDelete as $backup) {
                if (unlink($backup['file'])) {
                    $deletedCount++;
                    $this->log("Deleted old weekly backup: " . basename($backup['file']), 'INFO');
                }
            }
        }
        
        // Monthly backups
        if (count($backupsByType['monthly']) > $retention['monthly_keep']) {
            $toDelete = array_slice($backupsByType['monthly'], $retention['monthly_keep']);
            foreach ($toDelete as $backup) {
                if (unlink($backup['file'])) {
                    $deletedCount++;
                    $this->log("Deleted old monthly backup: " . basename($backup['file']), 'INFO');
                }
            }
        }
        
        $this->log("Cleanup completed. Deleted {$deletedCount} old backups", 'INFO');
    }
    
    private function sendNotification($message, $type, $details = []) {
        if (!$this->config['notifications']['email_enabled']) {
            return;
        }
        
        $settings = $this->config['notifications']['smtp_settings'];
        $adminEmail = $this->config['notifications']['admin_email'];
        
        if (empty($adminEmail) || empty($settings['host'])) {
            $this->log("Email notification skipped - incomplete configuration", 'WARNING');
            return;
        }
        
        $subject = $type === 'success' ? 
            "✅ ITRPOS Backup Successful" : 
            "❌ ITRPOS Backup Failed";
        
        $body = "<h3>ITRPOS Database Backup Report</h3>";
        $body .= "<p><strong>Status:</strong> " . ucfirst($type) . "</p>";
        $body .= "<p><strong>Message:</strong> {$message}</p>";
        $body .= "<p><strong>Time:</strong> " . date('Y-m-d H:i:s') . "</p>";
        
        if (!empty($details)) {
            $body .= "<h4>Details:</h4><ul>";
            foreach ($details as $key => $value) {
                $body .= "<li><strong>" . ucfirst(str_replace('_', ' ', $key)) . ":</strong> {$value}</li>";
            }
            $body .= "</ul>";
        }
        
        $body .= "<p><em>This is an automated message from ITRPOS Backup System.</em></p>";
        
        // Simple mail sending (can be enhanced with PHPMailer later)
        $headers = [
            'MIME-Version: 1.0',
            'Content-type: text/html; charset=UTF-8',
            'From: ITRPOS Backup System <noreply@itrpos.local>',
            'Reply-To: ' . $adminEmail,
            'X-Mailer: PHP/' . phpversion()
        ];
        
        if (mail($adminEmail, $subject, $body, implode("\r\n", $headers))) {
            $this->log("Email notification sent to {$adminEmail}", 'INFO');
        } else {
            $this->log("Failed to send email notification", 'WARNING');
        }
    }
    
    private function log($message, $level = 'INFO') {
        $timestamp = date('Y-m-d H:i:s');
        $logEntry = "[{$timestamp}] [{$level}] {$message}" . PHP_EOL;
        
        // Only log if level is appropriate
        $configLevel = strtoupper($this->config['monitoring']['log_level']);
        $levels = ['DEBUG' => 0, 'INFO' => 1, 'WARNING' => 2, 'ERROR' => 3, 'SUCCESS' => 1];
        
        if ($levels[$level] >= $levels[$configLevel]) {
            file_put_contents($this->logFile, $logEntry, FILE_APPEND | LOCK_EX);
        }
        
        // Also output to console if running from command line
        if (php_sapi_name() === 'cli') {
            echo $logEntry;
        }
        
        // Manage log file size
        $this->manageLogSize();
    }
    
    private function manageLogSize() {
        if (!file_exists($this->logFile)) {
            return;
        }
        
        $maxSize = $this->config['monitoring']['max_log_size_mb'] * 1024 * 1024;
        if (filesize($this->logFile) > $maxSize) {
            // Keep last 50% of the log
            $content = file_get_contents($this->logFile);
            $lines = explode("\n", $content);
            $keepLines = array_slice($lines, count($lines) / 2);
            file_put_contents($this->logFile, implode("\n", $keepLines));
        }
    }
    
    private function formatBytes($bytes, $precision = 2) {
        $units = array('B', 'KB', 'MB', 'GB', 'TB');
        
        for ($i = 0; $bytes > 1024 && $i < count($units) - 1; $i++) {
            $bytes /= 1024;
        }
        
        return round($bytes, $precision) . ' ' . $units[$i];
    }
    
    public function getBackupsList() {
        $backupDir = $this->config['storage']['local_path'];
        $pattern = $backupDir . 'itrpos_backup_*.sql*';
        $files = glob($pattern);
        
        $backups = [];
        foreach ($files as $file) {
            $backups[] = [
                'filename' => basename($file),
                'filepath' => $file,
                'size' => $this->formatBytes(filesize($file)),
                'created' => date('Y-m-d H:i:s', filemtime($file)),
                'type' => $this->detectBackupType(basename($file))
            ];
        }
        
        // Sort by creation time (newest first)
        usort($backups, function($a, $b) {
            return strtotime($b['created']) - strtotime($a['created']);
        });
        
        return $backups;
    }
    
    private function detectBackupType($filename) {
        if (strpos($filename, '_daily_') !== false) return 'Daily';
        if (strpos($filename, '_weekly_') !== false) return 'Weekly';
        if (strpos($filename, '_monthly_') !== false) return 'Monthly';
        if (strpos($filename, '_manual_') !== false) return 'Manual';
        return 'Unknown';
    }
}

// Handle direct execution
if (php_sapi_name() === 'cli' || isset($_GET['action'])) {
    try {
        $engine = new DatabaseBackupEngine();
        
        $action = $_GET['action'] ?? $argv[1] ?? 'manual';
        $type = $_GET['type'] ?? $argv[2] ?? 'manual';
        
        switch ($action) {
            case 'run_now':
            case 'backup':
                $result = $engine->createBackup($type);
                
                if (php_sapi_name() === 'cli') {
                    echo json_encode($result, JSON_PRETTY_PRINT) . "\n";
                } else {
                    header('Content-Type: application/json');
                    echo json_encode($result);
                }
                break;
                
            case 'list':
                $backups = $engine->getBackupsList();
                header('Content-Type: application/json');
                echo json_encode($backups);
                break;
                
            case 'test':
                $testResults = $engine->testMysqldump();
                header('Content-Type: application/json');
                echo json_encode($testResults, JSON_PRETTY_PRINT);
                break;
                
            default:
                if (php_sapi_name() !== 'cli') {
                    header('Location: backup_management.php');
                    exit;
                } else {
                    echo "Usage: php backup_engine.php [backup|list] [daily|weekly|monthly|manual]\n";
                }
        }
        
    } catch (Exception $e) {
        $error = ['success' => false, 'message' => $e->getMessage()];
        
        if (php_sapi_name() === 'cli') {
            echo json_encode($error, JSON_PRETTY_PRINT) . "\n";
            exit(1);
        } else {
            header('Content-Type: application/json');
            http_response_code(500);
            echo json_encode($error);
        }
    }
}
