<?php
/*******************************************************************************************************************
| Thumbnail Generation Job
| Handles thumbnail generation for videos and images
|*******************************************************************************************************************/

class ThumbnailGenerationJob extends BaseJob
{
    /**
     * Handle thumbnail generation
     * @param array $data Thumbnail generation data
     * @return array Generation result
     */
    public function handle($data)
    {
        $this->validateData($data, ['file_key', 'file_path', 'file_type']);
        
        $fileKey = $data['file_key'];
        $filePath = $data['file_path'];
        $fileType = $data['file_type'];
        $sizes = $data['sizes'] ?? ['small' => [160, 120], 'medium' => [320, 240], 'large' => [640, 480]];
        
        $this->logProgress('Starting thumbnail generation', [
            'file_key' => $fileKey,
            'file_path' => $filePath,
            'file_type' => $fileType,
            'sizes' => array_keys($sizes)
        ]);
        
        try {
            if (!file_exists($filePath)) {
                throw new Exception("Source file not found: {$filePath}");
            }
            
            $thumbnailDir = _FPATH . 'f_data/thumbnails/' . substr($fileKey, 0, 2) . '/' . $fileKey . '/';
            if (!is_dir($thumbnailDir)) {
                mkdir($thumbnailDir, 0755, true);
            }
            
            $results = [];
            
            if ($fileType === 'video') {
                $results = $this->generateVideoThumbnails($filePath, $thumbnailDir, $fileKey, $sizes);
            } elseif (in_array($fileType, ['image', 'photo'])) {
                $results = $this->generateImageThumbnails($filePath, $thumbnailDir, $fileKey, $sizes);
            } else {
                throw new Exception("Unsupported file type for thumbnail generation: {$fileType}");
            }
            
            // Update database with thumbnail information
            $this->updateThumbnailRecord($fileKey, $results);
            
            $this->logProgress('Thumbnail generation completed', [
                'file_key' => $fileKey,
                'thumbnails_generated' => count($results)
            ]);
            
            return [
                'file_key' => $fileKey,
                'thumbnails' => $results,
                'thumbnail_dir' => $thumbnailDir
            ];
            
        } catch (Exception $e) {
            $this->logError('Thumbnail generation failed', [
                'file_key' => $fileKey,
                'error' => $e->getMessage()
            ]);
            
            throw $e;
        }
    }
    
    /**
     * Generate video thumbnails using FFmpeg
     * @param string $videoPath Video file path
     * @param string $outputDir Output directory
     * @param string $fileKey File key
     * @param array $sizes Thumbnail sizes
     * @return array Generation results
     */
    private function generateVideoThumbnails($videoPath, $outputDir, $fileKey, $sizes)
    {
        $ffmpegPath = $this->findFFmpegPath();
        $results = [];
        
        foreach ($sizes as $sizeName => $dimensions) {
            $width = $dimensions[0];
            $height = $dimensions[1];
            $outputFile = $outputDir . $fileKey . "_{$sizeName}.jpg";
            
            // Generate thumbnail at 10% of video duration
            $command = sprintf(
                '%s -i %s -ss 00:00:10 -vframes 1 -vf "scale=%d:%d:force_original_aspect_ratio=decrease,pad=%d:%d:(ow-iw)/2:(oh-ih)/2:color=black" -q:v 2 %s 2>&1',
                escapeshellarg($ffmpegPath),
                escapeshellarg($videoPath),
                $width,
                $height,
                $width,
                $height,
                escapeshellarg($outputFile)
            );
            
            $output = [];
            $returnCode = 0;
            exec($command, $output, $returnCode);
            
            if ($returnCode === 0 && file_exists($outputFile)) {
                $results[$sizeName] = [
                    'success' => true,
                    'file' => $outputFile,
                    'size' => filesize($outputFile),
                    'width' => $width,
                    'height' => $height
                ];
            } else {
                $results[$sizeName] = [
                    'success' => false,
                    'error' => 'FFmpeg thumbnail generation failed',
                    'output' => implode("\n", $output)
                ];
            }
        }
        
        return $results;
    }
    
    /**
     * Generate image thumbnails using GD
     * @param string $imagePath Image file path
     * @param string $outputDir Output directory
     * @param string $fileKey File key
     * @param array $sizes Thumbnail sizes
     * @return array Generation results
     */
    private function generateImageThumbnails($imagePath, $outputDir, $fileKey, $sizes)
    {
        $results = [];
        
        // Get image info
        $imageInfo = getimagesize($imagePath);
        if (!$imageInfo) {
            throw new Exception("Unable to read image information");
        }
        
        $sourceWidth = $imageInfo[0];
        $sourceHeight = $imageInfo[1];
        $mimeType = $imageInfo['mime'];
        
        // Create source image resource
        switch ($mimeType) {
            case 'image/jpeg':
                $sourceImage = imagecreatefromjpeg($imagePath);
                break;
            case 'image/png':
                $sourceImage = imagecreatefrompng($imagePath);
                break;
            case 'image/gif':
                $sourceImage = imagecreatefromgif($imagePath);
                break;
            case 'image/webp':
                $sourceImage = imagecreatefromwebp($imagePath);
                break;
            default:
                throw new Exception("Unsupported image format: {$mimeType}");
        }
        
        if (!$sourceImage) {
            throw new Exception("Failed to create image resource");
        }
        
        foreach ($sizes as $sizeName => $dimensions) {
            $targetWidth = $dimensions[0];
            $targetHeight = $dimensions[1];
            
            // Calculate dimensions maintaining aspect ratio
            $ratio = min($targetWidth / $sourceWidth, $targetHeight / $sourceHeight);
            $newWidth = (int)($sourceWidth * $ratio);
            $newHeight = (int)($sourceHeight * $ratio);
            
            // Create thumbnail
            $thumbnail = imagecreatetruecolor($targetWidth, $targetHeight);
            
            // Handle transparency for PNG and GIF
            if ($mimeType === 'image/png' || $mimeType === 'image/gif') {
                imagealphablending($thumbnail, false);
                imagesavealpha($thumbnail, true);
                $transparent = imagecolorallocatealpha($thumbnail, 255, 255, 255, 127);
                imagefill($thumbnail, 0, 0, $transparent);
            } else {
                // Fill with white background for JPEG
                $white = imagecolorallocate($thumbnail, 255, 255, 255);
                imagefill($thumbnail, 0, 0, $white);
            }
            
            // Calculate centering offsets
            $offsetX = (int)(($targetWidth - $newWidth) / 2);
            $offsetY = (int)(($targetHeight - $newHeight) / 2);
            
            // Resize and copy
            imagecopyresampled(
                $thumbnail, $sourceImage,
                $offsetX, $offsetY, 0, 0,
                $newWidth, $newHeight, $sourceWidth, $sourceHeight
            );
            
            // Save thumbnail
            $outputFile = $outputDir . $fileKey . "_{$sizeName}.jpg";
            
            if (imagejpeg($thumbnail, $outputFile, 85)) {
                $results[$sizeName] = [
                    'success' => true,
                    'file' => $outputFile,
                    'size' => filesize($outputFile),
                    'width' => $targetWidth,
                    'height' => $targetHeight
                ];
            } else {
                $results[$sizeName] = [
                    'success' => false,
                    'error' => 'Failed to save thumbnail'
                ];
            }
            
            imagedestroy($thumbnail);
        }
        
        imagedestroy($sourceImage);
        
        return $results;
    }
    
    /**
     * Update thumbnail record in database
     * @param string $fileKey File key
     * @param array $results Thumbnail generation results
     */
    private function updateThumbnailRecord($fileKey, $results)
    {
        try {
            $db = $this->getDatabase();
            
            $thumbnailData = [];
            foreach ($results as $sizeName => $result) {
                if ($result['success']) {
                    $thumbnailData[$sizeName] = [
                        'file' => basename($result['file']),
                        'width' => $result['width'],
                        'height' => $result['height'],
                        'size' => $result['size']
                    ];
                }
            }
            
            $updateData = [
                'thumbnails_generated' => 1,
                'thumbnail_data' => json_encode($thumbnailData),
                'thumbnail_updated' => date('Y-m-d H:i:s')
            ];
            
            // Update appropriate table based on file type
            $db->doUpdate('db_videofiles', 'file_key', $updateData, $fileKey);
            
            $this->logProgress('Thumbnail record updated', [
                'file_key' => $fileKey,
                'thumbnails' => array_keys($thumbnailData)
            ]);
            
        } catch (Exception $e) {
            $this->logError('Failed to update thumbnail record', [
                'file_key' => $fileKey,
                'error' => $e->getMessage()
            ]);
        }
    }
    
    /**
     * Find FFmpeg path
     * @return string FFmpeg path
     */
    private function findFFmpegPath()
    {
        $paths = ['/usr/bin/ffmpeg', '/usr/local/bin/ffmpeg', 'ffmpeg'];
        
        foreach ($paths as $path) {
            if (shell_exec("which {$path}") || file_exists($path)) {
                return $path;
            }
        }
        
        return 'ffmpeg'; // Fallback to PATH
    }
}