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

if (!rdgblocksIsBedrock()) {
    if (!class_exists('WP_CLI')) {
        require_once RDGBLOCKS_PLUGIN_VENDOR_DIR . 'wp-cli/wp-cli/php/class-wp-cli.php';
    }

    if (!class_exists('WP_CLI_Command')) {
        require_once RDGBLOCKS_PLUGIN_VENDOR_DIR . 'wp-cli/wp-cli/php/class-wp-cli-command.php';
    }
}

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;
        }

        $helpers = New Rdg_Blocks_Helpers;
        $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);
                if (!is_array($file_parts)) continue;

                # Validate if the cache file name contains the minimum elements.
                if (count($file_parts) < 5) {
                    $delete = $this->delete_cache($this->cache_dir.$cache_file);

                    if ($delete) {
                        $files_deletes++;

                        continue;
                    }
                }

                $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];
                $suffix_cache = str_replace('-', '', $helpers->getCacheSuffix());

                // Extension and essential parts of the cache are validated.
                if ($extension != $suffix_cache || $prefix_block != 'block' || empty($block_id) || empty($post_id)) {
                    $delete = $this->delete_cache($this->cache_dir.$cache_file);

                    if ($delete) {
                        $files_deletes++;

                        continue;
                    }
                }

                $post = get_post($post_id);

                # Validate if the post/page exists
                if (empty($post)) {
                    $delete = $this->delete_cache($this->cache_dir.$cache_file);

                    if ($delete) {
                        $files_deletes++;

                        continue;
                    }
                }

                # 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++;

                        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++;

                        continue;
                    }
                }
            }
        }

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

        WP_CLI::line(sprintf(__('RDG_Blocks_CLI: 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->isInstallShortpixel()) {
                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->isActiveShortpixel()) {
                error_log('RDG Blocks: Shortpixel plugin disabled.');
                WP_CLI::line(sprintf(__('RDG Blocks: Shortpixel plugin disabled.')));

                return;
            }
    
            if (empty($helpers->getKeyShortpixel())) {
                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->getMaxChunksShortpixel();
            $key_queue = $helpers->getRedisKeyQueueShortpixel();
            $helpers->setRedisGroup(REDIS_GROUP_BLOCKS);
            $reducer_queue = unserialize($helpers->getRedis($key_queue));
    
            if (is_array($reducer_queue) && count($reducer_queue) > 0) {
                $attributes = [
                    'url' => $helpers->getUrlShortpixel(),
                    'key' => $helpers->getKeyShortpixel(),
                    '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->createImageReducer($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->setRedis($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->isInstallShortpixel(),
                'is_active_shortpixel' => $helpers->isActiveShortpixel(),
                '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->getImageName($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];
    }

    public function regenerate_cache($force = false) {
        if (!$force && get_option('rdg_blocks_cache_status') != 1) {
            error_log('RDG Blocks / regenerate_cache: Cron Jobs disabled.');

            return;
        }

        global $rdgb;
        $rdgb = (!empty($rdgb)) ? $rdgb : Rdg_Blocks::instance();
        $cache = New Rdg_Blocks_Cache;
        
        $connect = $cache->getRedisConnect();
        if (!$connect) {
            error_log('RDG Blocks / regenerate_cache: Redis connection not established.');
            
            return;
        }

        $cache_list = $cache->getCacheList();
        if (!is_array($cache_list) || count($cache_list) == 0) {
            error_log('RDG Blocks / regenerate_cache: No cache files found.');

            return;
        }

        $count_cahe_regenerate = 0;
        $count_cahe_analyze = count($cache_list);

        foreach ($cache_list as $block_name) {
            $data_block_json = $cache->getCacheBlock($block_name);
            if (empty($data_block_json)) {
                // CRITICAL FIX: Try to regenerate empty cache instead of just marking it
                error_log(sprintf(
                    'RDG Blocks / regenerate_cache: Empty cache detected for %s - Attempting to regenerate',
                    $block_name
                ));
                
                // Check failed attempts - only skip if it has failed too many times
                $failed_name = $cache->getCacheFailedName($block_name);
                $failed_count = $cache->getCacheBlock($failed_name);
                
                if (!empty($failed_count) && $failed_count >= RDG_BLOCK_CACHE_FAILED_RETRY) {
                    error_log(sprintf(
                        'RDG Blocks / regenerate_cache: Block %s has failed %d times - Skipping regeneration',
                        $block_name,
                        $failed_count
                    ));
                    continue;
                }
                
                // Try to get block info from the block name structure
                // Format: block_name:post_type:post_id:block_id[:redis_db][:date_suffix]
                // Supports 4 parts (old format), 5 parts (standard), or 6 parts (with date suffix)
                $block_parts = explode(':', $block_name);
                if (count($block_parts) >= 4) {
                    $block_name_part = $block_parts[0];
                    $post_type = $block_parts[1];
                    $post_id = $block_parts[2];
                    $block_custom_id = $block_parts[3];
                    // Parts 4 and 5 (if present) are redis_db and date_suffix, not needed for parsing
                    
                    // CRITICAL FIX: Refresh post object to ensure we have the latest content
                    // This prevents reading stale ACF field values from cached post content
                    clean_post_cache($post_id);
                    $post = get_post($post_id);
                    
                    if ($post && $post->post_status === 'publish') {
                        // Get block from settings
                        $block = $rdgb->settings->getBlock(str_replace('_', '-', $block_name_part));
                        if ($block) {
                            // Parse blocks from post content - need all blocks for proper parsing
                            $all_blocks = $rdgb->settings->getBlocks();
                            $blocks_caching = $this->getBlocksCachingTest($all_blocks, $post->post_content);
                            
                            if (!empty($blocks_caching)) {
                                foreach ($blocks_caching as $block_data) {
                                    // Include date range in cache key for rdg-picks-vs-multi to ensure unique cache entries
                                    $date_suffix = '';
                                    if ($block_data['name'] === BLOCK_RDG_PICKS_VS_MULTI && isset($block_data['api_params']['date']) && is_array($block_data['api_params']['date'])) {
                                        $date_params = $block_data['api_params']['date'];
                                        if (!empty($date_params['start']) || !empty($date_params['end'])) {
                                            $date_suffix = ':' . md5(($date_params['start'] ?? '') . '|' . ($date_params['end'] ?? ''));
                                        }
                                    }
                                    
                                    $cache_name_check = $rdgb->helpers->getBlocksCacheName(
                                        $block_data['name'],
                                        $post_type,
                                        $post_id,
                                        $block_data['custom_id']
                                    ) . $date_suffix;
                                    
                                    // If this is the block we're looking for, regenerate it
                                    if ($cache_name_check === $block_name) {
                                        try {
                                            // CRITICAL FIX: Get ACF field values directly from post meta
                                            // This ensures we use actual saved values, not stale parsed values
                                            $api_params_enhanced = $this->getAcfFieldValuesFromPost(
                                                $post_id,
                                                $block_name_part,
                                                $block_data['custom_id'],
                                                $block->getApiParams(),
                                                $block_data
                                            );
                                            
                                            // Merge enhanced values with parsed values (enhanced takes priority)
                                            $final_api_params = array_merge($block_data['api_params'], $api_params_enhanced);
                                            
                                            $api_attributes = $block->getApiAttributes($block_data['items'], $final_api_params);
                                            
                                            $response = $rdgb->helpers->getApiRequest(
                                                $api_attributes['request'],
                                                $api_attributes['method'],
                                                $api_attributes['headers']
                                            );
                                            
                                            $cache_refresh = 1;
                                            $interval_field = $block->getBlockInternalField();
                                            if (!empty($interval_field) && !empty(get_field($interval_field, 'option'))) {
                                                $cache_refresh = get_field($interval_field, 'option');
                                            }
                                            
                                            if ($response['http_code'] == 200) {
                                                $response_json = $rdgb->helpers->isJson($response['data']);
                                                if ($response_json !== null) {
                                                    $data_update = [
                                                        'api_attributes' => $api_attributes,
                                                        'api_response' => $response_json,
                                                        'items' => is_countable($response_json) ? count($response_json) : 0
                                                    ];
                                                    
                                                    if ($block->isPreSaved()) {
                                                        $data_update['cache_name'] = $block_name;
                                                        $data_update['block'] = $block;
                                                        $response_json = $block->getPreSavedData($response_json, $data_update);
                                                        $data_update['api_response'] = $response_json;
                                                    }
                                                    
                                                    $updated = $cache->updateCacheBlock($block_name, $data_update, $response_json);
                                                    if ($updated) {
                                                        error_log(sprintf(
                                                            'RDG Blocks / regenerate_cache: Successfully regenerated empty cache for %s',
                                                            $block_name
                                                        ));
                                                        $count_cahe_regenerate++;
                                                    }
                                                } else {
                                                    $cache->updateCacheFailed($block_name, $cache_refresh);
                                                }
                                            } else {
                                                $cache->updateCacheFailed($block_name, $cache_refresh);
                                            }
                                        } catch (\Exception $e) {
                                            error_log(sprintf(
                                                'RDG Blocks / regenerate_cache: Error regenerating %s: %s',
                                                $block_name,
                                                $e->getMessage()
                                            ));
                                            $cache->updateCacheFailed($block_name, 1);
                                        }
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                
                // If we couldn't regenerate, mark as failed
                if (empty($cache->getCacheBlock($block_name))) {
                    $failed_name = $cache->getCacheFailedName($block_name);
                    $current_failed = $cache->getCacheBlock($failed_name);
                    $cache->updateCacheFailed($block_name, 1);
                }
                
                continue;
            }

            $attributes = $rdgb->helpers->isJson($data_block_json);

            if (
                !is_array($attributes) || 
                !isset($attributes['api_attributes']['request']) ||
                empty($attributes['api_attributes']['request'])
            ) {
                // CRITICAL FIX: Try to regenerate blocks with invalid/empty attributes
                error_log(sprintf(
                    'RDG Blocks / regenerate_cache: Invalid or empty attributes detected for %s - Attempting to regenerate',
                    $block_name
                ));
                
                // Check failed attempts - only skip if it has failed too many times
                $failed_name = $cache->getCacheFailedName($block_name);
                $failed_count = $cache->getCacheBlock($failed_name);
                
                if (!empty($failed_count) && $failed_count >= RDG_BLOCK_CACHE_FAILED_RETRY) {
                    error_log(sprintf(
                        'RDG Blocks / regenerate_cache: Block %s has failed %d times - Skipping regeneration',
                        $block_name,
                        $failed_count
                    ));
                    continue;
                }
                
                // Try to regenerate the block (same logic as empty cache)
                // Format: block_name:post_type:post_id:block_id[:redis_db][:date_suffix]
                // Supports 4 parts (old format), 5 parts (standard), or 6 parts (with date suffix)
                $block_parts = explode(':', $block_name);
                if (count($block_parts) >= 4) {
                    $block_name_part = $block_parts[0];
                    $post_type = $block_parts[1];
                    $post_id = $block_parts[2];
                    $block_custom_id = $block_parts[3];
                    // Parts 4 and 5 (if present) are redis_db and date_suffix, not needed for parsing
                    
                    // CRITICAL FIX: Refresh post object to ensure we have the latest content
                    clean_post_cache($post_id);
                    $post = get_post($post_id);
                    
                    if ($post && $post->post_status === 'publish') {
                        $block = $rdgb->settings->getBlock(str_replace('_', '-', $block_name_part));
                        if ($block) {
                            $all_blocks = $rdgb->settings->getBlocks();
                            $blocks_caching = $this->getBlocksCachingTest($all_blocks, $post->post_content);
                            
                            if (!empty($blocks_caching)) {
                                foreach ($blocks_caching as $block_data) {
                                    // Include date range in cache key for rdg-picks-vs-multi to ensure unique cache entries
                                    $date_suffix = '';
                                    if ($block_data['name'] === BLOCK_RDG_PICKS_VS_MULTI && isset($block_data['api_params']['date']) && is_array($block_data['api_params']['date'])) {
                                        $date_params = $block_data['api_params']['date'];
                                        if (!empty($date_params['start']) || !empty($date_params['end'])) {
                                            $date_suffix = ':' . md5(($date_params['start'] ?? '') . '|' . ($date_params['end'] ?? ''));
                                        }
                                    }
                                    
                                    $cache_name_check = $rdgb->helpers->getBlocksCacheName(
                                        $block_data['name'],
                                        $post_type,
                                        $post_id,
                                        $block_data['custom_id']
                                    ) . $date_suffix;
                                    
                                    if ($cache_name_check === $block_name) {
                                        try {
                                            // CRITICAL FIX: Get ACF field values directly from post meta
                                            // This ensures we use actual saved values, not stale parsed values
                                            $api_params_enhanced = $this->getAcfFieldValuesFromPost(
                                                $post_id,
                                                $block_name_part,
                                                $block_data['custom_id'],
                                                $block->getApiParams(),
                                                $block_data
                                            );
                                            
                                            // Merge enhanced values with parsed values (enhanced takes priority)
                                            $final_api_params = array_merge($block_data['api_params'], $api_params_enhanced);
                                            
                                            $api_attributes = $block->getApiAttributes($block_data['items'], $final_api_params);
                                            
                                            // Validate api_attributes
                                            if (!is_array($api_attributes) || 
                                                !isset($api_attributes['request']) || 
                                                empty($api_attributes['request']) ||
                                                !isset($api_attributes['method'])) {
                                                error_log(sprintf(
                                                    'RDG Blocks / regenerate_cache: Invalid api_attributes for %s - Cannot regenerate',
                                                    $block_name
                                                ));
                                                $cache->updateCacheFailed($block_name, 1);
                                                break;
                                            }
                                            
                                            $cache_refresh = 1;
                                            $interval_field = $block->getBlockInternalField();
                                            if (!empty($interval_field) && !empty(get_field($interval_field, 'option'))) {
                                                $cache_refresh = get_field($interval_field, 'option');
                                            }
                                            
                                            $response = $rdgb->helpers->getApiRequest(
                                                $api_attributes['request'],
                                                $api_attributes['method'],
                                                isset($api_attributes['headers']) ? $api_attributes['headers'] : []
                                            );
                                            
                                            if ($response['http_code'] == 200) {
                                                $response_json = $rdgb->helpers->isJson($response['data']);
                                                if ($response_json !== null) {
                                                    $data_update = [
                                                        'api_attributes' => $api_attributes,
                                                        'api_response' => $response_json,
                                                        'items' => is_countable($response_json) ? count($response_json) : 0
                                                    ];
                                                    
                                                    if ($block->isPreSaved()) {
                                                        $data_update['cache_name'] = $block_name;
                                                        $data_update['block'] = $block;
                                                        $response_json = $block->getPreSavedData($response_json, $data_update);
                                                        $data_update['api_response'] = $response_json;
                                                    }
                                                    
                                                    $updated = $cache->updateCacheBlock($block_name, $data_update, $response_json);
                                                    if ($updated) {
                                                        error_log(sprintf(
                                                            'RDG Blocks / regenerate_cache: Successfully regenerated invalid cache for %s',
                                                            $block_name
                                                        ));
                                                        $count_cahe_regenerate++;
                                                    }
                                                } else {
                                                    $cache->updateCacheFailed($block_name, $cache_refresh);
                                                }
                                            } else {
                                                $cache->updateCacheFailed($block_name, $cache_refresh);
                                            }
                                        } catch (\Exception $e) {
                                            error_log(sprintf(
                                                'RDG Blocks / regenerate_cache: Error regenerating %s: %s',
                                                $block_name,
                                                $e->getMessage()
                                            ));
                                            $cache->updateCacheFailed($block_name, 1);
                                        }
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                
                // If we couldn't regenerate, mark as failed
                if (empty($cache->getCacheBlock($block_name)) || 
                    (is_array($attributes) && (empty($attributes['api_attributes']['request']) || empty($attributes['api_response'])))) {
                    $failed_name = $cache->getCacheFailedName($block_name);
                    $cache->updateCacheFailed($block_name, 1);
                }
                
                continue;
            }

            $cache_refresh = 1;
            if (
                isset($attributes['api_attributes']['cache_refresh']) &&
                !empty($attributes['api_attributes']['cache_refresh'])
            ) {
                $cache_refresh = $attributes['api_attributes']['cache_refresh'];
            }

            $regenerate = false;
            $api_attributes = $attributes['api_attributes'];
            $time = $cache->getCacheBlockTimeSeg($block_name);

            if (
                !isset($attributes['api_response']) ||
                (isset($attributes['api_response']) && !is_array($attributes['api_response']))
            ) {
                $regenerate = true;
            } elseif($time <= RDG_BLOCK_CACHE_CLEAR_TIME) {
                $regenerate = true;
            }

            if (!$regenerate) {
                continue;
            }

            $failed_name = $cache->getCacheFailedName($block_name);
            $failed_block = $cache->getCacheBlock($failed_name);

            if (!empty($failed_block) && $failed_block >= RDG_BLOCK_CACHE_FAILED_RETRY) {
                $rdgb->helpers->getApiError('api_request', [
                    'block' => $block_name,
                    'failed_block' => $failed_block,
                    'api_attributes' => $api_attributes
                ]);

                continue;
            }
            
            $response = $rdgb->helpers->getApiRequest(
                $api_attributes['request'],
                $api_attributes['method'],
                $api_attributes['headers']
            );

            if ($response['http_code'] != 200) {
                $rdgb->helpers->getApiError($response['http_code'], [
                    'block' => $block_name,
                    'http_code' => $response['http_code'],
                    'api_attributes' => $api_attributes
                ]);

                $cache->updateCacheFailed($block_name, $cache_refresh);

                continue;
            }

            $response_json = $rdgb->helpers->isJson($response['data']);
            if ($response_json == null) {
                $rdgb->helpers->getApiError('json_response', [
                    'block' => $block_name,
                    'code' => 'json_response',
                    'api_attributes' => $api_attributes
                ]);

                $cache->updateCacheFailed($block_name, $cache_refresh);

                continue;
            }

            $block_name_part = explode(':', $block_name)[0];
            $block = $rdgb->settings->getBlock(str_replace('_', '-', $block_name_part));

            if ($block->isPreSaved()) {
                $attributes['cache_name'] = $block_name;
                $attributes['block'] = $block;
                $response_json = $block->getPreSavedData($response_json, $attributes);
            }

            $updated = $cache->updateCacheBlock($block_name, $attributes, $response_json);
            if (!$updated) {
                continue;
            }

            // Parse cache key format: block_name:post_type:post_id:block_id[:redis_db][:date_suffix]
            // Supports both 5 parts (standard) and 6 parts (with optional date suffix)
            // Only need indices 1 and 2 for page_type and post_id
            $tems = explode(':', $block_name);
            $rdgb->helpers->getApiError('update_cache', [
                'page_type' => $tems[1] ?? '',
                'post_id' => $tems[2] ?? '',
                'block_name' => $block_name,
            ]);

            $count_cahe_regenerate++;
        }

        update_option('rdg_blocks_cache_last_run', date('Y-m-d H:i:s'));
        error_log(sprintf('RDG Blocks / regenerate_cache: Regenerated cache blocks. Analyzed: %s, Regenerated: %s', $count_cahe_analyze, $count_cahe_regenerate));
    }

    public function inGodWeTrust() {
        global $wpdb;
        global $rdgb;
        $blocks = $rdgb->settings->getBlocks();

        $cache = new Rdg_Blocks_Cache();
        $connect = $cache->getRedisConnect();

        if (!$connect) return;
        $cache_blocks = $cache->getCacheList();

        $offset = 0;
        $limit = 50;

        ini_set('max_execution_time', 300);

        do {
            $query = "
                SELECT p.ID, p.post_content, p.post_type
                FROM {$wpdb->prefix}posts p
                WHERE p.post_status = 'publish'
                AND (
                    p.post_content LIKE '%acf/rdg-admin-cappers-simple%' OR
                    p.post_content LIKE '%acf/rdg-handicapper-pick-results%' OR
                    p.post_content LIKE '%acf/rdg-handicappers-hub%' OR
                    p.post_content LIKE '%acf/rdg-handicappers-filter%' OR
                    p.post_content LIKE '%acf/rdg-injury-report%' OR
                    p.post_content LIKE '%acf/rdg-leader-board%' OR
                    p.post_content LIKE '%acf/rdg-membership-info%' OR
                    p.post_content LIKE '%acf/rdg-picks-vs%' OR
                    p.post_content LIKE '%acf/rdg-picks-vs-categories%' OR
                    p.post_content LIKE '%acf/rdg-picks-vs-multi%' OR
                    p.post_content LIKE '%acf/rdg-scores-and-odds%' OR
                    p.post_content LIKE '%acf/rdg-sport-betting-odds%' OR
                    p.post_content LIKE '%acf/rdg-sports-picks%' OR
                    p.post_content LIKE '%acf/rdg-sports-picks-vs%' OR
                    p.post_content LIKE '%acf/rdg-top-cappers%' OR
                    p.post_content LIKE '%acf/rdg-top-cappers-sport%' OR
                    p.post_content LIKE '%acf/rdg-top-winners%' OR
                    p.post_content LIKE '%acf/rdg-trends%'
                )
                LIMIT %d OFFSET %d
            ";

            $sql = $wpdb->prepare($query, $limit, $offset);
            $posts = $wpdb->get_results($sql);

            error_log('RDG Blocks / inGodWeTrust: Processing posts from offset '.$offset.' with limit '.$limit);
            echo 'RDG Blocks / inGodWeTrust: Processing posts from offset '.$offset.' with limit '.$limit."\n";

            foreach ($posts as $post) {
                $post_id = $post->ID;
                $post_type = $post->post_type;
                $blocks_caching = $this->getBlocksCachingTest($blocks, $post->post_content);
                $blocks_list = [];
                $page = $post_type.':'.$post_id;

                if (count($blocks_caching) > 0) {
                    foreach ($blocks_caching as $block) {
                        $block_paser = $block['block_parse'][0];
                        unset($block['block_parse']);
                        $html = render_block($block_paser);
                        
                        $block_name = $block['name'];
                        $items = $block['items'];
                        $block_custom_id = $block['custom_id'];
                        
                        // Include date range in cache key for rdg-picks-vs-multi to ensure unique cache entries
                        // Incorporate date hash into block_id to maintain standard 5-part cache name structure
                        $cache_block_id = $block_custom_id;
                        if ($block_name === BLOCK_RDG_PICKS_VS_MULTI && isset($block['api_params']['date']) && is_array($block['api_params']['date'])) {
                            $date_params = $block['api_params']['date'];
                            if (!empty($date_params['start']) || !empty($date_params['end'])) {
                                // Generate date hash and append to block_id to keep standard cache name format
                                $date_hash = md5(($date_params['start'] ?? '') . '|' . ($date_params['end'] ?? ''));
                                $cache_block_id = $block_custom_id . '-' . $date_hash;
                            }
                        }
                        
                        $cache_name = $rdgb->helpers->getBlocksCacheName($block_name, $post_type, $post_id, $cache_block_id);
                        
                        $cache_refresh = 1;
                        $interval_field = (isset($block['interval_field']) && !empty($block['interval_field'])) ? $block['interval_field'] : null;

                        if (!empty($interval_field) && !empty(get_field($interval_field, 'option'))) {
                            $cache_refresh = get_field($interval_field, 'option');
                        }

                        $blocks_list[] = $cache_name;

                        # If the block exists in Redis with valid data, do not generate cache
                        if (in_array($cache_name, $cache_blocks)) {
                            // Verificar si el bloque tiene datos válidos
                            $existing_block_data = $cache->getCacheBlock($cache_name);
                            if (!empty($existing_block_data)) {
                                try {
                                    $existing_data = json_decode($existing_block_data, true);
                                    // Si tiene api_response válido, no regenerar
                                    if (is_array($existing_data) && isset($existing_data['api_response']) && !empty($existing_data['api_response'])) {
                                        continue;
                                    }
                                } catch (\Exception $e) {
                                    // Si hay error al decodificar, regenerar
                                    error_log('RDG Blocks / inGodWeTrust: Invalid cache data for ' . $cache_name . ', will regenerate');
                                }
                            }
                            // Si el bloque existe pero está vacío o tiene datos inválidos, continuar para regenerarlo
                        }

                        try {
                            $current_block = $rdgb->settings->getBlock($block_name);
                            $api_attributes = $current_block->getApiAttributes($items, $block['api_params']);

                            $data = [
                                'api_attributes' => $api_attributes,
                                'api_response' => null,
                                'items' => 0,
                            ];

                            # Add the block to the cache list
                            $saved = $cache->addCacheList($cache_name, $cache_refresh, $data);
                            if (!$saved) {
                                $rdgb->helpers->getApiError('cache_save_error', [
                                    'block_name' => $block_name,
                                    'code' => 'cache_save_error',
                                    'api_attributes' => $api_attributes
                                ]);

                                continue;
                            }

                            $rdgb->helpers->getApiError(200, ['block_name' => $block_name]);
                        } catch (Exception $exception) {
                            $rdgb->helpers->getApiError('', [
                                'block_name' => $block_name,
                                'api_attributes' => $api_attributes,
                                'exception' => [
                                    'file' => $exception->getFile(),
                                    'line' => $exception->getLine(),
                                    'message' => $exception->getMessage(),
                                ],
                            ]);
                        }
                    }
                }

                $cache->clearCacheBlock($blocks_list, $page);
            }

            $offset += $limit;
        } while (count($posts) === $limit);

        error_log('RDG Blocks / inGodWeTrust: Finished processing posts.');
        echo 'RDG Blocks / inGodWeTrust: Finished processing posts.'."\n";
    }

    /**
     * Get ACF field values directly from post meta for a specific block instance
     * This ensures we get the actual saved values, not stale values from parsed block attributes
     * 
     * @param int $post_id The post ID
     * @param string $block_name The block name (e.g., 'rdg-picks-vs')
     * @param string $custom_id The block's custom_id
     * @param array $api_params The API params mapping from getApiParams()
     * @param array $block_data The parsed block data array from getBlocksCachingTest
     * @return array The array_attributes with actual ACF field values (only non-empty values to override)
     */
    private function getAcfFieldValuesFromPost($post_id, $block_name, $custom_id, $api_params, $block_data = []) {
        $array_attributes = [];
        
        // Parse all blocks from post to find the matching block instance with latest data
        $post = get_post($post_id);
        if (!$post) {
            return $array_attributes;
        }
        
        // Re-parse blocks to get the latest block data from post content
        $blocks_parsed = parse_blocks($post->post_content);
        $target_block_data = null;
        
        // Find the block with matching custom_id
        foreach ($blocks_parsed as $parsed_block) {
            if (isset($parsed_block['attrs']['data']['custom_id']) && 
                $parsed_block['attrs']['data']['custom_id'] === $custom_id &&
                isset($parsed_block['attrs']['name'])) {
                $parsed_block_name = $parsed_block['attrs']['name'];
                if (substr($parsed_block_name, 0, 4) == 'acf/') {
                    $parsed_block_name = substr($parsed_block_name, 4);
                }
                if ($parsed_block_name === $block_name || str_replace('_', '-', $parsed_block_name) === str_replace('_', '-', $block_name)) {
                    $target_block_data = $parsed_block['attrs']['data'];
                    break;
                }
            }
        }
        
        // Use the latest block data from post
        $latest_block_data = $target_block_data ? $target_block_data : [];
        
        // Get current values from block_data (already parsed)
        $current_api_params = isset($block_data['api_params']) && is_array($block_data['api_params']) ? $block_data['api_params'] : [];
        
        // Only override values that are actually different/non-empty in the latest block data
        // This prevents overwriting valid values with empty/default ones
        if (count($api_params) > 0 && !empty($latest_block_data)) {
            foreach ($api_params as $array_key => $field_name) {
                if ($array_key == '_to_transform_' || $array_key == '_to_array_') {
                    continue;
                }
                
                // Get value from latest parsed block data
                $latest_value = isset($latest_block_data[$field_name]) ? $latest_block_data[$field_name] : null;
                
                // Get current value from already-parsed block_data
                $current_value = isset($current_api_params[$array_key]) ? $current_api_params[$array_key] : '';
                
                // Check if latest value is meaningful (not empty, not '1', not 1, not '')
                // Special case: if current is '1' or 1 (default), and latest is different, use latest
                $is_default_value = ($current_value === '1' || $current_value === 1 || $current_value === '');
                $is_meaningful_latest = !empty($latest_value) && 
                                       $latest_value !== '1' && 
                                       $latest_value !== 1 && 
                                       $latest_value !== '';
                
                // Override if:
                // 1. Latest value is meaningful and different from current, OR
                // 2. Current is default/empty and latest exists (even if it's also default, prefer latest from post)
                if ($is_meaningful_latest || ($is_default_value && $latest_value !== null && $latest_value !== '')) {
                    $array_attributes[$array_key] = $latest_value;
                }
            }
        }
        
        return $array_attributes;
    }

    public function getBlocksCachingTest($blocks, $content) {
        $i = 0;
        $blocks_caching = [];

        foreach ($blocks as $block) {
            if ($block->isCaching()) {
                $block_name = $block->getBlockName();

                $block_name_exp_init = '<!-- wp:'.str_replace('/', '\/', 'acf/'.$block_name);
                $blocks_count = preg_match_all('/'.$block_name_exp_init.'/', $content, $blocks_exp, PREG_OFFSET_CAPTURE);

                if ($blocks_count > 0) {
                    foreach ($blocks_exp[0] as $block_exp) {
                        $clear_block_init = substr($content, $block_exp[1], strlen($content));
                        preg_match('/\/-->/', $clear_block_init, $clear_block_end, PREG_OFFSET_CAPTURE);
                        $block_content = substr($clear_block_init, 0, $clear_block_end[0][1]).'/-->';
                        $block_parse = parse_blocks($block_content);
                        $block_attrs = $block_parse[0]['attrs'];
                        $interval_field = $block->getBlockInternalField();

                        if (!isset($block_attrs['data']['source']) || $block_attrs['data']['source'] == SOURCE_DATA_API) {
                            $name = $block_attrs['name'];

                            if (substr($name, 0, 4) == 'acf/') {
                                $name = substr($name, 4, strlen($name));
                            }

                            $save = true;
                            foreach ($blocks_caching as $block_exist) {
                                if ($block_exist['custom_id'] == $block_attrs['data']['custom_id']) {
                                    $save = false;
                                    break;
                                }
                            }

                            if ($save) {
                                $blocks_caching[$i] = [
                                    'name' => $name,
                                    'interval_field' => $interval_field,
                                    'custom_id' => $block_attrs['data']['custom_id'],
                                    'items' => (isset($block_attrs['data']['number_of_items'])) ? $block_attrs['data']['number_of_items'] : null,
                                ];

                                $rdgb = Rdg_Blocks::instance();
                                $current_block = $rdgb->settings->getBlock($block_name);
                                $api_params = $current_block->getApiParams();

                                $transforms = [];
                                $to_array = '';
                                $array_attributes = [];

                                if (count($api_params) > 0) {
                                    foreach ($api_params as $array_key => $field_name) {
                                        if ($array_key == '_to_transform_') {
                                            $transforms = $api_params['_to_transform_'];
                                            unset($api_params['_to_transform_']);

                                            continue;
                                        }

                                        if ($array_key == '_to_array_') {
                                            $to_array = $api_params['_to_array_'];
                                            unset($api_params['_to_array_']);

                                            continue;
                                        }

                                        $array_attributes[$array_key] = isset($block_attrs['data'][$field_name]) ? $block_attrs['data'][$field_name] : '';
                                    }
                                    
                                    if (is_array($transforms) && count($transforms) > 0) {
                                        foreach ($transforms as $transform_item) {
                                            $params = [];

                                            $transform_result = null;
                                            foreach ($transform_item['params'] as $param_name) {
                                                if (isset($transform_item['repeater']) && $transform_item['repeater']) {
                                                    if (isset($block_attrs['data'][$param_name]) && $block_attrs['data'][$param_name] > 0) {
                                                        $cappers_items = $block_attrs['data'][$param_name];

                                                        $repeater_data = [];
                                                        for ($ii = 0; $ii < $cappers_items; $ii++) {
                                                            $repeater_field = sprintf($transform_item['repeater_format'], $ii);

                                                            if (isset($block_attrs['data'][$repeater_field])) {
                                                                $repeater_data[] = $block_attrs['data'][$repeater_field];
                                                            }
                                                        }

                                                        if (is_array($repeater_data) && count($repeater_data) > 0) {
                                                            $params[] = $repeater_data;
                                                        }
                                                    } else {
                                                        $params[] = [];
                                                    }
                                                } else {
                                                    if (isset($block_attrs['data'][$param_name])) {
                                                        $is_date = false;
                                                        if (isset($transform_item['fields_date'])) {
                                                            if (in_array($param_name, $transform_item['fields_date'])) {
                                                                $is_date = true;
                                                            }
                                                        }

                                                        if ($is_date) {
                                                            $params[] = $rdgb->helpers->getValidDate($block_attrs['data'][$param_name]);
                                                        } else {
                                                            $params[] = $block_attrs['data'][$param_name];
                                                        }
                                                    } else {
                                                        $params[] = '';
                                                    }
                                                }
                                            }

                                            $transform_result = call_user_func_array(array($current_block, $transform_item['function']), $params);
                                            
                                            if ($transform_result !== null) {
                                                $array_attributes[$transform_item['key']] = $transform_result;
                                            }
                                        }
                                    }

                                    $to_array_result = null;
                                    if (is_array($to_array)) {
                                        for ($j = 0; $j < $block_attrs['data'][$to_array['key']]; $j++) { 
                                            $prefix = $to_array['key'].'_'.$j.'_';

                                            foreach ($to_array['fields'] as $field_array) {
                                                $field_name = $prefix.$field_array;
                                                $to_array_result[$j][$field_array] = $block_attrs['data'][$field_name];
                                            }
                                        }
                                    }

                                    if ($to_array_result !== null) {
                                        $array_attributes[$to_array['key']] = $to_array_result;
                                    }
                                }

                                $blocks_caching[$i]['api_params'] = $array_attributes;
                                $blocks_caching[$i]['block_parse'] = $block_parse;
                                $i++;
                            }
                        }
                    }
                }
            }
        }

        return $blocks_caching;
    }
}
