<?php
class SecureFileHandler {
    private $maxFileSize;
    private $allowedImageTypes;
    private $allowedDocumentTypes;
    private $uploadPath;
    
    public function __construct() {
        $this->maxFileSize = $_ENV['MAX_FILE_SIZE'] ?? 5242880; // 5MB default
        $this->allowedImageTypes = explode(',', $_ENV['ALLOWED_IMAGE_TYPES'] ?? 'jpg,jpeg,png');
        $this->allowedDocumentTypes = explode(',', $_ENV['ALLOWED_DOCUMENT_TYPES'] ?? 'pdf,doc,docx');
        $this->uploadPath = UPLOAD_PATH;
    }
    
    public function validateFile($file, $type = 'document') {
        $errors = [];
        
        // Check if file was uploaded
        if (!isset($file['tmp_name']) || empty($file['tmp_name'])) {
            $errors[] = 'No file uploaded';
            return $errors;
        }
        
        // Check for upload errors
        if ($file['error'] !== UPLOAD_ERR_OK) {
            $errors[] = 'File upload error: ' . $this->getUploadErrorMessage($file['error']);
            return $errors;
        }
        
        // Check file size
        if ($file['size'] > $this->maxFileSize) {
            $errors[] = 'File size exceeds maximum allowed size of ' . ($this->maxFileSize / 1024 / 1024) . 'MB';
        }
        
        // Validate file extension
        $extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
        $allowedTypes = ($type === 'image') ? $this->allowedImageTypes : $this->allowedDocumentTypes;
        
        if (!in_array($extension, $allowedTypes)) {
            $errors[] = 'Invalid file type. Allowed types: ' . implode(', ', $allowedTypes);
        }
        
        // Validate MIME type
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        $mimeType = finfo_file($finfo, $file['tmp_name']);
        finfo_close($finfo);
        
        $allowedMimes = $this->getAllowedMimeTypes($type);
        if (!in_array($mimeType, $allowedMimes)) {
            $errors[] = 'Invalid file MIME type';
        }
        
        // Additional security checks
        if ($type === 'image') {
            $imageInfo = getimagesize($file['tmp_name']);
            if ($imageInfo === false) {
                $errors[] = 'Invalid image file';
            }
        }
        
        return $errors;
    }
    
    public function secureUpload($file, $directory, $type = 'document') {
        $errors = $this->validateFile($file, $type);
        
        if (!empty($errors)) {
            return ['success' => false, 'errors' => $errors];
        }
        
        // Generate secure filename
        $extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
        $filename = uniqid() . '.' . $extension;
        
        // Ensure upload directory exists with secure permissions
        $uploadDir = $this->uploadPath . $directory . '/';
        if (!is_dir($uploadDir)) {
            mkdir($uploadDir, 0755, true);
        }
        
        $uploadPath = $uploadDir . $filename;
        
        // Move uploaded file
        if (move_uploaded_file($file['tmp_name'], $uploadPath)) {
            // Set secure file permissions
            chmod($uploadPath, 0644);
            return ['success' => true, 'filename' => $filename];
        }
        
        return ['success' => false, 'errors' => ['Failed to upload file']];
    }
    
    private function getAllowedMimeTypes($type) {
        if ($type === 'image') {
            return [
                'image/jpeg',
                'image/png',
                'image/gif'
            ];
        }
        
        return [
            'application/pdf',
            'application/msword',
            'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
        ];
    }
    
    private function getUploadErrorMessage($errorCode) {
        switch ($errorCode) {
            case UPLOAD_ERR_INI_SIZE:
            case UPLOAD_ERR_FORM_SIZE:
                return 'File too large';
            case UPLOAD_ERR_PARTIAL:
                return 'File upload incomplete';
            case UPLOAD_ERR_NO_FILE:
                return 'No file uploaded';
            case UPLOAD_ERR_NO_TMP_DIR:
                return 'Missing temporary folder';
            case UPLOAD_ERR_CANT_WRITE:
                return 'Failed to write file';
            case UPLOAD_ERR_EXTENSION:
                return 'File upload stopped by extension';
            default:
                return 'Unknown upload error';
        }
    }
    
    public function deleteFile($filename, $directory) {
        $filePath = $this->uploadPath . $directory . '/' . $filename;
        if (file_exists($filePath)) {
            return unlink($filePath);
        }
        return false;
    }
}
?>