<?php
/**
 * File Upload Handler
 * 
 * Handles secure file uploads for expense receipts with WordPress Media Library integration
 * 
 * @package Freelance_Studio
 */

class FS_File_Handler {
    
    /**
     * Allowed file types for receipt uploads
     */
    private static $allowed_mime_types = array(
        'jpg|jpeg|jpe' => 'image/jpeg',
        'png' => 'image/png',
        'gif' => 'image/gif',
        'pdf' => 'application/pdf',
        'doc' => 'application/msword',
        'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'
    );
    
    /**
     * Maximum file size (10MB)
     */
    private static $max_file_size = 10485760;
    
    /**
     * Upload directory name
     */
    private static $upload_dir = 'freelance-studio-receipts';
    
    /**
     * Handle file upload for expense receipt
     * 
     * @param array $file $_FILES array element
     * @param int $expense_id Expense ID
     * @return array|WP_Error Upload result or error
     */
    public static function handle_upload($file, $expense_id) {
        // Security checks
        if (!is_user_logged_in()) {
            return new WP_Error('not_logged_in', __('You must be logged in to upload files.', 'freelance-studio'));
        }
        
        if (!current_user_can('upload_files')) {
            return new WP_Error('insufficient_permissions', __('You do not have permission to upload files.', 'freelance-studio'));
        }
        
        if (empty($file) || empty($file['tmp_name'])) {
            return new WP_Error('no_file', __('No file was uploaded.', 'freelance-studio'));
        }
        
        if ($file['error'] !== UPLOAD_ERR_OK) {
            return new WP_Error('upload_error', __('File upload failed with error code: ', 'freelance-studio') . $file['error']);
        }
        
        // Validate file type
        $file_info = wp_check_filetype_and_ext($file['tmp_name'], $file['name']);
        if (!$file_info['type'] || !self::is_allowed_file_type($file_info['type'])) {
            return new WP_Error('invalid_file_type', __('Invalid file type. Allowed types: JPG, PNG, GIF, PDF, DOC, DOCX.', 'freelance-studio'));
        }
        
        // Validate file size
        if ($file['size'] > self::$max_file_size) {
            return new WP_Error('file_too_large', __('File is too large. Maximum size is 10MB.', 'freelance-studio'));
        }
        
        // Create custom upload directory
        $upload_dir = self::get_upload_dir();
        if (!file_exists($upload_dir['path'])) {
            wp_mkdir_p($upload_dir['path']);
        }
        
        // Generate unique filename
        $filename = self::generate_filename($file['name'], $expense_id);
        $file_path = $upload_dir['path'] . '/' . $filename;
        
        // Move uploaded file
        // phpcs:ignore Generic.PHP.ForbiddenFunctions.Found -- Custom upload path; wp_handle_upload() not suitable here.
        if (!move_uploaded_file($file['tmp_name'], $file_path)) {
            return new WP_Error('move_failed', __('Failed to move uploaded file.', 'freelance-studio'));
        }
        
        // Set proper permissions using WP_Filesystem.
        global $wp_filesystem;
        if ( empty( $wp_filesystem ) ) {
            require_once ABSPATH . 'wp-admin/includes/file.php';
            WP_Filesystem();
        }
        $wp_filesystem->chmod( $file_path, 0644 );
        
        // Create attachment post
        $attachment = array(
            'post_mime_type' => $file_info['type'],
            'post_title' => sanitize_file_name($filename),
            'post_content' => '',
            'post_status' => 'inherit'
        );
        
        $attachment_id = wp_insert_attachment($attachment, $file_path);
        
        if (is_wp_error($attachment_id)) {
            wp_delete_file($file_path);
            return $attachment_id;
        }
        
        // Generate attachment metadata
        require_once(ABSPATH . 'wp-admin/includes/image.php');
        $attachment_data = wp_generate_attachment_metadata($attachment_id, $file_path);
        wp_update_attachment_metadata($attachment_id, $attachment_data);
        
        // Store expense attachment metadata
        update_post_meta($attachment_id, '_fs_expense_id', $expense_id);
        update_post_meta($attachment_id, '_fs_attachment_type', 'expense_receipt');
        
        return array(
            'attachment_id' => $attachment_id,
            'filename' => $filename,
            'file_path' => $file_path,
            'file_url' => $upload_dir['url'] . '/' . $filename,
            'mime_type' => $file_info['type'],
            'file_size' => filesize($file_path),
            'upload_date' => current_time('mysql')
        );
    }
    
    /**
     * Delete receipt file and attachment
     * 
     * @param int $attachment_id Attachment ID
     * @param int $expense_id Expense ID
     * @return bool|WP_Error Success or error
     */
    public static function delete_receipt($attachment_id, $expense_id = null) {
        if (!current_user_can('delete_posts')) {
            return new WP_Error('insufficient_permissions', __('You do not have permission to delete files.', 'freelance-studio'));
        }
        
        $attachment = get_post($attachment_id);
        if (!$attachment || $attachment->post_type !== 'attachment') {
            return new WP_Error('invalid_attachment', __('Invalid attachment ID.', 'freelance-studio'));
        }
        
        // Get expense ID from attachment if not provided
        if (!$expense_id) {
            $expense_id = get_post_meta($attachment_id, '_fs_expense_id', true);
        }
        
        // Get file path before deleting
        $file_path = get_attached_file($attachment_id);
        
        // Delete attachment
        $result = wp_delete_attachment($attachment_id, true);
        
        if ($result) {
            // Delete physical file if it still exists
            if ($file_path && file_exists($file_path)) {
                wp_delete_file($file_path);
            }
            
            // Remove from expense record
            if ($expense_id) {
                global $wpdb;
                $expenses_table = $wpdb->prefix . 'fs_expenses';
                $wpdb->update(
                    $expenses_table,
                    array(
                        'receipt_id' => null,
                        'receipt_url' => null,
                        'updated_at' => current_time('mysql')
                    ),
                    array('id' => $expense_id),
                    array('%d', '%s', '%s'),
                    array('%d')
                );
            }
            
            return true;
        }
        
        return new WP_Error('delete_failed', __('Failed to delete attachment.', 'freelance-studio'));
    }
    
    /**
     * Get receipt information for expense
     * 
     * @param int $expense_id Expense ID
     * @return array|false Receipt info or false if no receipt
     */
    public static function get_receipt_info($expense_id) {
        global $wpdb;
        
        $expenses_table = $wpdb->prefix . 'fs_expenses';
        $expense = $wpdb->get_row($wpdb->prepare(
            "SELECT receipt_id, receipt_url FROM {$expenses_table} WHERE id = %d AND receipt_id IS NOT NULL",
            $expense_id
        ));
        
        if (!$expense || !$expense->receipt_id) {
            return false;
        }
        
        $attachment_id = $expense->receipt_id;
        $file_path = get_attached_file($attachment_id);
        $file_url = $expense->receipt_url ?: wp_get_attachment_url($attachment_id);
        
        return array(
            'attachment_id' => $attachment_id,
            'filename' => basename($file_path),
            'file_path' => $file_path,
            'file_url' => $file_url,
            'mime_type' => get_post_mime_type($attachment_id),
            'file_size' => file_exists($file_path) ? filesize($file_path) : 0
        );
    }
    
    /**
     * Check if file type is allowed
     * 
     * @param string $mime_type MIME type
     * @return bool Is allowed
     */
    private static function is_allowed_file_type($mime_type) {
        $allowed_types = array_values(self::$allowed_mime_types);
        return in_array($mime_type, $allowed_types);
    }
    
    /**
     * Generate unique filename
     * 
     * @param string $original_filename Original filename
     * @param int $expense_id Expense ID
     * @return string Unique filename
     */
    private static function generate_filename($original_filename, $expense_id) {
        $info = pathinfo($original_filename);
        $extension = isset($info['extension']) ? '.' . strtolower($info['extension']) : '';
        $filename = sanitize_file_name($info['filename']);
        
        // Add expense ID and timestamp for uniqueness
        $unique_filename = 'expense-' . $expense_id . '-' . time() . '-' . $filename . $extension;
        
        return $unique_filename;
    }
    
    /**
     * Get custom upload directory
     * 
     * @return array Upload directory info
     */
    private static function get_upload_dir() {
        $uploads = wp_upload_dir();
        
        $subdir = '/' . self::$upload_dir . '/' . gmdate('Y/m');
        $path = $uploads['basedir'] . $subdir;
        $url = $uploads['baseurl'] . $subdir;
        
        return array(
            'path' => $path,
            'url' => $url,
            'subdir' => $subdir
        );
    }
    
    /**
     * Format file size for display
     * 
     * @param int $bytes File size in bytes
     * @return string Formatted file size
     */
    public static function format_file_size($bytes) {
        if ($bytes >= 1048576) {
            return round($bytes / 1048576, 2) . ' MB';
        } elseif ($bytes >= 1024) {
            return round($bytes / 1024, 2) . ' KB';
        } else {
            return $bytes . ' bytes';
        }
    }
    
    /**
     * Check if file is an image
     * 
     * @param string $mime_type MIME type
     * @return bool Is image
     */
    public static function is_image($mime_type) {
        return strpos($mime_type, 'image/') === 0;
    }
}
