<?php
defined('ABSPATH') or die('Direct access not allowed');

class CodeEditor_ZipArchive {
    public function __construct() {
        add_action('wp_ajax_code_editor_compress', [$this, 'handle_compress_request']);
        add_action('wp_ajax_code_editor_extract', [$this, 'handle_extract_request']);
    }

    public function handle_compress_request() {
        check_ajax_referer('code_editor_nonce', 'security');
        
        if (!current_user_can('manage_options')) {
            wp_send_json_error('Unauthorized', 403);
        }

        $files = isset($_POST['files']) ? $_POST['files'] : [];
        $destination = isset($_POST['destination']) ? sanitize_text_field($_POST['destination']) : '';
        
        if (empty($files) || empty($destination)) {
            wp_send_json_error('Invalid parameters', 400);
        }

        $result = $this->compress_files($files, $destination);
        wp_send_json_success($result);
    }

    public function handle_extract_request() {
        check_ajax_referer('code_editor_nonce', 'security');
        
        if (!current_user_can('manage_options')) {
            wp_send_json_error('Unauthorized', 403);
        }

        $archive = isset($_POST['archive']) ? sanitize_text_field($_POST['archive']) : '';
        $destination = isset($_POST['destination']) ? sanitize_text_field($_POST['destination']) : '';
        
        if (empty($archive) || empty($destination)) {
            wp_send_json_error('Invalid parameters', 400);
        }

        $result = $this->extract_archive($archive, $destination);
        wp_send_json_success($result);
    }

    private function compress_files($files, $destination) {
        $base_path = ABSPATH;
        $full_destination = realpath($base_path . $destination);
        
        if (strpos($full_destination, $base_path) !== 0) {
            return ['success' => false, 'message' => 'Invalid destination path'];
        }

        $zip = new ZipArchive();
        if ($zip->open($full_destination, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== TRUE) {
            return ['success' => false, 'message' => 'Failed to create zip file'];
        }

        foreach ($files as $file) {
            $full_path = realpath($base_path . $file);
            if (strpos($full_path, $base_path) === 0 && file_exists($full_path)) {
                if (is_dir($full_path)) {
                    $this->add_directory_to_zip($zip, $full_path, dirname($full_path));
                } else {
                    $zip->addFile($full_path, basename($full_path));
                }
            }
        }

        $zip->close();
        return ['success' => true, 'message' => 'Files compressed successfully'];
    }

    private function add_directory_to_zip($zip, $directory, $base_path) {
        $files = new RecursiveIteratorIterator(
            new RecursiveDirectoryIterator($directory),
            RecursiveIteratorIterator::LEAVES_ONLY
        );

        foreach ($files as $name => $file) {
            if (!$file->isDir()) {
                $file_path = $file->getRealPath();
                $relative_path = substr($file_path, strlen($base_path) + 1);
                $zip->addFile($file_path, $relative_path);
            }
        }
    }

    private function extract_archive($archive, $destination) {
        $base_path = ABSPATH;
        $full_archive = realpath($base_path . $archive);
        $full_destination = realpath($base_path . $destination);
        
        if (strpos($full_archive, $base_path) !== 0 || 
            strpos($full_destination, $base_path) !== 0) {
            return ['success' => false, 'message' => 'Invalid paths'];
        }

        $zip = new ZipArchive();
        if ($zip->open($full_archive) !== TRUE) {
            return ['success' => false, 'message' => 'Failed to open zip file'];
        }

        if (!is_dir($full_destination)) {
            mkdir($full_destination, 0755, true);
        }

        $zip->extractTo($full_destination);
        $zip->close();
        return ['success' => true, 'message' => 'Files extracted successfully'];
    }
}

new CodeEditor_ZipArchive();