<?php
/**
 * Upload Handler
 * Manages file uploads for cases, profiles, and temporary files
 */

class UploadHandler {
    private $uploadDir;
    private $maxFileSize = 5242880; // 5MB
    private $allowedTypes = [
        'image/jpeg', 'image/png', 'image/gif', 'image/webp',
        'application/pdf',
        'application/msword',
        'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
    ];
    
    public function __construct() {
        $this->uploadDir = __DIR__ . '/../assets/uploads/';
        $this->ensureDirectories();
    }
    
    /**
     * Ensure all upload directories exist
     */
    private function ensureDirectories() {
        $dirs = ['cases', 'profiles', 'temp'];
        foreach ($dirs as $dir) {
            $path = $this->uploadDir . $dir;
            if (!is_dir($path)) {
                mkdir($path, 0755, true);
            }
        }
    }
    
    /**
     * Upload file to specified directory
     * @param array $file $_FILES array element
     * @param string $type 'cases', 'profiles', or 'temp'
     * @param int $caseId Optional case ID for case attachments
     * @return array
     */
    public function upload($file, $type = 'temp', $caseId = null) {
        if ($file['error'] !== UPLOAD_ERR_OK) {
            return [
                'success' => false,
                'error' => $this->getUploadErrorMessage($file['error'])
            ];
        }
        
        // Validate file size
        if ($file['size'] > $this->maxFileSize) {
            return [
                'success' => false,
                'error' => 'File too large. Maximum size: ' . ($this->maxFileSize / 1024 / 1024) . 'MB'
            ];
        }
        
        // Validate file type
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $mimeType = finfo_file($finfo, $file['tmp_name']);
        finfo_close($finfo);
        
        if (!in_array($mimeType, $this->allowedTypes)) {
            return [
                'success' => false,
                'error' => 'Invalid file type. Allowed: ' . implode(', ', $this->allowedTypes)
            ];
        }
        
        // Generate unique filename
        $extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
        $filename = time() . '_' . bin2hex(random_bytes(8)) . '.' . $extension;
        
        // Determine target directory
        if ($type == 'cases' && $caseId) {
            $targetDir = $this->uploadDir . 'cases/' . $caseId . '/';
            if (!is_dir($targetDir)) {
                mkdir($targetDir, 0755, true);
            }
        } else {
            $targetDir = $this->uploadDir . $type . '/';
        }
        
        $filepath = $targetDir . $filename;
        
        if (move_uploaded_file($file['tmp_name'], $filepath)) {
            return [
                'success' => true,
                'filename' => $filename,
                'original_name' => $file['name'],
                'size' => $file['size'],
                'mime_type' => $mimeType,
                'path' => str_replace(__DIR__ . '/../', '', $filepath),
                'full_path' => $filepath
            ];
        }
        
        return [
            'success' => false,
            'error' => 'Failed to save uploaded file'
        ];
    }
    
    /**
     * Delete file
     * @param string $filepath
     * @return bool
     */
    public function delete($filepath) {
        $fullPath = __DIR__ . '/../' . $filepath;
        if (file_exists($fullPath) && is_file($fullPath)) {
            return unlink($fullPath);
        }
        return false;
    }
    
    /**
     * Get file URL
     * @param string $filepath
     * @return string
     */
    public function getUrl($filepath) {
        return APP_URL . '/' . $filepath;
    }
    
    /**
     * Get file size human readable
     * @param string $filepath
     * @return string
     */
    public function getFileSize($filepath) {
        $fullPath = __DIR__ . '/../' . $filepath;
        if (file_exists($fullPath)) {
            return $this->formatSize(filesize($fullPath));
        }
        return '0 B';
    }
    
    /**
     * Get file icon based on mime type
     * @param string $mimeType
     * @return string
     */
    public function getFileIcon($mimeType) {
        $icons = [
            'image/' => 'fa-file-image',
            'application/pdf' => 'fa-file-pdf',
            'application/msword' => 'fa-file-word',
            'application/vnd.openxmlformats-officedocument' => 'fa-file-word',
            'text/plain' => 'fa-file-alt'
        ];
        
        foreach ($icons as $pattern => $icon) {
            if (strpos($mimeType, $pattern) === 0) {
                return $icon;
            }
        }
        
        return 'fa-file';
    }
    
    /**
     * Get upload error message
     * @param int $errorCode
     * @return string
     */
    private function getUploadErrorMessage($errorCode) {
        switch ($errorCode) {
            case UPLOAD_ERR_INI_SIZE:
                return 'File exceeds upload_max_filesize directive';
            case UPLOAD_ERR_FORM_SIZE:
                return 'File exceeds MAX_FILE_SIZE directive';
            case UPLOAD_ERR_PARTIAL:
                return 'File was only partially uploaded';
            case UPLOAD_ERR_NO_FILE:
                return 'No file was uploaded';
            case UPLOAD_ERR_NO_TMP_DIR:
                return 'Missing temporary folder';
            case UPLOAD_ERR_CANT_WRITE:
                return 'Failed to write file to disk';
            case UPLOAD_ERR_EXTENSION:
                return 'File upload stopped by extension';
            default:
                return 'Unknown upload error';
        }
    }
    
    /**
     * Format file size
     * @param int $bytes
     * @return string
     */
    private function formatSize($bytes) {
        if ($bytes >= 1073741824) {
            return round($bytes / 1073741824, 2) . ' GB';
        } elseif ($bytes >= 1048576) {
            return round($bytes / 1048576, 2) . ' MB';
        } elseif ($bytes >= 1024) {
            return round($bytes / 1024, 2) . ' KB';
        }
        return $bytes . ' B';
    }
    
    /**
     * Get upload statistics
     * @return array
     */
    public function getStats() {
        $stats = [];
        $dirs = ['cases', 'profiles', 'temp'];
        
        foreach ($dirs as $dir) {
            $path = $this->uploadDir . $dir;
            $totalSize = 0;
            $fileCount = 0;
            
            if (is_dir($path)) {
                $files = new RecursiveIteratorIterator(
                    new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS)
                );
                foreach ($files as $file) {
                    if ($file->isFile()) {
                        $fileCount++;
                        $totalSize += $file->getSize();
                    }
                }
            }
            
            $stats[$dir] = [
                'file_count' => $fileCount,
                'total_size' => $totalSize,
                'total_size_formatted' => $this->formatSize($totalSize)
            ];
        }
        
        return $stats;
    }
    
    /**
     * Clean temporary files older than specified hours
     * @param int $hours
     * @return int
     */
    public function cleanTemp($hours = 24) {
        $count = 0;
        $tempDir = $this->uploadDir . 'temp/';
        $expiryTime = time() - ($hours * 3600);
        
        if (is_dir($tempDir)) {
            $files = glob($tempDir . '*');
            foreach ($files as $file) {
                if (is_file($file) && filemtime($file) < $expiryTime) {
                    if (unlink($file)) {
                        $count++;
                    }
                }
            }
        }
        
        return $count;
    }
}

// Global upload handler instance
$uploadHandler = null;

function getUploadHandler() {
    global $uploadHandler;
    if ($uploadHandler === null) {
        $uploadHandler = new UploadHandler();
    }
    return $uploadHandler;
}