<?php
/**
 * Kontroler Administracji
 * 
 * Sekcje:
 * - Konfiguracja systemu
 * - Monitor serwera
 * - Logi systemowe
 * - Harmonogram zadań
 * - Tryb konserwacji
 * - Aktualizacje
 */

require_once __DIR__ . '/BaseController.php';

class AdminController extends BaseController
{
    private string $configFile;
    private string $cronFile;
    private AuditLog $auditLog;
    
    public function __construct()
    {
        parent::__construct();
        
        // Tylko admin ma dostęp
        if (!$this->auth->isAdmin()) {
            $this->redirect('dashboard', 'danger', 'Brak dostępu.');
            exit;
        }
        
        $this->configFile = __DIR__ . '/../../config/settings.json';
        $this->cronFile = __DIR__ . '/../../config/cron_jobs.json';
        $this->auditLog = new AuditLog();
        
        // Utwórz katalog config jeśli nie istnieje
        $configDir = dirname($this->configFile);
        if (!is_dir($configDir)) {
            mkdir($configDir, 0755, true);
        }
    }
    
    // ==================== KONFIGURACJA ====================
    
    /**
     * Strona konfiguracji systemu
     */
    public function settings(): void
    {
        $settings = $this->loadSettings();
        
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            if (!$this->verifyCsrf()) {
                return;
            }
            
            $newSettings = [
                'site_name' => trim(post('site_name', 'IPTV Panel')),
                'site_description' => trim(post('site_description', '')),
                'items_per_page' => max(5, min(100, (int)post('items_per_page', 20))),
                'session_lifetime' => max(300, min(86400, (int)post('session_lifetime', 3600))),
                'maintenance_mode' => post('maintenance_mode') ? true : false,
                'maintenance_message' => trim(post('maintenance_message', 'System w trakcie konserwacji.')),
                'allow_registration' => post('allow_registration') ? true : false,
                'default_device_limit' => max(1, min(100, (int)post('default_device_limit', 3))),
                'default_playlist_limit' => max(1, min(1000, (int)post('default_playlist_limit', 100))),
                'password_length' => max(6, min(32, (int)post('password_length', 12))),
                'password_lowercase' => post('password_lowercase') ? true : false,
                'password_uppercase' => post('password_uppercase') ? true : false,
                'password_numbers' => post('password_numbers') ? true : false,
                'password_symbols' => post('password_symbols') ? true : false,
                'api_enabled' => post('api_enabled') ? true : false,
                'api_rate_limit' => max(10, min(1000, (int)post('api_rate_limit', 100))),
                'log_retention_days' => max(1, min(365, (int)post('log_retention_days', 30))),
                'smtp_enabled' => post('smtp_enabled') ? true : false,
                'smtp_host' => trim(post('smtp_host', '')),
                'smtp_port' => (int)post('smtp_port', 587),
                'smtp_user' => trim(post('smtp_user', '')),
                'smtp_pass' => post('smtp_pass') ?: ($settings['smtp_pass'] ?? ''),
                'smtp_from' => trim(post('smtp_from', '')),
                'smtp_from_name' => trim(post('smtp_from_name', 'IPTV Panel')),
                'login_attempts_limit' => max(3, min(20, (int)post('login_attempts_limit', 5))),
                'login_lockout_time' => max(60, min(3600, (int)post('login_lockout_time', 300))),
            ];
            
            if ($this->saveSettings($newSettings)) {
                $this->logger->log('settings_updated', 'Zaktualizowano ustawienia systemu', $this->currentUser['id']);
                
                // Audit log
                $this->auditLog->log(
                    AuditLog::ENTITY_SETTINGS,
                    0,
                    AuditLog::ACTION_UPDATE,
                    $settings,
                    $newSettings
                );
                
                $this->redirect('admin/settings', 'success', 'Ustawienia zostały zapisane.');
            } else {
                $this->render('admin/settings.tpl', [
                    'pageTitle' => 'Konfiguracja systemu',
                    'settings' => $newSettings,
                    'error' => 'Nie udało się zapisać ustawień.'
                ]);
            }
            return;
        }
        
        $this->render('admin/settings.tpl', [
            'pageTitle' => 'Konfiguracja systemu',
            'settings' => $settings
        ]);
    }
    
    /**
     * Wczytaj ustawienia
     */
    private function loadSettings(): array
    {
        $defaults = [
            'site_name' => 'IPTV Panel',
            'site_description' => 'Panel zarządzania playlistami IPTV',
            'items_per_page' => 20,
            'session_lifetime' => 3600,
            'maintenance_mode' => false,
            'maintenance_message' => 'System w trakcie konserwacji. Spróbuj ponownie później.',
            'allow_registration' => false,
            'default_device_limit' => 3,
            'default_playlist_limit' => 100,
            'api_enabled' => true,
            'api_rate_limit' => 100,
            'log_retention_days' => 30,
            'smtp_enabled' => false,
            'smtp_host' => '',
            'smtp_port' => 587,
            'smtp_user' => '',
            'smtp_pass' => '',
            'smtp_from' => '',
            'smtp_from_name' => 'IPTV Panel',
            'login_attempts_limit' => 5,
            'login_lockout_time' => 300,
        ];
        
        if (file_exists($this->configFile)) {
            $saved = json_decode(file_get_contents($this->configFile), true);
            if (is_array($saved)) {
                return array_merge($defaults, $saved);
            }
        }
        
        return $defaults;
    }
    
    /**
     * Zapisz ustawienia
     */
    private function saveSettings(array $settings): bool
    {
        $json = json_encode($settings, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
        return file_put_contents($this->configFile, $json) !== false;
    }
    
    // ==================== MONITOR SERWERA ====================
    
    /**
     * Monitor serwera
     */
    public function monitor(): void
    {
        $stats = $this->getServerStats();
        
        $this->render('admin/monitor.tpl', [
            'pageTitle' => 'Monitor serwera',
            'stats' => $stats
        ]);
    }
    
    /**
     * API - pobierz statystyki serwera (AJAX)
     */
    public function monitorApi(): void
    {
        $this->json([
            'success' => true,
            'stats' => $this->getServerStats()
        ]);
    }
    
    /**
     * Pobierz statystyki serwera
     */
    private function getServerStats(): array
    {
        $stats = [
            'timestamp' => date('Y-m-d H:i:s'),
            'php_version' => PHP_VERSION,
            'server_software' => $_SERVER['SERVER_SOFTWARE'] ?? 'Unknown',
        ];
        
        // CPU Load
        if (function_exists('sys_getloadavg')) {
            $load = sys_getloadavg();
            $stats['cpu_load'] = [
                '1min' => round($load[0], 2),
                '5min' => round($load[1], 2),
                '15min' => round($load[2], 2)
            ];
        } else {
            $stats['cpu_load'] = ['1min' => 0, '5min' => 0, '15min' => 0];
        }
        
        // Liczba rdzeni CPU
        $cpuCores = 1;
        if (is_readable('/proc/cpuinfo')) {
            $cpuinfo = file_get_contents('/proc/cpuinfo');
            $cpuCores = substr_count($cpuinfo, 'processor');
        }
        $stats['cpu_cores'] = $cpuCores;
        $stats['cpu_percent'] = min(100, round(($stats['cpu_load']['1min'] / $cpuCores) * 100, 1));
        
        // Memory
        if (is_readable('/proc/meminfo')) {
            $meminfo = file_get_contents('/proc/meminfo');
            preg_match('/MemTotal:\s+(\d+)/', $meminfo, $total);
            preg_match('/MemAvailable:\s+(\d+)/', $meminfo, $available);
            
            $totalMem = isset($total[1]) ? (int)$total[1] * 1024 : 0;
            $availableMem = isset($available[1]) ? (int)$available[1] * 1024 : 0;
            $usedMem = $totalMem - $availableMem;
            
            $stats['memory'] = [
                'total' => $totalMem,
                'used' => $usedMem,
                'free' => $availableMem,
                'percent' => $totalMem > 0 ? round(($usedMem / $totalMem) * 100, 1) : 0
            ];
        } else {
            $stats['memory'] = ['total' => 0, 'used' => 0, 'free' => 0, 'percent' => 0];
        }
        
        // Disk
        $diskPath = '/';
        $stats['disk'] = [
            'total' => @disk_total_space($diskPath) ?: 0,
            'free' => @disk_free_space($diskPath) ?: 0,
            'used' => (@disk_total_space($diskPath) ?: 0) - (@disk_free_space($diskPath) ?: 0),
            'percent' => 0
        ];
        if ($stats['disk']['total'] > 0) {
            $stats['disk']['percent'] = round(($stats['disk']['used'] / $stats['disk']['total']) * 100, 1);
        }
        
        // Uptime
        if (is_readable('/proc/uptime')) {
            $uptime = (float)file_get_contents('/proc/uptime');
            $stats['uptime'] = [
                'seconds' => (int)$uptime,
                'formatted' => $this->formatUptime((int)$uptime)
            ];
        } else {
            $stats['uptime'] = ['seconds' => 0, 'formatted' => 'N/A'];
        }
        
        // Database size
        $dbPath = __DIR__ . '/../../db/database.sqlite';
        $stats['database'] = [
            'size' => file_exists($dbPath) ? filesize($dbPath) : 0,
            'path' => $dbPath
        ];
        
        // Statystyki aplikacji
        $db = Database::getInstance();
        $stats['app'] = [
            'users' => (int)$db->fetchOne("SELECT COUNT(*) as c FROM users")['c'],
            'devices' => (int)$db->fetchOne("SELECT COUNT(*) as c FROM devices")['c'],
            'playlists' => (int)$db->fetchOne("SELECT COUNT(*) as c FROM playlists")['c'],
            'logs' => (int)$db->fetchOne("SELECT COUNT(*) as c FROM logs")['c'],
        ];
        
        return $stats;
    }
    
    /**
     * Formatuj uptime
     */
    private function formatUptime(int $seconds): string
    {
        $days = floor($seconds / 86400);
        $hours = floor(($seconds % 86400) / 3600);
        $minutes = floor(($seconds % 3600) / 60);
        
        $parts = [];
        if ($days > 0) $parts[] = "{$days}d";
        if ($hours > 0) $parts[] = "{$hours}h";
        if ($minutes > 0) $parts[] = "{$minutes}m";
        
        return implode(' ', $parts) ?: '< 1m';
    }
    
    // ==================== LOGI SYSTEMOWE ====================
    
    /**
     * Przeglądarka logów systemowych
     */
    public function systemLogs(): void
    {
        $logType = get('type', 'app');
        $lines = max(50, min(1000, (int)get('lines', 100)));
        
        $logFiles = $this->getAvailableLogFiles();
        $content = '';
        $selectedFile = '';
        
        if (isset($logFiles[$logType])) {
            $selectedFile = $logFiles[$logType]['path'];
            if (file_exists($selectedFile) && is_readable($selectedFile)) {
                $content = $this->tailFile($selectedFile, $lines);
            }
        }
        
        $this->render('admin/system_logs.tpl', [
            'pageTitle' => 'Logi systemowe',
            'logFiles' => $logFiles,
            'selectedType' => $logType,
            'lines' => $lines,
            'content' => $content,
            'selectedFile' => $selectedFile
        ]);
    }
    
    /**
     * Pobierz dostępne pliki logów
     */
    private function getAvailableLogFiles(): array
    {
        $files = [
            'app' => [
                'name' => 'Logi aplikacji',
                'path' => __DIR__ . '/../../logs/app.log',
                'icon' => 'bi-journal-code'
            ],
            'error' => [
                'name' => 'Błędy PHP',
                'path' => '/var/log/php_errors.log',
                'icon' => 'bi-exclamation-triangle'
            ],
            'apache_error' => [
                'name' => 'Błędy Apache',
                'path' => '/var/log/apache2/error.log',
                'icon' => 'bi-server'
            ],
            'apache_access' => [
                'name' => 'Dostęp Apache',
                'path' => '/var/log/apache2/access.log',
                'icon' => 'bi-arrow-left-right'
            ],
            'nginx_error' => [
                'name' => 'Błędy Nginx',
                'path' => '/var/log/nginx/error.log',
                'icon' => 'bi-server'
            ],
            'nginx_access' => [
                'name' => 'Dostęp Nginx',
                'path' => '/var/log/nginx/access.log',
                'icon' => 'bi-arrow-left-right'
            ],
            'syslog' => [
                'name' => 'Syslog',
                'path' => '/var/log/syslog',
                'icon' => 'bi-terminal'
            ],
        ];
        
        // Sprawdź które pliki istnieją i są dostępne
        foreach ($files as $key => &$file) {
            $file['exists'] = file_exists($file['path']) && is_readable($file['path']);
            if ($file['exists']) {
                $file['size'] = filesize($file['path']);
                $file['modified'] = filemtime($file['path']);
            }
        }
        
        return $files;
    }
    
    /**
     * Pobierz ostatnie N linii z pliku
     */
    private function tailFile(string $filepath, int $lines = 100): string
    {
        if (!file_exists($filepath) || !is_readable($filepath)) {
            return "Nie można odczytać pliku: {$filepath}";
        }
        
        $file = new SplFileObject($filepath, 'r');
        $file->seek(PHP_INT_MAX);
        $totalLines = $file->key();
        
        $startLine = max(0, $totalLines - $lines);
        $file->seek($startLine);
        
        $output = [];
        while (!$file->eof()) {
            $line = $file->fgets();
            if (trim($line) !== '') {
                $output[] = htmlspecialchars($line);
            }
        }
        
        return implode('', $output);
    }
    
    /**
     * Wyczyść logi aplikacji
     */
    public function clearLogs(): void
    {
        if (!$this->verifyCsrf()) {
            return;
        }
        
        $logType = post('type', 'app');
        
        // Tylko logi aplikacji można czyścić z panelu
        if ($logType === 'app') {
            $logFile = __DIR__ . '/../../logs/app.log';
            if (file_exists($logFile)) {
                file_put_contents($logFile, '');
                $this->logger->log('logs_cleared', 'Wyczyszczono logi aplikacji', $this->currentUser['id']);
                
                // Audit log
                $this->auditLog->log(
                    AuditLog::ENTITY_SETTINGS,
                    0,
                    'logs_cleared',
                    null,
                    ['type' => 'app_log_file']
                );
            }
        }
        
        // Wyczyść stare wpisy z bazy
        if ($logType === 'database') {
            $settings = $this->loadSettings();
            $days = $settings['log_retention_days'] ?? 30;
            
            $db = Database::getInstance();
            $db->execute(
                "DELETE FROM logs WHERE created_at < datetime('now', '-' || :days || ' days')",
                ['days' => $days]
            );
            $db->execute(
                "DELETE FROM api_logs WHERE created_at < datetime('now', '-' || :days || ' days')",
                ['days' => $days]
            );
            $db->execute("VACUUM");
            
            $this->logger->log('logs_cleared', "Wyczyszczono logi starsze niż {$days} dni", $this->currentUser['id']);
            
            // Audit log
            $this->auditLog->log(
                AuditLog::ENTITY_SETTINGS,
                0,
                'logs_cleared',
                null,
                ['type' => 'database', 'days_kept' => $days]
            );
        }
        
        $this->redirect('admin/system-logs', 'success', 'Logi zostały wyczyszczone.');
    }
    
    // ==================== HARMONOGRAM ZADAŃ ====================
    
    /**
     * Harmonogram zadań
     */
    public function cron(): void
    {
        $jobs = $this->loadCronJobs();
        $cronStatus = $this->checkCronStatus();
        
        $this->render('admin/cron.tpl', [
            'pageTitle' => 'Harmonogram zadań',
            'jobs' => $jobs,
            'cronStatus' => $cronStatus,
            'availableJobs' => $this->getAvailableJobs()
        ]);
    }
    
    /**
     * Dodaj/edytuj zadanie cron
     */
    public function cronSave(): void
    {
        if (!$this->verifyCsrf()) {
            return;
        }
        
        $jobs = $this->loadCronJobs();
        
        $jobId = post('job_id');
        $job = [
            'id' => $jobId ?: uniqid('job_'),
            'name' => trim(post('name', '')),
            'type' => post('type', ''),
            'schedule' => post('schedule', ''),
            'enabled' => post('enabled') ? true : false,
            'last_run' => null,
            'next_run' => null,
            'created_at' => date('Y-m-d H:i:s')
        ];
        
        if (empty($job['name']) || empty($job['type']) || empty($job['schedule'])) {
            $this->redirect('admin/cron', 'danger', 'Wszystkie pola są wymagane.');
            return;
        }
        
        // Aktualizuj lub dodaj
        $found = false;
        foreach ($jobs as &$existing) {
            if ($existing['id'] === $jobId) {
                $job['created_at'] = $existing['created_at'];
                $job['last_run'] = $existing['last_run'];
                $existing = $job;
                $found = true;
                break;
            }
        }
        
        if (!$found) {
            $jobs[] = $job;
        }
        
        $this->saveCronJobs($jobs);
        $this->logger->log('cron_job_saved', "Zapisano zadanie: {$job['name']}", $this->currentUser['id']);
        
        $this->redirect('admin/cron', 'success', 'Zadanie zostało zapisane.');
    }
    
    /**
     * Usuń zadanie cron
     */
    public function cronDelete(): void
    {
        if (!$this->verifyCsrf()) {
            return;
        }
        
        $jobId = post('job_id');
        $jobs = $this->loadCronJobs();
        
        $jobs = array_filter($jobs, fn($j) => $j['id'] !== $jobId);
        $this->saveCronJobs(array_values($jobs));
        
        $this->logger->log('cron_job_deleted', "Usunięto zadanie: {$jobId}", $this->currentUser['id']);
        $this->redirect('admin/cron', 'success', 'Zadanie zostało usunięte.');
    }
    
    /**
     * Uruchom zadanie ręcznie
     */
    public function cronRun(): void
    {
        if (!$this->verifyCsrf()) {
            return;
        }
        
        $jobId = post('job_id');
        $jobs = $this->loadCronJobs();
        
        foreach ($jobs as &$job) {
            if ($job['id'] === $jobId) {
                $result = $this->executeJob($job);
                $job['last_run'] = date('Y-m-d H:i:s');
                $this->saveCronJobs($jobs);
                
                $this->logger->log('cron_job_run', "Uruchomiono ręcznie: {$job['name']}", $this->currentUser['id']);
                
                $message = $result['success'] 
                    ? "Zadanie wykonane: {$result['message']}" 
                    : "Błąd: {$result['message']}";
                $type = $result['success'] ? 'success' : 'danger';
                
                $this->redirect('admin/cron', $type, $message);
                return;
            }
        }
        
        $this->redirect('admin/cron', 'danger', 'Nie znaleziono zadania.');
    }
    
    /**
     * Wczytaj zadania cron
     */
    private function loadCronJobs(): array
    {
        if (file_exists($this->cronFile)) {
            $data = json_decode(file_get_contents($this->cronFile), true);
            return is_array($data) ? $data : [];
        }
        return [];
    }
    
    /**
     * Zapisz zadania cron
     */
    private function saveCronJobs(array $jobs): bool
    {
        return file_put_contents(
            $this->cronFile, 
            json_encode($jobs, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE)
        ) !== false;
    }
    
    /**
     * Sprawdź status crona systemowego
     */
    private function checkCronStatus(): array
    {
        $status = [
            'installed' => false,
            'running' => false,
            'entry_exists' => false,
            'last_check' => null
        ];
        
        // Sprawdź czy cron jest zainstalowany
        exec('which cron 2>/dev/null', $output, $code);
        $status['installed'] = ($code === 0);
        
        // Sprawdź czy proces cron działa
        exec('pgrep cron 2>/dev/null', $output2, $code2);
        $status['running'] = ($code2 === 0);
        
        // Sprawdź wpis w crontab
        $cronScript = realpath(__DIR__ . '/../../cron.php');
        exec('crontab -l 2>/dev/null', $crontab);
        foreach ($crontab as $line) {
            if (strpos($line, 'cron.php') !== false) {
                $status['entry_exists'] = true;
                break;
            }
        }
        
        return $status;
    }
    
    /**
     * Dostępne typy zadań
     */
    private function getAvailableJobs(): array
    {
        return [
            'cleanup_logs' => [
                'name' => 'Czyszczenie logów',
                'description' => 'Usuwa stare wpisy z logów'
            ],
            'cleanup_sessions' => [
                'name' => 'Czyszczenie sesji',
                'description' => 'Usuwa wygasłe sesje'
            ],
            'backup_database' => [
                'name' => 'Backup bazy danych',
                'description' => 'Tworzy kopię zapasową bazy SQLite'
            ],
            'check_playlists' => [
                'name' => 'Sprawdzenie playlist',
                'description' => 'Weryfikuje dostępność serwerów IPTV'
            ],
            'send_reports' => [
                'name' => 'Wysyłanie raportów',
                'description' => 'Wysyła dzienny raport na email'
            ],
            'optimize_database' => [
                'name' => 'Optymalizacja bazy',
                'description' => 'Wykonuje VACUUM na bazie SQLite'
            ],
        ];
    }
    
    /**
     * Wykonaj zadanie
     */
    private function executeJob(array $job): array
    {
        switch ($job['type']) {
            case 'cleanup_logs':
                return $this->jobCleanupLogs();
            case 'cleanup_sessions':
                return $this->jobCleanupSessions();
            case 'backup_database':
                return $this->jobBackupDatabase();
            case 'optimize_database':
                return $this->jobOptimizeDatabase();
            default:
                return ['success' => false, 'message' => 'Nieznany typ zadania'];
        }
    }
    
    private function jobCleanupLogs(): array
    {
        $settings = $this->loadSettings();
        $days = $settings['log_retention_days'] ?? 30;
        
        $db = Database::getInstance();
        $db->execute(
            "DELETE FROM logs WHERE created_at < datetime('now', '-' || :days || ' days')",
            ['days' => $days]
        );
        $deleted = $db->getLastStatement()->rowCount();
        
        return ['success' => true, 'message' => "Usunięto {$deleted} starych wpisów"];
    }
    
    private function jobCleanupSessions(): array
    {
        $db = Database::getInstance();
        $db->execute("DELETE FROM active_sessions WHERE expires_at < datetime('now')");
        $deleted = $db->getLastStatement()->rowCount();
        
        return ['success' => true, 'message' => "Usunięto {$deleted} wygasłych sesji"];
    }
    
    private function jobBackupDatabase(): array
    {
        $dbPath = __DIR__ . '/../db/playlist.db';
        $backupDir = __DIR__ . '/../../backups';
        
        // Sprawdź czy baza istnieje
        if (!file_exists($dbPath)) {
            $this->logger->log('backup_error', "Baza danych nie istnieje: {$dbPath}", $this->currentUser['id'] ?? null);
            return ['success' => false, 'message' => 'Baza danych nie istnieje: ' . $dbPath];
        }
        
        // Utwórz katalog backupów jeśli nie istnieje
        if (!is_dir($backupDir)) {
            if (!@mkdir($backupDir, 0755, true)) {
                $this->logger->log('backup_error', "Nie można utworzyć katalogu: {$backupDir}", $this->currentUser['id'] ?? null);
                return ['success' => false, 'message' => 'Nie można utworzyć katalogu backupów'];
            }
        }
        
        // Sprawdź czy katalog jest zapisywalny
        if (!is_writable($backupDir)) {
            $this->logger->log('backup_error', "Katalog nie jest zapisywalny: {$backupDir}", $this->currentUser['id'] ?? null);
            return ['success' => false, 'message' => 'Katalog backupów nie jest zapisywalny'];
        }
        
        $backupFile = $backupDir . '/database_' . date('Y-m-d_His') . '.sqlite';
        
        if (@copy($dbPath, $backupFile)) {
            // Usuń stare backupy (zostaw ostatnie 7)
            $backups = glob($backupDir . '/database_*.sqlite');
            usort($backups, fn($a, $b) => filemtime($b) - filemtime($a));
            
            foreach (array_slice($backups, 7) as $old) {
                @unlink($old);
            }
            
            $this->logger->log('backup_created', "Utworzono backup: " . basename($backupFile), $this->currentUser['id'] ?? null);
            return ['success' => true, 'message' => 'Backup utworzony: ' . basename($backupFile)];
        }
        
        $error = error_get_last();
        $errorMsg = $error ? $error['message'] : 'Nieznany błąd';
        $this->logger->log('backup_error', "Błąd kopiowania: {$errorMsg}", $this->currentUser['id'] ?? null);
        return ['success' => false, 'message' => 'Nie udało się utworzyć backupu: ' . $errorMsg];
    }
    
    private function jobOptimizeDatabase(): array
    {
        $db = Database::getInstance();
        $db->execute("VACUUM");
        $db->execute("ANALYZE");
        
        return ['success' => true, 'message' => 'Baza zoptymalizowana'];
    }
    
    // ==================== TRYB KONSERWACJI ====================
    
    /**
     * Przełącz tryb konserwacji
     */
    public function toggleMaintenance(): void
    {
        if (!$this->verifyCsrf()) {
            return;
        }
        
        $settings = $this->loadSettings();
        $oldMode = $settings['maintenance_mode'];
        $settings['maintenance_mode'] = !$settings['maintenance_mode'];
        $this->saveSettings($settings);
        
        $status = $settings['maintenance_mode'] ? 'włączony' : 'wyłączony';
        $this->logger->log('maintenance_toggle', "Tryb konserwacji: {$status}", $this->currentUser['id']);
        
        // Audit log
        $this->auditLog->log(
            AuditLog::ENTITY_SETTINGS,
            0,
            'maintenance_toggle',
            ['maintenance_mode' => $oldMode],
            ['maintenance_mode' => $settings['maintenance_mode']]
        );
        
        $this->redirect('admin/settings', 'success', "Tryb konserwacji {$status}.");
    }
    
    // ==================== AKTUALIZACJE ====================
    
    /**
     * Sprawdź aktualizacje
     */
    public function updates(): void
    {
        $currentVersion = $this->getCurrentVersion();
        $latestVersion = $this->checkLatestVersion();
        
        $this->render('admin/updates.tpl', [
            'pageTitle' => 'Aktualizacje',
            'currentVersion' => $currentVersion,
            'latestVersion' => $latestVersion,
            'updateAvailable' => version_compare($latestVersion['version'] ?? '0', $currentVersion, '>'),
            'changelog' => $latestVersion['changelog'] ?? []
        ]);
    }
    
    /**
     * Pobierz aktualną wersję
     */
    private function getCurrentVersion(): string
    {
        $versionFile = __DIR__ . '/../../VERSION';
        if (file_exists($versionFile)) {
            return trim(file_get_contents($versionFile));
        }
        return '1.0.0';
    }
    
    /**
     * Sprawdź najnowszą wersję (placeholder - w rzeczywistości łączyłby się z serwerem)
     */
    private function checkLatestVersion(): array
    {
        // W rzeczywistej implementacji tutaj byłoby połączenie z serwerem aktualizacji
        return [
            'version' => '1.0.0',
            'release_date' => date('Y-m-d'),
            'changelog' => [
                '1.0.0' => [
                    'Pierwsza wersja systemu',
                    'Zarządzanie użytkownikami',
                    'Zarządzanie urządzeniami i playlistami',
                    'System resellerów',
                    'Panel administracyjny'
                ]
            ]
        ];
    }
    
    // ==================== NARZĘDZIA ====================
    
    /**
     * Strona narzędzi
     */
    public function tools(): void
    {
        $this->render('admin/tools.tpl', [
            'pageTitle' => 'Narzędzia'
        ]);
    }
    
    /**
     * Wymuś VACUUM na bazie
     */
    public function optimizeDb(): void
    {
        if (!$this->verifyCsrf()) {
            return;
        }
        
        $result = $this->jobOptimizeDatabase();
        $this->logger->log('database_optimized', 'Zoptymalizowano bazę danych', $this->currentUser['id']);
        
        $this->redirect('admin/tools', 'success', $result['message']);
    }
    
    /**
     * Utwórz backup
     */
    public function createBackup(): void
    {
        if (!$this->verifyCsrf()) {
            return;
        }
        
        $result = $this->jobBackupDatabase();
        $type = $result['success'] ? 'success' : 'danger';
        
        // Audit log
        if ($result['success']) {
            $this->auditLog->log(
                AuditLog::ENTITY_SETTINGS,
                0,
                'backup_created',
                null,
                ['message' => $result['message']]
            );
        }
        
        $this->redirect('admin/tools', $type, $result['message']);
    }
    
    /**
     * Lista backupów
     */
    public function backups(): void
    {
        $backupDir = __DIR__ . '/../../backups';
        $backups = [];
        
        if (is_dir($backupDir)) {
            foreach (glob($backupDir . '/database_*.sqlite') as $file) {
                $backups[] = [
                    'name' => basename($file),
                    'path' => $file,
                    'size' => filesize($file),
                    'created' => filemtime($file)
                ];
            }
            usort($backups, fn($a, $b) => $b['created'] - $a['created']);
        }
        
        $this->render('admin/backups.tpl', [
            'pageTitle' => 'Kopie zapasowe',
            'backups' => $backups
        ]);
    }
    
    /**
     * Pobierz backup
     */
    public function downloadBackup(): void
    {
        $filename = get('file');
        $backupDir = __DIR__ . '/../../backups';
        $filepath = $backupDir . '/' . basename($filename);
        
        if (!file_exists($filepath) || strpos(realpath($filepath), realpath($backupDir)) !== 0) {
            $this->redirect('admin/backups', 'danger', 'Plik nie istnieje.');
            return;
        }
        
        header('Content-Type: application/octet-stream');
        header('Content-Disposition: attachment; filename="' . basename($filepath) . '"');
        header('Content-Length: ' . filesize($filepath));
        readfile($filepath);
        exit;
    }
    
    /**
     * Usuń backup
     */
    public function deleteBackup(): void
    {
        if (!$this->verifyCsrf()) {
            return;
        }
        
        $filename = post('file');
        $backupDir = __DIR__ . '/../../backups';
        $filepath = $backupDir . '/' . basename($filename);
        
        if (file_exists($filepath) && strpos(realpath($filepath), realpath($backupDir)) === 0) {
            unlink($filepath);
            $this->logger->log('backup_deleted', "Usunięto backup: {$filename}", $this->currentUser['id']);
            
            // Audit log
            $this->auditLog->log(
                AuditLog::ENTITY_SETTINGS,
                0,
                'backup_deleted',
                null,
                ['filename' => $filename]
            );
            
            $this->redirect('admin/backups', 'success', 'Backup został usunięty.');
        } else {
            $this->redirect('admin/backups', 'danger', 'Plik nie istnieje.');
        }
    }
    
    // ==================== PHP INFO ====================
    
    /**
     * Wyświetl phpinfo
     */
    public function phpinfo(): void
    {
        $this->render('admin/phpinfo.tpl', [
            'pageTitle' => 'Informacje PHP'
        ]);
    }
    
    /**
     * Surowe phpinfo (do iframe)
     */
    public function phpinfoRaw(): void
    {
        phpinfo();
        exit;
    }
    
    /**
     * Wyczyść cache Smarty
     */
    public function clearCache(): void
    {
        if (!$this->verifyCsrf()) {
            return;
        }
        
        $cacheDir = __DIR__ . '/../templates_c';
        $count = 0;
        
        if (is_dir($cacheDir)) {
            foreach (glob($cacheDir . '/*') as $file) {
                if (is_file($file) && basename($file) !== '.gitkeep') {
                    unlink($file);
                    $count++;
                }
            }
        }
        
        $this->logger->log('cache_cleared', "Wyczyszczono cache ({$count} plików)", $this->currentUser['id']);
        $this->redirect('admin/tools', 'success', "Wyczyszczono cache ({$count} plików).");
    }
    
    /**
     * Wyloguj wszystkich użytkowników
     */
    public function clearSessions(): void
    {
        if (!$this->verifyCsrf()) {
            return;
        }
        
        // Zachowaj własną sesję
        $currentToken = $_COOKIE[SESSION_NAME] ?? null;
        
        $this->db->execute(
            "DELETE FROM sessions WHERE token != :token",
            ['token' => $currentToken]
        );
        
        $this->db->execute("DELETE FROM active_sessions");
        
        $this->logger->log('sessions_cleared', 'Wylogowano wszystkich użytkowników', $this->currentUser['id']);
        
        // Audit log
        $this->auditLog->log(
            AuditLog::ENTITY_SETTINGS,
            0,
            'sessions_cleared',
            null,
            ['message' => 'All users logged out']
        );
        
        $this->redirect('admin/tools', 'success', 'Wylogowano wszystkich użytkowników.');
    }
    
    /**
     * Wyślij testowy email
     */
    public function testEmail(): void
    {
        if (!$this->verifyCsrf()) {
            return;
        }
        
        $email = filter_var(post('email', ''), FILTER_VALIDATE_EMAIL);
        
        if (!$email) {
            $this->redirect('admin/tools', 'danger', 'Nieprawidłowy adres email.');
            return;
        }
        
        $settings = $this->loadSettings();
        
        // Sprawdź czy SMTP jest skonfigurowany
        if (empty($settings['smtp_host']) || empty($settings['smtp_user'])) {
            $this->redirect('admin/tools', 'danger', 'SMTP nie jest skonfigurowany. Przejdź do Konfiguracja > SMTP.');
            return;
        }
        
        // Próba wysłania emaila
        $subject = 'Test email z ' . ($settings['site_name'] ?? 'IPTV Panel');
        $message = "To jest testowa wiadomość wysłana z panelu IPTV.\n\nData: " . date('Y-m-d H:i:s');
        
        $headers = [
            'From' => ($settings['smtp_from_name'] ?? 'IPTV Panel') . ' <' . ($settings['smtp_from'] ?? $settings['smtp_user']) . '>',
            'Reply-To' => $settings['smtp_from'] ?? $settings['smtp_user'],
            'X-Mailer' => 'PHP/' . phpversion(),
            'Content-Type' => 'text/plain; charset=UTF-8'
        ];
        
        // W prawdziwej implementacji użyj PHPMailer lub podobnej biblioteki
        // Na razie używamy prostego mail() jako placeholder
        $result = @mail($email, $subject, $message, $headers);
        
        if ($result) {
            $this->logger->log('test_email_sent', "Wysłano testowy email do: {$email}", $this->currentUser['id']);
            $this->redirect('admin/tools', 'success', "Testowy email został wysłany na adres: {$email}");
        } else {
            $this->redirect('admin/tools', 'warning', 'Email może nie zostać dostarczony. Funkcja mail() nie gwarantuje dostarczenia. Rozważ instalację PHPMailer.');
        }
    }
}
