<?php
/*******************************************************************************************************************
| System Cleanup Job
| Handles automated system maintenance and cleanup tasks
|*******************************************************************************************************************/

class CleanupJob extends BaseJob
{
    private $queueManager;
    
    public function __construct()
    {
        parent::__construct();
        $this->queueManager = new VQueueManager();
    }
    
    /**
     * Handle cleanup job
     * @param array $data Cleanup configuration data
     * @return array Cleanup result
     */
    public function handle($data)
    {
        $cleanupType = $data['type'] ?? 'full';
        
        $this->logProgress('Starting system cleanup', [
            'type' => $cleanupType,
            'data' => $data
        ]);
        
        $results = [];
        
        try {
            switch ($cleanupType) {
                case 'full':
                    $results = $this->performFullCleanup($data);
                    break;
                    
                case 'logs':
                    $results['logs'] = $this->cleanupLogs($data);
                    break;
                    
                case 'temp_files':
                    $results['temp_files'] = $this->cleanupTempFiles($data);
                    break;
                    
                case 'old_sessions':
                    $results['sessions'] = $this->cleanupOldSessions($data);
                    break;
                    
                case 'failed_uploads':
                    $results['failed_uploads'] = $this->cleanupFailedUploads($data);
                    break;
                    
                case 'analytics':
                    $results['analytics'] = $this->cleanupOldAnalytics($data);
                    break;
                    
                default:
                    throw new Exception("Unknown cleanup type: {$cleanupType}");
            }
            
            $this->logProgress('System cleanup completed', [
                'type' => $cleanupType,
                'results' => $results
            ]);
            
            return [
                'success' => true,
                'type' => $cleanupType,
                'results' => $results,
                'message' => 'Cleanup completed successfully'
            ];
            
        } catch (Exception $e) {
            $this->logError('System cleanup failed', [
                'type' => $cleanupType,
                'error' => $e->getMessage()
            ]);
            
            throw $e;
        }
    }
    
    /**
     * Perform full system cleanup
     * @param array $data Configuration data
     * @return array Cleanup results
     */
    private function performFullCleanup($data)
    {
        $results = [];
        
        $this->updateProgress(1, 8, 'Cleaning up logs');
        $results['logs'] = $this->cleanupLogs($data);
        
        $this->updateProgress(2, 8, 'Cleaning up temporary files');
        $results['temp_files'] = $this->cleanupTempFiles($data);
        
        $this->updateProgress(3, 8, 'Cleaning up old sessions');
        $results['sessions'] = $this->cleanupOldSessions($data);
        
        $this->updateProgress(4, 8, 'Cleaning up failed uploads');
        $results['failed_uploads'] = $this->cleanupFailedUploads($data);
        
        $this->updateProgress(5, 8, 'Cleaning up old analytics');
        $results['analytics'] = $this->cleanupOldAnalytics($data);
        
        $this->updateProgress(6, 8, 'Cleaning up queue jobs');
        $results['queue_jobs'] = $this->queueManager->cleanupOldJobs(
            $data['queue_retention_hours'] ?? 24
        );
        
        $this->updateProgress(7, 8, 'Cleaning up orphaned files');
        $results['orphaned_files'] = $this->cleanupOrphanedFiles($data);
        
        $this->updateProgress(8, 8, 'Optimizing database');
        $results['database'] = $this->optimizeDatabase($data);
        
        return $results;
    }
    
    /**
     * Cleanup old log files
     * @param array $data Configuration data
     * @return array Cleanup result
     */
    private function cleanupLogs($data)
    {
        $logDir = _FPATH . 'f_data/logs/';
        $retentionDays = $data['log_retention_days'] ?? 30;
        $cutoffTime = time() - ($retentionDays * 24 * 3600);
        
        $deletedFiles = 0;
        $deletedSize = 0;
        
        if (is_dir($logDir)) {
            $files = glob($logDir . '*.log');
            
            foreach ($files as $file) {
                if (filemtime($file) < $cutoffTime) {
                    $size = filesize($file);
                    if (unlink($file)) {
                        $deletedFiles++;
                        $deletedSize += $size;
                    }
                }
            }
        }
        
        return [
            'deleted_files' => $deletedFiles,
            'deleted_size' => $deletedSize,
            'retention_days' => $retentionDays
        ];
    }
    
    /**
     * Cleanup temporary files
     * @param array $data Configuration data
     * @return array Cleanup result
     */
    private function cleanupTempFiles($data)
    {
        $tempDir = _FPATH . 'f_data/temp/';
        $maxAge = $data['temp_file_max_age_hours'] ?? 24;
        $cutoffTime = time() - ($maxAge * 3600);
        
        $deletedFiles = 0;
        $deletedSize = 0;
        
        if (is_dir($tempDir)) {
            $iterator = new RecursiveIteratorIterator(
                new RecursiveDirectoryIterator($tempDir, RecursiveDirectoryIterator::SKIP_DOTS)
            );
            
            foreach ($iterator as $file) {
                if ($file->isFile() && $file->getMTime() < $cutoffTime) {
                    $size = $file->getSize();
                    if (unlink($file->getPathname())) {
                        $deletedFiles++;
                        $deletedSize += $size;
                    }
                }
            }
        }
        
        return [
            'deleted_files' => $deletedFiles,
            'deleted_size' => $deletedSize,
            'max_age_hours' => $maxAge
        ];
    }
    
    /**
     * Cleanup old sessions
     * @param array $data Configuration data
     * @return array Cleanup result
     */
    private function cleanupOldSessions($data)
    {
        $maxAge = $data['session_max_age_hours'] ?? 168; // 7 days
        $cutoffTime = date('Y-m-d H:i:s', time() - ($maxAge * 3600));
        
        try {
            $db = $this->getDatabase();
            
            // Cleanup database sessions if using database session storage
            $query = "DELETE FROM db_sessions WHERE last_activity < ?";
            $db->doQuery($query, [$cutoffTime]);
            $deletedSessions = $db->getAffectedRows();
            
            return [
                'deleted_db_sessions' => $deletedSessions,
                'max_age_hours' => $maxAge
            ];
            
        } catch (Exception $e) {
            $this->logError('Session cleanup failed', [
                'error' => $e->getMessage()
            ]);
            
            return [
                'error' => $e->getMessage(),
                'deleted_db_sessions' => 0
            ];
        }
    }
    
    /**
     * Cleanup failed uploads
     * @param array $data Configuration data
     * @return array Cleanup result
     */
    private function cleanupFailedUploads($data)
    {
        $maxAge = $data['failed_upload_max_age_hours'] ?? 48;
        $cutoffTime = date('Y-m-d H:i:s', time() - ($maxAge * 3600));
        
        try {
            $db = $this->getDatabase();
            
            // Find failed uploads
            $query = "SELECT file_key, usr_id FROM db_videofiles 
                      WHERE processing_status = 'failed' 
                      AND processed_at < ?";
            
            $result = $db->doQuery($query, [$cutoffTime]);
            
            $deletedRecords = 0;
            $deletedFiles = 0;
            $deletedSize = 0;
            
            while ($row = $db->doFetch($result)) {
                // Delete associated files
                $userDir = _FPATH . 'f_data/media/' . $row['usr_id'] . '/';
                $videoFiles = glob($userDir . $row['file_key'] . '*');
                
                foreach ($videoFiles as $file) {
                    if (is_file($file)) {
                        $deletedSize += filesize($file);
                        if (unlink($file)) {
                            $deletedFiles++;
                        }
                    }
                }
                
                // Delete database record
                $deleteQuery = "DELETE FROM db_videofiles WHERE file_key = ?";
                $db->doQuery($deleteQuery, [$row['file_key']]);
                $deletedRecords++;
            }
            
            return [
                'deleted_records' => $deletedRecords,
                'deleted_files' => $deletedFiles,
                'deleted_size' => $deletedSize,
                'max_age_hours' => $maxAge
            ];
            
        } catch (Exception $e) {
            $this->logError('Failed upload cleanup failed', [
                'error' => $e->getMessage()
            ]);
            
            return [
                'error' => $e->getMessage(),
                'deleted_records' => 0,
                'deleted_files' => 0
            ];
        }
    }
    
    /**
     * Cleanup old analytics data
     * @param array $data Configuration data
     * @return array Cleanup result
     */
    private function cleanupOldAnalytics($data)
    {
        $retentionDays = $data['analytics_retention_days'] ?? 90;
        $cutoffTime = date('Y-m-d H:i:s', time() - ($retentionDays * 24 * 3600));
        
        try {
            $db = $this->getDatabase();
            $deletedRecords = 0;
            
            // Cleanup video analytics
            $query = "DELETE FROM db_video_analytics WHERE created_at < ?";
            $db->doQuery($query, [$cutoffTime]);
            $deletedRecords += $db->getAffectedRows();
            
            // Cleanup video views
            $query = "DELETE FROM db_video_views WHERE created_at < ?";
            $db->doQuery($query, [$cutoffTime]);
            $deletedRecords += $db->getAffectedRows();
            
            return [
                'deleted_records' => $deletedRecords,
                'retention_days' => $retentionDays
            ];
            
        } catch (Exception $e) {
            $this->logError('Analytics cleanup failed', [
                'error' => $e->getMessage()
            ]);
            
            return [
                'error' => $e->getMessage(),
                'deleted_records' => 0
            ];
        }
    }
    
    /**
     * Cleanup orphaned files
     * @param array $data Configuration data
     * @return array Cleanup result
     */
    private function cleanupOrphanedFiles($data)
    {
        $mediaDir = _FPATH . 'f_data/media/';
        $deletedFiles = 0;
        $deletedSize = 0;
        
        try {
            if (!is_dir($mediaDir)) {
                return [
                    'deleted_files' => 0,
                    'deleted_size' => 0,
                    'message' => 'Media directory not found'
                ];
            }
            
            // Get all file keys from database
            $db = $this->getDatabase();
            $query = "SELECT file_key FROM db_videofiles 
                      UNION SELECT file_key FROM db_imagefiles 
                      UNION SELECT file_key FROM db_audiofiles 
                      UNION SELECT file_key FROM db_documentfiles";
            
            $result = $db->doQuery($query);
            $validKeys = [];
            
            while ($row = $db->doFetch($result)) {
                $validKeys[] = $row['file_key'];
            }
            
            // Scan media directory for orphaned files
            $iterator = new RecursiveIteratorIterator(
                new RecursiveDirectoryIterator($mediaDir, RecursiveDirectoryIterator::SKIP_DOTS)
            );
            
            foreach ($iterator as $file) {
                if ($file->isFile()) {
                    $filename = $file->getFilename();
                    
                    // Extract file key from filename (assuming format: filekey.extension)
                    $fileKey = pathinfo($filename, PATHINFO_FILENAME);
                    
                    if (!in_array($fileKey, $validKeys)) {
                        $size = $file->getSize();
                        if (unlink($file->getPathname())) {
                            $deletedFiles++;
                            $deletedSize += $size;
                        }
                    }
                }
            }
            
            return [
                'deleted_files' => $deletedFiles,
                'deleted_size' => $deletedSize,
                'scanned_keys' => count($validKeys)
            ];
            
        } catch (Exception $e) {
            $this->logError('Orphaned files cleanup failed', [
                'error' => $e->getMessage()
            ]);
            
            return [
                'error' => $e->getMessage(),
                'deleted_files' => 0,
                'deleted_size' => 0
            ];
        }
    }
    
    /**
     * Optimize database
     * @param array $data Configuration data
     * @return array Optimization result
     */
    private function optimizeDatabase($data)
    {
        try {
            $db = $this->getDatabase();
            $optimizedTables = 0;
            
            // Get all tables
            $query = "SHOW TABLES";
            $result = $db->doQuery($query);
            
            while ($row = $db->doFetch($result)) {
                $table = array_values($row)[0];
                
                // Optimize table
                $optimizeQuery = "OPTIMIZE TABLE `{$table}`";
                $db->doQuery($optimizeQuery);
                $optimizedTables++;
            }
            
            return [
                'optimized_tables' => $optimizedTables,
                'message' => 'Database optimization completed'
            ];
            
        } catch (Exception $e) {
            $this->logError('Database optimization failed', [
                'error' => $e->getMessage()
            ]);
            
            return [
                'error' => $e->getMessage(),
                'optimized_tables' => 0
            ];
        }
    }
}