<?php
// Exit if accessed directly
if (!defined('ABSPATH')) exit;

WP_CLI::add_command('rdg_blocks', 'RDG_Blocks_CLI');

class RDG_Blocks_CLI extends WP_CLI_Command
{
    private $cache_dir;

    public function __construct()
    {
        $this->cache_dir = wp_upload_dir()['basedir'].'/'.RDGBLOCKS_NAME_SLUG.'/';
    }

    public function details()
    {
        WP_CLI::line(sprintf(__('Plugin name: %s'), RDGBLOCKS_NAME));
        WP_CLI::line(sprintf(__('Plugin version: %s'), RDGBLOCKS_VERSION));
    }

    public function status_cache() {
        if (!file_exists($this->cache_dir)) {
            WP_CLI::line(sprintf(__('Directory does not exist: %s'), $this->cache_dir));
    
            return;
        }
    
        $cache_list = scandir($this->cache_dir);

        WP_CLI::line(sprintf(__('Cache files: %s'), count($cache_list)));
    }

    public function clear_cache() {
        if (!file_exists($this->cache_dir)) {
            WP_CLI::line(sprintf(__('Directory does not exist: %s'), $this->cache_dir));
    
            return;
        }
    
        $cache_list = scandir($this->cache_dir);
        $files_deletes = 0;
    
        foreach ($cache_list as $cache_file) {
            if ($cache_file != '.' && $cache_file != '..' && !is_dir($this->cache_dir.$cache_file)) {
                $file_parts = explode('-',$cache_file);
    
                # Validate if the cache file name contains the minimum elements.
                if (is_array($file_parts) && count($file_parts) >= 5) {
                    $extension = $file_parts[count($file_parts) - 1];
                    $block_id = $file_parts[count($file_parts) - 2];
                    $prefix_block = $file_parts[count($file_parts) - 3];
                    $post_id = $file_parts[count($file_parts) - 4];
    
                    # Validate if the cache file name contains the minimum information.
                    if ($extension == 'cache.log' && $prefix_block == 'block' && !empty($block_id) && !empty($post_id)) {
                        $post = get_post($post_id);
    
                        # Validate if the post/page exists
                        if ($post) {
                            # Validate if the post/page is published.
                            if ($post->post_status != 'publish') {
                                $delete = $this->delete_cache($this->cache_dir.$cache_file);

                                if ($delete) {
                                    $files_deletes++;

                                    error_log(print_r([
                                        'message' => 'The cache file refers to an unpublished post.',
                                        'cache_file' => $this->cache_dir.$cache_file,
                                    ], true));
                                }

                                continue;
                            }
    
                            # Validate if the post/page still contains a block associated with the cache file.
                            if (!str_contains($post->post_content, $block_id)) {
                                $delete = $this->delete_cache($this->cache_dir.$cache_file);

                                if ($delete) {
                                    $files_deletes++;

                                    error_log(print_r([
                                        'message' => 'The cache file is no longer used by a block in the post.',
                                        'cache_file' => $this->cache_dir.$cache_file,
                                    ], true));
                                }

                                continue;
                            }
                        } else {
                            $delete = $this->delete_cache($this->cache_dir.$cache_file);

                            if ($delete) {
                                $files_deletes++;

                                error_log(print_r([
                                    'message' => 'The cache file refers to a post that does not exist.',
                                    'cache_file' => $this->cache_dir.$cache_file,
                                ], true));
                            }
                        }
                    } else {
                        $delete = $this->delete_cache($this->cache_dir.$cache_file);

                        if ($delete) {
                            $files_deletes++;

                            error_log(print_r([
                                'message' => 'Invalid cache name format.',
                                'cache_file' => $this->cache_dir.$cache_file,
                            ], true));
                        }
                    }
                } else {
                    $delete = $this->delete_cache($this->cache_dir.$cache_file);

                    if ($delete) {
                        $files_deletes++;

                        error_log(print_r([
                            'message' => 'Invalid cache name format.',
                            'cache_file' => $this->cache_dir.$cache_file,
                        ], true));
                    }
                }
            }
        }

        error_log(sprintf(__('RDG_Blocks_CLI: Deleted cache files: %s'), $files_deletes));

        WP_CLI::line(sprintf(__('Deleted cache files: %s'), $files_deletes));
    }

    public function delete_all() {
        if (!file_exists($this->cache_dir)) {
            WP_CLI::line(sprintf(__('Directory does not exist: %s'), $this->cache_dir));
    
            return;
        }
    
        $cache_list = scandir($this->cache_dir);
        $files_deletes = 0;
    
        foreach ($cache_list as $cache_file) {
            if ($cache_file != '.' && $cache_file != '..' && !is_dir($this->cache_dir.$cache_file)) {
                $delete = $this->delete_cache($this->cache_dir.$cache_file);
                if ($delete) $files_deletes++;
            }
        }

        WP_CLI::line(sprintf(__('Deleted cache files: %s'), $files_deletes));
    }

    private function delete_cache($cache_file) {
        try {
            unlink($cache_file);

            return true;
        } catch (\Exception $exception) {
            error_log(print_r([
                'message' => 'Error trying to clear cache file.',
                'exception' => $exception->getMessage(),
                'cache_file' => $cache_file,
            ], true));
        }

        return false;
    }

    public function images_optimize() {
        try {
            $reducer_queue = [];
            $helpers = New Rdg_Blocks_Helpers;

            if (!$helpers->is_install_shortpixel()) {
                error_log(print_r([
                    'mesage' => 'The shortpixel plugin must be installed and active.',
                    'plugin_name' => 'shortpixel-image-optimiser/wp-shortpixel.php',
                    'active_plugins' => apply_filters('active_plugins', get_option('active_plugins')),
                ], true));
    
                WP_CLI::line(sprintf(__('RDG Blocks: The shortpixel plugin must be installed and active.')));

                return;
            }
    
            if (!$helpers->is_active_shortpixel()) {
                error_log('RDG Blocks: Shortpixel plugin disabled.');
                WP_CLI::line(sprintf(__('RDG Blocks: Shortpixel plugin disabled.')));

                return;
            }
    
            if (empty($helpers->get_key_shortpixel())) {
                error_log('RDG Blocks: You must set the api key to the shortpixel plugin.');
                WP_CLI::line(sprintf(__('RDG Blocks: You must set the api key to the shortpixel plugin.')));

                return;
            }

            $max_chunk = $helpers->get_max_chunks_shortpixel();
            $key_queue = $helpers->get_redis_key_queue_shortpixel();
            $helpers->set_redis_group(REDIS_GROUP_BLOCKS);
            $reducer_queue = unserialize($helpers->get_redis($key_queue));
    
            if (is_array($reducer_queue) && count($reducer_queue) > 0) {
                $attributes = [
                    'url' => $helpers->get_url_shortpixel(),
                    'key' => $helpers->get_key_shortpixel(),
                    'resize_width' => (!empty(get_option('wp-short-pixel-resize-width'))) ? get_option('wp-short-pixel-resize-width') : 400,
                    'resize_height' => (!empty(get_option('wp-short-pixel-resize-height'))) ? get_option('wp-short-pixel-resize-height') : 400,
                ];
    
                $images = 0;
                $errors = 0;
                $chunks = array_chunk($reducer_queue, $max_chunk);
    
                foreach($chunks as $chunk) {
                    $update_cache = false;
                    list($reducer_images, $errors) = $this->shortPixelReducer($chunk, $attributes);
    
                    if ($reducer_images !== null) {
                        foreach ($reducer_images as $new_image) {
                            $image_response = $helpers->create_image_reducer($new_image);
        
                            if ($image_response) {
                                if (($key = array_search($new_image['original_url'], $reducer_queue)) !== false) {
                                    unset($reducer_queue[$key]);
                                }
        
                                $update_cache = true;
                                $images++;
                            }
                        }
        
                        if ($update_cache) {
                            $helpers->set_redis($key_queue, serialize($reducer_queue));
                        }
                    }
                }
    
                if ($images > 0) {
                    error_log(print_r($images.' new images were optimized.', true));
                    WP_CLI::line(sprintf(__($images.' new images were optimized.')));
                }

                if ($errors > 0) {
                    WP_CLI::line(sprintf(__($errors.' errors when optimizing the images.')));
                }
            } else {
                error_log(print_r('RDG Blocks: No images to optimize.', true));
                WP_CLI::line(sprintf(__('RDG Blocks: No images to optimize.')));
            }
        } catch (\Exception $exception) {
            error_log(print_r([
                'is_install_shortpixel' => $helpers->is_install_shortpixel(),
                'is_active_shortpixel' => $helpers->is_active_shortpixel(),
                'key_queue' => (isset($key_queue)) ? $key_queue : '',
                'reducer_queue' => $reducer_queue,
                'exception' => $exception->getMessage(),
            ], true));

            WP_CLI::line(sprintf(__('RDG Blocks: An error occurred while trying to execute the command.')));
        }
    }

    public function shortPixelReducer($array_images, $attributes) {
        try {
            $errors = 0;
            $reducer_images = [];
            $helpers = New Rdg_Blocks_Helpers;

            $params = json_encode([
                'plugin_version' => 'rdg10',
                'key' => $attributes['key'],
                'lossy' => 1,
                'resize' => 1,
                'resize_width' => $attributes['resize_width'],
                'resize_height' => $attributes['resize_height'],
                'cmyk2rgb' => 1, 
                'keep_exif'=> 0, 
                'convertto'=> '+webp', 
                'refresh'=> 0, 
                'wait'=> 30,
                'urllist' => array_map('rawurlencode', $array_images)
            ]);
    
            $context = stream_context_create([
                'http' => [
                    'method' => 'POST',
                    'header' => "Content-Type: application/json\r\n" . "Accept: application/json\r\n" . "Content-Length: " . strlen($params) ,
                    'content' => $params
                ]
            ]);

            $responses = json_decode(file_get_contents($attributes['url'], false, $context), true);
            
            foreach ($responses as $response) {
                $tem_array = [];

                if (isset($response['Status']['Code']) && $response['Status']['Code'] == 2) {
                    $tem_array = $helpers->get_image_name($response['OriginalURL']);
                    $tem_array['reducer_url'] = $response['WebPLossyURL'];
                    $tem_array['original_url'] = $response['OriginalURL'];
                    $reducer_images[] = $tem_array;
                } else {
                    $errors++;
                    error_log(print_r([
                        'message' => 'RDG_Blocks_CLI:shortPixelReducer',
                        'response' => $response,
                    ], true));
                }
            }
        } catch (\Exception $exception) {
            unset($attributes['key']);
            error_log(print_r([
                'message' => $exception->getMessage(),
                'array_images' => $array_images,
                'attributes' => $attributes,
            ], true));

            WP_CLI::line(sprintf(__('RDG Blocks: An error occurred while trying to convert the images.')));
        }

        $images = (is_array($reducer_images) && count($reducer_images) > 0) ? $reducer_images : null;
        return [$images, $errors];
    }
}
