<?php
declare(strict_types=1);


/**
 * Performance Fix REST Controller
 * Handles auto-fix functionality for Core Web Vitals
 *
 * @package ProRank\Core\RestApi
 */

namespace ProRank\SEO\Core\RestApi;

use WP_REST_Server;
use WP_REST_Request;
use WP_REST_Response;
use WP_Error;

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}


/**
 * Handles performance auto-fix endpoints
 */


class PerformanceFixController extends BaseController {
    
    /**
     * Routes base
     *
     * @var string
     */
    protected string $route_base = 'performance';
    
    /**
     * Register routes
     *
     * @return void
     */
    public function register_routes(): void {
        // Auto-fix endpoint
        register_rest_route($this->namespace, '/' . $this->route_base . '/auto-fix', [
            [
                'methods' => WP_REST_Server::CREATABLE,
                'callback' => [$this, 'auto_fix_issue'],
                'permission_callback' => [$this, 'check_admin_permission'],
                'args' => [
                    'issueId' => [
                        'required' => true,
                        'type' => 'string',
                        'description' => __('Issue identifier', 'prorank-seo'),
                    ],
                ],
            ],
        ]);
        
        // Compress images endpoint
        register_rest_route($this->namespace, '/' . $this->route_base . '/compress-images', [
            [
                'methods' => WP_REST_Server::CREATABLE,
                'callback' => [$this, 'compress_images'],
                'permission_callback' => [$this, 'check_admin_permission'],
                'args' => [
                    'quality' => [
                        'type' => 'integer',
                        'default' => 85,
                        'minimum' => 50,
                        'maximum' => 100,
                    ],
                ],
            ],
        ]);
        
        // Lazy loading endpoint
        register_rest_route($this->namespace, '/' . $this->route_base . '/lazy-loading', [
            [
                'methods' => WP_REST_Server::CREATABLE,
                'callback' => [$this, 'enable_lazy_loading'],
                'permission_callback' => [$this, 'check_admin_permission'],
            ],
        ]);
        
        // Browser caching endpoint
        register_rest_route($this->namespace, '/' . $this->route_base . '/browser-caching', [
            [
                'methods' => WP_REST_Server::CREATABLE,
                'callback' => [$this, 'enable_browser_caching'],
                'permission_callback' => [$this, 'check_admin_permission'],
            ],
        ]);
        
        // Minification endpoints
        register_rest_route($this->namespace, '/' . $this->route_base . '/minify-css', [
            [
                'methods' => WP_REST_Server::CREATABLE,
                'callback' => [$this, 'minify_css'],
                'permission_callback' => [$this, 'check_admin_permission'],
            ],
        ]);
        
        register_rest_route($this->namespace, '/' . $this->route_base . '/minify-js', [
            [
                'methods' => WP_REST_Server::CREATABLE,
                'callback' => [$this, 'minify_js'],
                'permission_callback' => [$this, 'check_admin_permission'],
            ],
        ]);
        
        // Verification endpoint
        register_rest_route($this->namespace, '/' . $this->route_base . '/verify-fix', [
            [
                'methods' => WP_REST_Server::CREATABLE,
                'callback' => [$this, 'verify_fix'],
                'permission_callback' => [$this, 'check_admin_permission'],
            ],
        ]);
        
        // Backup/Rollback endpoints
        register_rest_route($this->namespace, '/' . $this->route_base . '/create-backup', [
            [
                'methods' => WP_REST_Server::CREATABLE,
                'callback' => [$this, 'create_backup'],
                'permission_callback' => [$this, 'check_admin_permission'],
            ],
        ]);
        
        register_rest_route($this->namespace, '/' . $this->route_base . '/rollback', [
            [
                'methods' => WP_REST_Server::CREATABLE,
                'callback' => [$this, 'rollback'],
                'permission_callback' => [$this, 'check_admin_permission'],
                'args' => [
                    'rollbackId' => [
                        'required' => true,
                        'type' => 'string',
                    ],
                ],
            ],
        ]);
    }
    
    /**
     * Auto-fix a performance issue
     */
    public function auto_fix_issue(WP_REST_Request $request) {
        $issue_id = $request->get_param('issueId');
        
        // Map issue to fix function
        $fix_map = [
            'lcp-image' => 'fix_large_images',
            'render-blocking' => 'fix_render_blocking',
            'browser-cache' => 'fix_browser_caching',
            'unused-js' => 'fix_unused_javascript',
            'lazy-loading' => 'fix_lazy_loading',
        ];
        
        if (!isset($fix_map[$issue_id])) {
            return new WP_Error(
                'unknown_issue',
                __('Unknown issue type', 'prorank-seo'),
                ['status' => 400]
            );
        }
        
        $fix_method = $fix_map[$issue_id];
        if (method_exists($this, $fix_method)) {
            $result = $this->$fix_method();
            
            if (is_wp_error($result)) {
                return $result;
            }
            
            return new WP_REST_Response([
                'success' => true,
                'message' => __('Issue fixed successfully', 'prorank-seo'),
                'details' => $result,
            ], 200);
        }
        
        return new WP_Error(
            'fix_not_implemented',
            __('Fix not implemented', 'prorank-seo'),
            ['status' => 501]
        );
    }
    
    /**
     * Compress images
     */
    public function compress_images(WP_REST_Request $request) {
        $quality = $request->get_param('quality');
        
        // Get all image attachments
        $images = get_posts([
            'post_type' => 'attachment',
            'post_mime_type' => 'image',
            'posts_per_page' => -1,
        ]);
        
        $compressed = 0;
        $saved_bytes = 0;
        
        foreach ($images as $image) {
            $file_path = get_attached_file($image->ID);
            if (!$file_path || !file_exists($file_path)) {
                continue;
            }
            
            $original_size = filesize($file_path);
            
            // Use WordPress image editor
            $editor = wp_get_image_editor($file_path);
            if (!is_wp_error($editor)) {
                $editor->set_quality($quality);
                $result = $editor->save($file_path);
                
                if (!is_wp_error($result)) {
                    $new_size = filesize($file_path);
                    $saved_bytes += ($original_size - $new_size);
                    $compressed++;
                    
                    // Regenerate thumbnails
                    wp_update_attachment_metadata(
                        $image->ID,
                        wp_generate_attachment_metadata($image->ID, $file_path)
                    );
                }
            }
        }
        
        return new WP_REST_Response([
            'success' => true,
            'compressed' => $compressed,
            'saved' => $this->format_bytes($saved_bytes),
            'message' => sprintf(
/* translators: %1$: value, %2$: value */
                __('Compressed %1$d images, saved %2$s', 'prorank-seo'),
                $compressed,
                $this->format_bytes($saved_bytes)
            ),
        ], 200);
    }
    
    /**
     * Enable lazy loading
     */
    public function enable_lazy_loading(WP_REST_Request $request) {
        // Update ProRank settings to enable lazy loading
        $settings = get_option('prorank_performance_settings', []);
        $settings['lazy_loading'] = true;
        $settings['lazy_loading_exclude_above_fold'] = true;
        update_option('prorank_performance_settings', $settings);
        
        // Add lazy loading attribute to images
        add_filter('wp_get_attachment_image_attributes', function($attr) {
            $attr['loading'] = 'lazy';
            return $attr;
        });
        
        // Add lazy loading to content images
        add_filter('the_content', function($content) {
            // Add loading="lazy" to img tags that don't have it
            $content = preg_replace(
                '/<img((?!loading=)[^>]*)>/i',
                '<img loading="lazy"$1>',
                $content
            );
            return $content;
        });
        
        return new WP_REST_Response([
            'success' => true,
            'message' => __('Lazy loading enabled for all images', 'prorank-seo'),
        ], 200);
    }
    
    /**
     * Enable browser caching
     */
    public function enable_browser_caching(WP_REST_Request $request) {
        $htaccess_file = $this->get_htaccess_path();
        $htaccess_dir = dirname($htaccess_file);
        $writable = file_exists($htaccess_file) ? wp_is_writable($htaccess_file) : wp_is_writable($htaccess_dir);

        if (!$writable) {
            return new WP_Error(
                'htaccess_not_writable',
                __('.htaccess file is not writable', 'prorank-seo'),
                ['status' => 403]
            );
        }
        
        $cache_rules = '
<IfModule mod_expires.c>
    ExpiresActive On
    
    # Images
    ExpiresByType image/jpeg "access plus 1 year"
    ExpiresByType image/gif "access plus 1 year"
    ExpiresByType image/png "access plus 1 year"
    ExpiresByType image/webp "access plus 1 year"
    ExpiresByType image/svg+xml "access plus 1 year"
    ExpiresByType image/x-icon "access plus 1 year"
    
    # Video
    ExpiresByType video/mp4 "access plus 1 year"
    ExpiresByType video/mpeg "access plus 1 year"
    
    # CSS, JavaScript
    ExpiresByType text/css "access plus 1 month"
    ExpiresByType text/javascript "access plus 1 month"
    ExpiresByType application/javascript "access plus 1 month"
    
    # Others
    ExpiresByType application/pdf "access plus 1 month"
    ExpiresByType application/x-shockwave-flash "access plus 1 month"
</IfModule>

<IfModule mod_headers.c>
    # Cache-Control Headers
    <FilesMatch "\.(ico|jpe?g|png|gif|webp|swf|css|js)$">
        Header set Cache-Control "public, max-age=31536000"
    </FilesMatch>
    
    # Unset ETag
    Header unset ETag
    FileETag None
</IfModule>
';

        if (!function_exists('insert_with_markers')) {
            require_once ABSPATH . 'wp-admin/includes/misc.php';
        }

        $rules = array_filter(array_map('rtrim', explode("\n", trim($cache_rules))));
        $updated = insert_with_markers($htaccess_file, 'ProRank Browser Caching', $rules);

        if ($updated) {
            return new WP_REST_Response([
                'success' => true,
                'message' => __('Browser caching enabled successfully', 'prorank-seo'),
            ], 200);
        }
        
        return new WP_Error(
            'write_failed',
            __('Failed to write .htaccess file', 'prorank-seo'),
            ['status' => 500]
        );
    }
    
    /**
     * Minify CSS
     */
    public function minify_css(WP_REST_Request $request) {
        $settings = get_option('prorank_performance_settings', []);
        $settings['minify_css'] = true;
        $settings['combine_css'] = true;
        update_option('prorank_performance_settings', $settings);
        
        // Hook into WordPress to minify CSS
        add_filter('style_loader_tag', function($tag, $handle, $href, $media) {
            // Skip admin styles
            if (is_admin()) {
                return $tag;
            }
            
            // Get CSS content and minify
            $response = wp_remote_get($href);
            if (!is_wp_error($response)) {
                $css = wp_remote_retrieve_body($response);
                $minified = $this->minify_css_content($css);
                
                // Save minified version
                $upload_dir = wp_upload_dir();
                $filename = 'prorank-min-' . md5($href) . '.css';
                $file_path = $upload_dir['basedir'] . '/prorank-cache/' . $filename;
                $file_url = $upload_dir['baseurl'] . '/prorank-cache/' . $filename;
                
                wp_mkdir_p(dirname($file_path));

                $filesystem = $this->get_filesystem();
                if ($filesystem) {
                    $filesystem->put_contents($file_path, $minified, FS_CHMOD_FILE);
                    // Replace href with minified version
                    $tag = str_replace($href, $file_url, $tag);
                }
            }
            
            return $tag;
        }, 10, 4);
        
        return new WP_REST_Response([
            'success' => true,
            'message' => __('CSS minification enabled', 'prorank-seo'),
        ], 200);
    }
    
    /**
     * Minify JavaScript
     */
    public function minify_js(WP_REST_Request $request) {
        $settings = get_option('prorank_performance_settings', []);
        $settings['minify_js'] = true;
        $settings['defer_js'] = true;
        update_option('prorank_performance_settings', $settings);
        
        // Hook into WordPress to minify and defer JS
        add_filter('script_loader_tag', function($tag, $handle, $src) {
            // Skip admin scripts
            if (is_admin()) {
                return $tag;
            }
            
            // Add defer attribute
            if (strpos($tag, 'defer') === false) {
                $tag = str_replace(' src', ' defer src', $tag);
            }
            
            return $tag;
        }, 10, 3);
        
        return new WP_REST_Response([
            'success' => true,
            'message' => __('JavaScript minification and deferral enabled', 'prorank-seo'),
        ], 200);
    }
    
    /**
     * Verify fix was successful
     */
    public function verify_fix(WP_REST_Request $request) {
        $issue_id = $request->get_param('issueId');
        
        // Re-run performance test for specific metric
        $cwv_service = new \ProRank\SEO\Core\Services\CoreWebVitalsService();
        $current_data = $cwv_service->get_vitals(home_url('/'), 'mobile');
        
        if (is_wp_error($current_data)) {
            return $current_data;
        }
        
        // Compare with previous data
        $previous = get_transient('prorank_cwv_before_fix_' . $issue_id);
        
        $improvement = null;
        if ($previous) {
            // Calculate improvement based on issue type
            $metric_map = [
                'lcp-image' => 'lcp',
                'render-blocking' => 'fcp',
                'unused-js' => 'tbt',
            ];
            
            if (isset($metric_map[$issue_id])) {
                $metric = $metric_map[$issue_id];
                if (isset($previous[$metric]) && isset($current_data[$metric])) {
                    $improvement = [
                        'before' => $previous[$metric],
                        'after' => $current_data[$metric],
                        'metric' => strtoupper($metric),
                    ];
                }
            }
        }
        
        return new WP_REST_Response([
            'success' => true,
            'improvement' => $improvement,
        ], 200);
    }
    
    /**
     * Create backup before applying fix
     */
    public function create_backup(WP_REST_Request $request) {
        $issue_id = $request->get_param('issueId');
        $backup_id = 'backup_' . $issue_id . '_' . time();
        
        $htaccess_content = '';
        $filesystem = $this->get_filesystem();
        $htaccess_path = $this->get_htaccess_path();
        if ($filesystem && $filesystem->exists($htaccess_path)) {
            $htaccess_content = (string) $filesystem->get_contents($htaccess_path);
        }

        // Store current state
        $backup_data = [
            'settings' => [
                'performance' => get_option('prorank_performance_settings'),
                'cwv' => get_option('prorank_cwv_settings'),
            ],
            'htaccess' => $htaccess_content,
            'timestamp' => current_time('mysql'),
        ];
        
        set_transient('prorank_backup_' . $backup_id, $backup_data, DAY_IN_SECONDS);
        
        return new WP_REST_Response([
            'backupId' => $backup_id,
        ], 200);
    }
    
    /**
     * Rollback changes
     */
    public function rollback(WP_REST_Request $request) {
        $rollback_id = $request->get_param('rollbackId');
        $backup_data = get_transient('prorank_backup_' . $rollback_id);
        
        if (!$backup_data) {
            return new WP_Error(
                'backup_not_found',
                __('Backup not found', 'prorank-seo'),
                ['status' => 404]
            );
        }
        
        // Restore settings
        if (isset($backup_data['settings'])) {
            foreach ($backup_data['settings'] as $key => $value) {
                update_option('prorank_' . $key . '_settings', $value);
            }
        }
        
        // Restore .htaccess
        if (isset($backup_data['htaccess']) && $backup_data['htaccess'] !== '') {
            $filesystem = $this->get_filesystem();
            $htaccess_path = $this->get_htaccess_path();
            if ($filesystem) {
                $filesystem->put_contents($htaccess_path, $backup_data['htaccess'], FS_CHMOD_FILE);
            }
        }
        
        // Delete backup
        delete_transient('prorank_backup_' . $rollback_id);
        
        return new WP_REST_Response([
            'success' => true,
            'message' => __('Changes rolled back successfully', 'prorank-seo'),
        ], 200);
    }
    
    /**
     * Helper: Fix large images
     */
    private function fix_large_images() {
        // Compress and optimize images
        return $this->compress_images(new WP_REST_Request());
    }
    
    /**
     * Helper: Fix render-blocking resources
     */
    private function fix_render_blocking() {
        // Defer CSS and JS
        $settings = get_option('prorank_performance_settings', []);
        $settings['defer_css'] = true;
        $settings['defer_js'] = true;
        update_option('prorank_performance_settings', $settings);
        
        return [
            'deferred_css' => true,
            'deferred_js' => true,
        ];
    }
    
    /**
     * Helper: Fix unused JavaScript
     */
    private function fix_unused_javascript() {
        // Implement conditional loading
        $settings = get_option('prorank_performance_settings', []);
        $settings['conditional_loading'] = true;
        $settings['remove_unused_js'] = true;
        update_option('prorank_performance_settings', $settings);
        
        return [
            'conditional_loading' => true,
        ];
    }
    
    /**
     * Helper: Fix browser caching
     */
    private function fix_browser_caching() {
        // Call the existing enable_browser_caching method
        return $this->enable_browser_caching(new WP_REST_Request());
    }
    
    /**
     * Helper: Fix lazy loading
     */
    private function fix_lazy_loading() {
        // Call the existing enable_lazy_loading method
        return $this->enable_lazy_loading(new WP_REST_Request());
    }

    /**
     * Get filesystem handler.
     *
     * @return \WP_Filesystem_Base|null
     */
    private function get_filesystem() {
        global $wp_filesystem;

        if ( ! function_exists( 'WP_Filesystem' ) ) {
            require_once ABSPATH . 'wp-admin/includes/file.php';
        }

        WP_Filesystem();

        return $wp_filesystem ?: null;
    }

    /**
     * Get .htaccess path in the site root.
     *
     * @return string
     */
    private function get_htaccess_path(): string {
        if ( ! function_exists( 'get_home_path' ) ) {
            require_once ABSPATH . 'wp-admin/includes/file.php';
        }

        return trailingslashit( get_home_path() ) . '.htaccess';
    }
    
    /**
     * Helper: Minify CSS content
     */
    private function minify_css_content($css) {
        // Remove comments
        $css = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $css);
        // Remove unnecessary whitespace
        $css = preg_replace('/\s+/', ' ', $css);
        // Remove unnecessary semicolons
        $css = str_replace(';}', '}', $css);
        // Remove space after colons
        $css = str_replace(': ', ':', $css);
        // Remove whitespace around operators
        $css = preg_replace('/\s*([{}|:;,])\s+/', '$1', $css);
        
        return trim($css);
    }
    
    /**
     * Helper: Format bytes
     */
    private function format_bytes($bytes, $precision = 2) {
        $units = ['B', 'KB', 'MB', 'GB'];
        
        for ($i = 0; $bytes > 1024 && $i < count($units) - 1; $i++) {
            $bytes /= 1024;
        }
        
        return round($bytes, $precision) . ' ' . $units[$i];
    }
}
