<?php

// Exit if accessed directly.
if (!defined('ABSPATH')) exit;

/**
 * Class Rdg_Blocks_Helpers
 *
 * This class contains repetitive functions that
 * are used globally within the plugin.
 *
 * @package        RDGBLOCKS
 * @subpackage    Classes/Rdg_Blocks_Helpers
 * @author        RDGCorp
 * @since        1.0.0
 */
class Rdg_Blocks_Helpers
{
    /**
     * The blocks cache directory
     *
     * @var        array
     * @since   1.0.13
     */

    private $cache_dir;

    /**
     * The blocks cache suffix
     *
     * @var        array
     * @since   1.0.13
     */

    private $cache_suffix;

    /**
     * Redis Service
     *
     * @var        class
     * @since   1.0.68
     */

     private $redis_cache;
     private $redis_cache_group;

    /**
     * Our Rdg_Blocks_Settings constructor 
     * to run the plugin logic.
     *
     * @since 1.0.0
     */

    function __construct() {
        $this->cache_dir = wp_upload_dir()['basedir'].'/'.RDGBLOCKS_NAME_SLUG.'/';
        $this->cache_suffix = '-cache.json';
        $this->redis_cache = $this->initRedis();
        $this->setRedisGroup();
        
    }

    public function getCacheDir() {
        return $this->cache_dir;
    }

    public function getCacheSuffix() {
        return $this->cache_suffix;
    }

    public function webpack($file, $buildDirectory = 'dist') {
        static $manifest;
        static $manifestPath;

        if (is_null($manifest) || $manifestPath !== $buildDirectory) {
            $manifest = json_decode(
                file_get_contents(RDGBLOCKS_PLUGIN_DIR.$buildDirectory.'/manifest.json'),
                true
            );

            $manifestPath = $buildDirectory;
        }

        if (isset($manifest[$file])) {
            return RDGBLOCKS_PLUGIN_URL.trim($buildDirectory.'/'.$manifest[$file], '/');
        }

        throw new InvalidArgumentException("File {$file} not defined in asset manifest.");
    }

    public function getBlocksSpaces($fields) {
        $styles = [];

        if (!empty($fields['top'])) {
            $styles[] = $fields['top']['top_type'].'-top: '.$fields['top']['top_space'].'rem';
        }

        if (!empty($fields['right'])) {
            $styles[] = $fields['right']['right_type'].'-right: '.$fields['right']['right_space'].'rem';
        }

        if (!empty($fields['bottom'])) {
            $styles[] = $fields['bottom']['bottom_type'].'-bottom: '.$fields['bottom']['bottom_space'].'rem';
        }

        if (!empty($fields['left'])) {
            $styles[] = $fields['left']['left_type'].'-left: '.$fields['left']['left_space'].'rem';
        }

        if (count($styles) > 0) {
            return implode('; ', $styles).';';
        }

        return '';
    }

    public function getTitle($fields, $return_string = true, $validations = []) {
        $style = $this->getTitleSizes($fields);
        $title = (!empty($fields['title'])) ? $fields['title'] : '';
        $heading = (!empty($fields['heading'])) ? $fields['heading'] : 'span';
        
        $styles = [];
        $style[] = (!empty($fields['title_color'])) ? 'color: '.$fields['title_color'] : 'color: #3a96e0';
        $style[] = (!empty($fields['font_weight'])) ? '--font-weight: '.$fields['font_weight'] : '--font-weight: 500';

        if (is_array($validations) && !isset($validations['unaligned']) || (isset($validations['unaligned']) && $validations['unaligned'] == false)) {
            $style[] = (!empty($fields['title_align'])) ? 'justify-content: '.$fields['title_align'] : 'justify-content: left';
        }

        $style[] = (!empty($fields['title_color_shadow'])) ? 'text-shadow: 0px 1px 1px '.$fields['title_color_shadow'] : 'text-shadow: 0px 1px 1px #03467d';
        $style[] = (!empty($fields['padding'])) ? 'padding-bottom: '.$fields['padding'].'rem' : 'padding-bottom: 0';
    
        if (count($style) > 0 && $return_string) {
            $styles = implode('; ', $style).';';
        } else {
            $styles = $style;
        }
    
        return [$heading, $title, $styles];
    }

    public function getHeading($fields, $type) {
        $style = $this->getTitleSizes($fields);

        if ($type == 'separator') {
            $heading = (!empty($fields['separator']['tag'])) ? $fields['separator']['tag'] : 'span';
            $separator = [];
            $separator[] = (!empty($fields['separator']['padding'])) ? 'padding-bottom: '.$fields['separator']['padding'].'rem' : 'padding-bottom: 0';
            $separator[] = (!empty($fields['separator']['text_align'])) ? '--justify: '.$fields['separator']['text_align'] : '--justify: left';
            $separator[] = (!empty($fields['separator']['border'])) ? '--border-size: '.$fields['separator']['border'].'px' : '--border-size: 5px';
            $separator[] = (!empty($fields['separator']['border_color'])) ? '--border-color: '.$fields['separator']['border_color'] : '--border-color: #000000';

            $separator_style = implode('; ', $separator).';';

            return [$heading, $separator_style];
        } else {
            $titles = [];
            $titles = $this->getTitleSizes($fields);
            
            $title = (!empty($fields['heading_text'])) ? $fields['heading_text'] : '';
            $titles[] = (!empty($fields['title_color'])) ? 'color: '.$fields['title_color'] : 'color: #000000';
            $titles[] = (!empty($fields['font_weight'])) ? '--font-weight: '.$fields['font_weight'] : '--font-weight: 500';

            if (!empty($fields['title_color_shadow'])) {
                $titles[] = 'text-shadow: 0px 1px 1px '.$fields['title_color_shadow'];
            }

            $titles_style = implode('; ', $titles).';';

            return [$title, $titles_style];
        }
    }
    
    public function getTitleSizes($fields) {
        $size = (!empty($fields['size'])) ? $fields['size'] : 3;
        $size_lg = (!empty($fields['size_lg'])) ? $fields['size_lg'] : null;
        $size_md = (!empty($fields['size_md'])) ? $fields['size_md'] : null;
        $size_sm = (!empty($fields['size_sm'])) ? $fields['size_sm'] : null;
    
        $style = [];
        
        if (!empty($size) || !empty($size_lg) || !empty($size_md) || !empty($size_sm)) {
            if (!empty($size)) {
                $last = $size;
                $style[] = '--font-size: '.$size.'rem';
                $style[] = '--line-height: '.(intval($size) + 0.5).'rem';
            } else {
                $last = 3;
                $style[] = '--font-size-lg: '.$last.'rem';
                $style[] = '--line-height-lg: '.($last + 0.5).'rem';
            }
    
            if (!empty($size_lg)) {
                $last = $size_lg;
                $style[] = '--font-size-lg: '.$size_lg.'rem';
                $style[] = '--line-height-lg: '.(intval($size_lg) + 0.5).'rem';
            } else {
                $style[] = '--font-size-lg: '.$last.'rem';
                $style[] = '--line-height-lg: '.($last + 0.5).'rem';
            }
    
            if (!empty($size_md)) {
                $last = $size_md;
                $style[] = '--font-size-md: '.$size_md.'rem';
                $style[] = '--line-height-md: '.(intval($size_md) + 0.5).'rem';
            } else {
                $style[] = '--font-size-md: '.$last.'rem';
                $style[] = '--line-height-md: '.($last + 0.5).'rem';
            }
            
            if (!empty($size_sm)) {
                $style[] = '--font-size-sm: '.$size_sm.'rem';
                $style[] = '--line-height-sm: '.(intval($size_sm) + 0.5).'rem';
            } else {
                $style[] = '--font-size-sm: '.$last.'rem';
                $style[] = '--line-height-sm: '.($last + 0.5).'rem';
            }
        }
    
        return $style;
    }

    public function getCacheName($block_name, $post_type, $post_id, $block_id, $dir = false) {
        $cache_name = $block_name.'-'.$post_type.'-'.$post_id.'-'.$block_id.$this->cache_suffix;

        if (!$dir) {
            return $cache_name;
        }

        return $this->cache_dir.$cache_name;
    }

    public function getBlocksCacheName($block_name, $post_type, $post_id, $block_id) {
        $block_name = str_replace('-', '_', $block_name);
        
        // Add Redis database ID as suffix for additional isolation and debugging
        // This works in combination with database selection for double protection
        $redis_db = defined('WP_REDIS_DATABASE') ? WP_REDIS_DATABASE : 0;

        return $block_name.':'.$post_type.':'.$post_id.':'.$block_id.':'.$redis_db;
    }

    public function setCacheFile($block_name, $cache_file, $data = null) {
        $file = New StdClass();
        $file->code = 200;
        $file->message = null;
        $file->cache_file = null;

        if (!file_exists($this->cache_dir)) {
            try {
                mkdir($this->cache_dir);
            } catch (Exception $exception) {
                if (file_exists($this->cache_dir)) {
                    unlink($this->cache_dir);
                }

                $error = $this->getApiError('create_directory', ['block_name' => $block_name]);
                $file->code = 'create_directory';
                $file->message = $error;

                return $file;
            }
        }

        try {
            $cache = fopen($cache_file, "w");

            if (!empty($data)) {
                fwrite($cache, json_encode($data));
            }

            fclose($cache);
        } catch (Exception $exception) {
            if (file_exists($cache_file)) {
                unlink($cache_file);
            }

            $error = $this->getApiError('create_cache', ['block_name' => $block_name]);
            $file->code = 'create_cache';
            $file->message = $error;

            return $file;
        }

        $file->cache_file = $cache_file;

        return $file;
    }

    /**
     * Centralizes curl request with logs and configuration.
     */
    public function rdgblocks_curl_request($url, $method = 'GET', $headers = [], $timeout = 30)
    {
        $curl = curl_init();

        // Ensure headers is always an array
        if (!is_array($headers)) {
            $headers = [];
        }

        $parsed_url = parse_url($url);
        $host = isset($parsed_url['host']) ? $parsed_url['host'] : '';

        $default_headers = [
            'Host: ' . $host,
            'User-Agent: Mozilla/5.0 (compatible; RDGBlocks/1.0; +' . get_bloginfo('url') . ')',
            'Accept: application/json, text/plain, */*',
            'Accept-Encoding: gzip, deflate',
            'Cache-Control: no-cache',
        ];

        // Merge default headers with custom headers
        $merged_headers = array_merge($default_headers, $headers);

        // Ensure merged_headers is an array (additional safety)
        if (!is_array($merged_headers)) {
            $merged_headers = $default_headers;
        }

        $curl_options = [
            CURLOPT_URL            => $url,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_TIMEOUT        => $timeout,
            CURLOPT_CONNECTTIMEOUT => 10,
            CURLOPT_FOLLOWLOCATION => true,
            CURLOPT_MAXREDIRS      => 5,
            CURLOPT_CUSTOMREQUEST  => $method,
            CURLOPT_HTTPHEADER     => $merged_headers,
            CURLOPT_HTTP_VERSION   => CURL_HTTP_VERSION_1_1,
            CURLOPT_FAILONERROR    => false,
            CURLOPT_ENCODING       => '',
        ];

        // Don't verify SSL in local environments if defined
        if (defined('RDGBLOCKS_DISABLE_SSL_VERIFY') && RDGBLOCKS_DISABLE_SSL_VERIFY) {
            $curl_options[CURLOPT_SSL_VERIFYHOST] = 0;
            $curl_options[CURLOPT_SSL_VERIFYPEER] = false;
            error_log("[RDG Blocks] Advertencia: SSL verification deshabilitado para URL: $url");
        }

        curl_setopt_array($curl, $curl_options);

        $response = [];
        $response['data']      = curl_exec($curl);
        $response['http_code'] = curl_getinfo($curl, CURLINFO_HTTP_CODE);

        if ($response['data'] === false) {
            $errno = curl_errno($curl);
            $error = curl_error($curl);
            error_log("[RDG Blocks] cURL error en $url (errno: $errno): $error");
            $response['data'] = '{"error": "Connection failed"}';
            $response['http_code'] = 0;
        }

        return $response;
    }

    public function getApiRequest($request, $method = 'GET', $headers = []) {
        // Different timeout depending on context
        $timeout = is_admin() && defined('DOING_AJAX') && DOING_AJAX ? 30 : 10;

        error_log("[RDG Blocks] getApiRequest → URL: $request | Method: $method | Headers: " . json_encode($headers) . " | Timeout: $timeout");

        $response = $this->rdgblocks_curl_request($request, $method, $headers, $timeout);

        if ($response['http_code'] != 200) {
            error_log("[RDG Blocks] getApiRequest → fallo HTTP={$response['http_code']} en $request");
        }

        return $response;
    }


    public function getApiDataAjax($block_name, $attibutes = []) {
        $data = new StdClass();
        $data->json = '';
        $data->message = '';

        $items = (isset($attibutes['items']) && !empty($attibutes['items'])) 
            ? intval($attibutes['items']) : 10;
        $request = (isset($attibutes['request']) && !empty($attibutes['request'])) 
            ? $attibutes['request'] : '';
        $request_method = (isset($attibutes['method']) && !empty($attibutes['method'])) 
            ? $attibutes['method'] : 'GET';
        $request_headers = (isset($attibutes['headers']) && !empty($attibutes['headers'])) 
            ? $attibutes['headers'] : [];

        $response_json = '';
        $response = $this->getApiRequest($request, $request_method, $request_headers);

        if ($response['http_code'] == 200) {
            $response_json = $this->isJson($response['data']);

            if ($response_json != null) {
                $data->json = $response_json;

                return $data;
            }

            $response['http_code'] = 'json_response';
        }

        $error = $this->getApiError($response['http_code'], [
            'block_name' => $block_name,
            'request' => $request,
            'response_json' => $response_json
        ]);

        $data->message = $error;
        
        return $data;
    }

    public function getBlocksCaching($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[] = $this->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;
                                $i++;
                            }
                        }
                    }
                }
            }
        }

        return $blocks_caching;
    }

    public function getValidDate($date) {
        if (substr_count($date, '-') == 2 && strlen($date) == 10) {
            return $date;
        }

        if (!strpos($date, '-') && strlen($date) == 8) {
            if (checkdate(intval(substr($date,4,2)), intval(substr($date,6,2)), intval(substr($date,0,4)))) {
                return substr($date,0,4).'-'.substr($date,4,2).'-'.substr($date,6,2);
            }
        }

        return $date;
    }

    public function isJson($string) {
        $encode = json_decode($string, true);
        $response = (json_last_error() === JSON_ERROR_NONE) ? $encode : null;

        return $response;
    }

    public function getApiError($error, $attributes = null) {
        if ($error == 0) {
            $message = RDGBLOCKS_NAME.': Invalid or unavailable URL.';
           error_log(print_r(['error' => $error, 'message' => $message, 'attributes' => $attributes], true));

            return __($message);
        }

        if ($error == 200) {
           error_log(RDGBLOCKS_NAME.': Block '. $attributes['block_name'].'. The cache was updated correctly.');

            return;
        }

        if ($error == 404) {
            $message = RDGBLOCKS_NAME.': Resource not found.';
           error_log(print_r(['error' => $error, 'message' => $message, 'attributes' => $attributes], true));

            return __($message);
        }

        if ($error == 401) {
            $message = RDGBLOCKS_NAME.': Not authorized.';
           error_log(print_r(['error' => $error, 'message' => $message, 'attributes' => $attributes], true));

            return __($message);
        }
        
        if ($error == 'json_response') {
            $message = RDGBLOCKS_NAME.': Invalid data format.';
           error_log(print_r(['error' => $error, 'message' => $message, 'attributes' => $attributes], true));

            return __($message);
        }

        if ($error == 'api_request') {
            $message = RDGBLOCKS_NAME.': The request could not be processed.';
           error_log(print_r(['error' => $error, 'message' => $message, 'attributes' => $attributes], true));

            return __($message);
        }

        if ($error == 'create_cache') {
            $message = RDGBLOCKS_NAME.': Error trying to create cache.';
           error_log(print_r(['error' => $error, 'message' => $message, 'attributes' => $attributes], true));

            return __($message);
        }

        if ($error == 'load_cache') {
            $message = RDGBLOCKS_NAME.': Error trying to load cache.';
           error_log(print_r(['error' => $error, 'message' => $message, 'attributes' => $attributes], true));

            return __($message);
        }

        if ($error == 'delete_cache') {
            $message = RDGBLOCKS_NAME.': Anerror_log occurred while trying to clear the cache.';
           error_log(print_r(['error' => $error, 'message' => $message, 'attributes' => $attributes], true));

            return __($message);
        }

        if ($error == 'refresh_cache') {
            $message = RDGBLOCKS_NAME.': Error trying to update cache.';
           error_log(print_r(['error' => $error, 'message' => $message, 'attributes' => $attributes], true));

            return __($message);
        }

        if ($error == 'create_directory') {
            $message = RDGBLOCKS_NAME.': Error trying to create directory.';
           error_log(print_r(['error' => $error, 'message' => $message, 'attributes' => $attributes], true));

            return __($message);
        }

        if ($error == 'update_cache') {
           error_log(sprintf(
                '%s: Type %s ID %s Block %s. The cache was successfully regenerated.',
                RDGBLOCKS_NAME,
                $attributes['page_type'],
                $attributes['post_id'],
                $attributes['block_name'],
            ));

            return;
        }

        $message = RDGBLOCKS_NAME.': The data could not be accessed, please try again later.';
        error_log(print_r(['error' => $error, 'message' => $message, 'attributes' => $attributes], true));

        return $message;
    }

    public function getMenus() {
        global $rdgb;
        $menus = [];
        $blocks = $rdgb->settings->getBlocks();

        foreach ($blocks as $block) {
            if ($block->isConfig()) {
                $config = $block->getConfig();
                $menus[] = $config;
            }
        }

        return $menus;
    }

    public function initRedis() {
        global $wp_object_cache;

        if (isset($wp_object_cache->redis) && $wp_object_cache->redis instanceof \Redis) {
            return true;
        }

        return false;
    }

    public function isRedisActive() {
        return $this->redis_cache;
    }

    public function setRedisGroup($group = '') {
        $this->redis_cache_group = $group;
    }

    public function setRedis($key, $data, $expire = 0) {
        wp_cache_set($key, $data, $this->redis_cache_group, $expire);

        return true;
    }

    public function getRedis($key) {
        return wp_cache_get($key, $this->redis_cache_group);
    }

    public function updateRedis($key, $data, $expire = 0) {
        wp_cache_replace($key, $data, $this->redis_cache_group, $expire);

        return true;
    }

    public function deleteRedis($key) {
        wp_cache_delete($key, $this->redis_cache_group);

        return true;
    }

    public function getImageSource($url_image, $attributes = [])
    {
        $baseURL = get_bloginfo('url');
        //Force WPML to use the English version URL for images
        global $sitepress;
        if (isset($sitepress)) {
            $current_language = $sitepress->get_current_language();
            if ($current_language == 'es' || stripos($baseURL, "/es/") !== false) {
                $baseURL = str_ireplace("/es/", "", $baseURL);
            }
        }

        $alt_image = '';

        if (!file_exists($this->cache_dir)) {
            try {
                mkdir($this->cache_dir);
            } catch (Exception $exception) {
               error_log(print_r([
                    'message' => 'Error: Creating the cache directory.',
                    'directory' => $this->cache_dir,
                    'exception' => $exception->getMessage(),
                ], true));

                return ['url' => $url_image, 'alt' => $alt_image];
            }
        }

        if (!file_exists($this->cache_dir . 'images')) {
            try {
                mkdir($this->cache_dir . 'images');
            } catch (Exception $exception) {
               error_log(print_r([
                    'message' => 'Error: Creating the image directory.',
                    'directory' => $this->cache_dir . 'images',
                    'exception' => $exception->getMessage(),
                ], true));

                return ['url' => $url_image, 'alt' => $alt_image];
            }
        }

        try {
            $image_file = $this->getImageName($url_image, $attributes['image_alt']);
            $alt_image = ($attributes['logo_label']) ? $image_file['alt'] . ' Logo' : $image_file['alt'];
            $image_file['name'] = sanitize_file_name($image_file['name']);

            $name_image = $image_file['name'] . '.' . $image_file['extension'];
            $image = $this->cache_dir . 'images/' . $name_image;
            $new_image = $baseURL . RDGBLOCKS_BASE_PATH . $name_image;

        } catch (Exception $exception) {
           error_log(print_r([
                'message' => 'Error: Creating the image name.',
                'url_image' => $url_image,
                'exception' => $exception->getMessage(),
            ], true));

            return ['url' => $url_image, 'alt' => $alt_image];
        }

        $image_reducer = $this->cache_dir . 'images/' . $image_file['name'] . '.webp';
        $new_image_reducer = $baseURL . RDGBLOCKS_BASE_PATH . $image_file['name'] . '.webp';

        if (file_exists($image_reducer)) {
            return ['url' => $new_image_reducer, 'alt' => $alt_image];
        } else {
            if ($this->isInstallShortpixel() && $this->isActiveShortpixel()) {
                $this->addImageReducer([$url_image]);
            }
        }

        if (file_exists($image)) {
            return ['url' => $new_image, 'alt' => $alt_image];
        } else {
            try {
                $url_image_parts = explode("/", $url_image);
                $url_image_parts_names = array_pop($url_image_parts);
                $url_image_parts_names = explode(".", $url_image_parts_names);
                $url_image_parts_name_new = rawurlencode($url_image_parts_names[0]);
                $new_image = implode("/", $url_image_parts) . "/" . $url_image_parts_name_new . "." . $url_image_parts_names[1];

                copy($new_image, $image);

                return ['url' => $new_image, 'alt' => $alt_image];
            } catch (Exception $exception) {
                if (file_exists($image)) {
                    unlink($image);
                }

               error_log(print_r([
                    'message' => 'Error: creating the image.',
                    'image' => $image,
                    'url_image' => $url_image,
                    'exception' => $exception->getMessage(),
                ], true));
            }
        }

        return ['url' => $url_image, 'alt' => $alt_image];
    }

    public function createImageReducer($new_image) {
        if (!file_exists($this->cache_dir.'images')) {
            try {
                mkdir($this->cache_dir.'images');
            } catch (Exception $exception) {
               error_log(print_r([
                    'message' => 'Error: Creating the image directory.',
                    'directory' => $this->cache_dir.'images',
                    'exception' => $exception->getMessage(),
                ], true));

                return false;
            }
        }

        try {
            $name_image = $new_image['name'].'.webp';
            $image = $this->cache_dir.'images/'.$name_image;

            if (!file_exists($image)) {
                copy($new_image['reducer_url'], $image);
            }
        } catch (Exception $exception) {
           error_log(print_r([
                'message' => 'Error: Creating the image reducer.',
                'new_image' => $new_image,
                'exception' => $exception->getMessage(),
            ], true));

            return false;
        }

        return true;
    }

    public function getImageName($url_image, $alt_image = '') {
        $alt = (!empty($alt_image)) ? $alt_image : '';
        $name = '';
        $extension = '';

        if (empty($url_image) || strpos($url_image, '/') == false) {
            return ['alt' => $alt, 'name' => $name, 'extension' => $extension];
        }

        $url_parts = explode('/', $url_image);

        if (is_array($url_parts) && count($url_parts) > 0) {
            $image = $url_parts[count($url_parts)-1];

            if (strpos($image, '.') == false) {
                return ['alt' => $alt, 'name' => $name, 'extension' => $extension];
            }

            $image_parts = explode('.', $image);
            $extension = strtolower($image_parts[count($image_parts) - 1]);
            array_pop($image_parts);

            if (count($image_parts) == 1) {
                $name = strtolower($image_parts[0]);
            } else {
                $name = strtolower(implode('-', $image_parts));
            }

            $alt = (!empty($alt_image)) ? $alt_image : str_replace(['-', '_'], ' ', $name);
        }

        return ['alt' => $alt, 'name' => $name, 'extension' => $extension];
    }

    public function isInstallShortpixel() {
        if (in_array('shortpixel-image-optimiser/wp-shortpixel.php', apply_filters('active_plugins', get_option('active_plugins')))) {
            return true;
        }
        
        return false;
    }

    public function isActiveShortpixel() {
        $short_pixel = (isset(get_field('rdg_resource_short_pixel_group', 'option')['short_pixel_active']))
            ? get_field('rdg_resource_short_pixel_group', 'option')['short_pixel_active']
            : 'none';
        
        return ($short_pixel == 'active') ? true : false;
    }

    public function getMaxChunksShortpixel() {
        $max_chunks = (isset(get_field('rdg_resource_short_pixel_group', 'option')['max_chunks']))
            ? intval(get_field('rdg_resource_short_pixel_group', 'option')['max_chunks'])
            : 10;
        
        return $max_chunks;
    }

    public function getRedisKeyQueueShortpixel() {
        return 'short_pixel_reducer_queue';
    }

    public function addImageReducer($array_images = []) {
        try {
            $images_queue = [];
            $key = $this->getRedisKeyQueueShortpixel();

            if ($this->initRedis()) {
                $this->setRedisGroup(REDIS_GROUP_BLOCKS);
                $serialized_images = $this->getRedis($key);
        
                if (!empty($serialized_images)) {
                    $images_queue = unserialize($serialized_images);
                }

                foreach ($array_images as $new_image) {
                    if (!in_array($new_image, $images_queue)) {
                        $images_queue[] = $new_image;
                    }
                }

                $this->setRedis($key, serialize($images_queue));
            } else {
               error_log(print_r([
                    'message' => 'RDG Blocks: Redis needs to be enabled to handle image queue.',
                    'array_images' => $array_images
                ], true));
            }
        } catch (\Exception $exection) {
           error_log(print_r([
                'exception' => $exection->getMessage(),
                'array_images' => $array_images
            ], true));
        }
    }

    public function getKeyShortpixel() {
        return get_option('wp-short-pixel-apiKey');
    }

    public function getUrlShortpixel() {
        return 'https://api.shortpixel.com/v2/reducer.php';
    }

    public function getSporstCategoriesOptions($is_sub_title = false) {
        $sport_titles = [];
        $key = 'rdg_blocks_sports_categories_select_option';

        if ($this->initRedis()) {
            $this->setRedisGroup(REDIS_GROUP_BLOCKS);
            $data_titles = $this->getRedis($key);
    
            if (!empty($data_titles)) {
                $unserialize_data = unserialize($data_titles);

                if (is_array($unserialize_data) && count($unserialize_data) > 0) {
                    return $unserialize_data;
                }
            }
        }

        $titles = get_field('sports_categories', 'option');

        if (is_array($titles) && count($titles) > 0) {
            foreach ($titles as $title) {
                if (is_array($title['categories']) && count($title['categories']) > 0 && $is_sub_title) {
                    $sub_titles = [];
                    $sub_titles[$title['sport_id']] = $title['sport_title'] .' - '. __('ANY CATEGORY');

                    foreach ($title['categories'] as $sub_title) {
                        $sub_titles[$title['sport_id'].'-'.$sub_title['category_id']] = $sub_title['category_title'];
                    }
                } else {
                    $sub_titles = $title['sport_title'];
                }

                if (is_array($sub_titles)) {
                    $sport_titles[$title['sport_title']] = $sub_titles;
                } else {
                    $sport_titles[$title['sport_id']] = $sub_titles;
                }
            }

            if ($this->initRedis() && is_array($sport_titles) && count($sport_titles) > 0) {
                $this->setRedis($key, serialize($sport_titles), REDIS_TIMEOUT);
            }
        }

        return $sport_titles;
    }

    public function getSporstCategoriesTitles($is_sub_title = false) {
        $sport_titles = [];
        $key = 'rdg_blocks_sports_categories';
        
        if ($this->initRedis()) {
            $this->setRedisGroup(REDIS_GROUP_BLOCKS);
            $data_titles = $this->getRedis($key);
    
            if (!empty($data_titles)) {
                $unserialize_data = unserialize($data_titles);

                if (is_array($unserialize_data) && count($unserialize_data) > 0) {
                    return $unserialize_data;
                }
            }
        }

        $titles = get_field('sports_categories', 'option');
        
        if (is_array($titles) && count($titles) > 0) {
            foreach ($titles as $title) {
                if (is_array($title['categories']) && count($title['categories']) > 0 && $is_sub_title) {
                    $sport_titles[$title['sport_id']] = $title['sport_title'];

                    foreach ($title['categories'] as $sub_title) {
                        $sport_titles[$title['sport_id'].'-'.$sub_title['category_id']] = $title['sport_title'].' | '.$sub_title['category_title'];
                    }
                } else {
                    $sport_titles[$title['sport_id']] = $title['sport_title'];
                }
            }

            if ($this->initRedis() && is_array($sport_titles) && count($sport_titles) > 0) {
                $this->setRedis($key, serialize($sport_titles), REDIS_TIMEOUT);
            }
        }

        return $sport_titles;
    }

    public function getSporstPartsOptions($is_sub_title = false) {
        $sport_titles = [];
        $key = 'rdg_blocks_sports_parts_select_option';

        if ($this->initRedis()) {
            $this->setRedisGroup(REDIS_GROUP_BLOCKS);
            $data_titles = $this->getRedis($key);
    
            if (!empty($data_titles)) {
                $unserialize_data = unserialize($data_titles);

                if (is_array($unserialize_data) && count($unserialize_data) > 0) {
                    return $unserialize_data;
                }
            }
        }

        $titles = get_field('sports_categories', 'option');

        if (is_array($titles) && count($titles) > 0) {
            foreach ($titles as $title) {
                if (is_array($title['parts']) && count($title['parts']) > 0 && $is_sub_title) {
                    $sub_titles = [];
                    $sub_titles[$title['sport_id']] = $title['sport_title'] .' - '. __('ANY PARTS');

                    foreach ($title['parts'] as $sub_title) {
                        $sub_titles[$title['sport_id'].'-'.$sub_title['part_id']] = $sub_title['part_title'];
                    }
                } else {
                    $sub_titles = $title['sport_title'];
                }

                if (is_array($sub_titles)) {
                    $sport_titles[$title['sport_title']] = $sub_titles;
                } else {
                    $sport_titles[$title['sport_id']] = $sub_titles;
                }
            }

            if ($this->initRedis() && is_array($sport_titles) && count($sport_titles) > 0) {
                $this->setRedis($key, serialize($sport_titles), REDIS_TIMEOUT);
            }
        }

        return $sport_titles;
    }

    public function rdgPagination($current, $total) {
        $big = 999999999; // need an unlikely integer

        $pagination =  paginate_links([
            'base' => str_replace($big, '%#%', esc_url(get_pagenum_link($big))),
            'format' => '/page/%#%',
            'current' => (int) $current,
            'total' =>  (int) $total,
            'type' => 'array' 
        ]);

        echo '<nav><ul class="pagination">';

        foreach ($pagination ?? array() as $element) {
            $dom = new DomDocument();
            $dom->loadHTML($element);
            $page = '';

            foreach($dom->getElementsByTagName('a') as $a) {
                $parts = array_filter(explode('/', $a->getAttribute('href')), 'strlen');
                $page = $parts[count($parts)];
            }

            if (strpos($page, '=')) {
                $page = explode('=', $page)[1];
            }

            echo '<li class="page-item ">' . str_replace('class="', 'data-page="'.$page.'" class="page-link ', $element) . '</li>';
        }

        echo '</ul></nav>';
    }

    function rdgDebugRequest($api_attributes) {
        if (get_field('rdg_blocks_debug_request', 'options') != 'active') return false;

        if (is_user_logged_in() && current_user_can('administrator') && isset($api_attributes['request']) && !empty($api_attributes['request'])) {
            return true;
        }

        return false;
    }

    public function validateFields($fields, $data) {
        $validate = true;

        if (is_array($fields) && count($fields) > 0) {
            foreach ($fields as $field => $validations) {
                if (in_array('required', $validations) && !isset($data[$field])) {
                    $validate = false;
                }

                if (in_array('notnull', $validations) && isset($data[$field])) {
                    $value = $data[$field];
                    
                    // For numeric fields (like num_picks), allow 0 as a valid value
                    // Check if field name suggests it's numeric
                    $is_numeric_field = (strpos($field, 'num_') !== false || strpos($field, 'picks') !== false || strpos($field, 'count') !== false);
                    
                    if ($is_numeric_field) {
                        // For numeric fields, only fail if value is null, empty string, or false (but not 0)
                        if ($value === null || $value === '' || $value === false) {
                            $validate = false;
                        }
                        // Note: 0, '0', and 0.0 are all valid and will pass
                    } else {
                        // For other fields, use standard empty() check
                        if (empty($value)) {
                            $validate = false;
                        }
                    }
                }

                if (!$validate) {
                    break;
                }
            }
        }

        return $validate;
    }

    public function rdgDebugCache($cache_file) {
        if (empty($cache_file)) return false;
        if (get_field('rdg_blocks_debug_cache', 'options') != 'active') return false;
        
        $file_exists = file_exists($this->cache_dir.$cache_file);

        if (is_user_logged_in() && current_user_can('administrator') && $file_exists) {
            return true;
        }

        return false;
    }

    public function rdgApiRequest($url) { 
        $response = wp_remote_get($url);
        
        if (wp_remote_retrieve_response_code($response) !== 200) {
            return null;
        }
        
        return json_decode(wp_remote_retrieve_body($response), true);
    }

    public function isInstallPlugin($plugin) {
        if (in_array($plugin, apply_filters('active_plugins', get_option('active_plugins')))) {
            return true;
        }
        
        return false;
    }

    public function isInstallAcfe() {
        if ($this->isInstallPlugin('acf-extended-pro/acf-extended.php')) {
            return true;
        }

        if ($this->isInstallPlugin('acf-extended/acf-extended.php')) {
            return true;
        }
        
        return false;
    }

    public function isInstallGeneratePress() {
        $current_theme = wp_get_theme();

        # Check if the active theme is generatePress
        if ('generatepress' == $current_theme->get('TextDomain')) {
            return true;
        }

        # Check if the active theme is a child of a generatePress theme
        if ('generatepress' == $current_theme->get('Template')) {
            return true;
        }
        
        return false;
    }

    public function getBlocksStylesLoad() {
        $i = 0;
        $blocks_load = [];

        $rdgb = Rdg_Blocks::instance();
        $blocks = $rdgb->settings->getBlocks();

        foreach ($blocks as $block) {
            if ($block->isStylesLoad()) {
                $blocks_load[$block->getBlockName()] = $block;
            }
        }

        return $blocks_load;
    }

    public function registerGeneratePressColors($colors, $saved_colors, $options) {
        $colors_new = [];
        foreach ($colors as $key => $color) {
            if (!in_array($color['slug'], $saved_colors)) {
                $colors_new[] = $color;
            }
        }

        if (is_array($colors_new) && count($colors_new) > 0) {
            $generatepress_colors = array_merge($options['global_colors'], $colors_new);
            $options['global_colors'] = $generatepress_colors;
            update_option('generate_settings', $options);
        }

        return $options;
    }

    public function getDefaultColors() {
        return [
            [
                'name' => __( 'Contrast', 'generatepress' ),
                'slug' => 'contrast',
                'color' => '#333333',
            ],
            [
                'name' => sprintf( __( 'Contrast %s', 'generatepress' ), '2' ),
                'slug' => 'contrast-2',
                'color' => '#555555',
            ],
            [
                'name' => sprintf( __( 'Contrast %s', 'generatepress' ), '3' ),
                'slug' => 'contrast-3',
                'color' => '#b4b4b4',
            ],
            [
                'name' => __( 'Base', 'generatepress' ),
                'slug' => 'base',
                'color' => '#f1f1f1',
            ],
            [
                'name' => sprintf( __( 'Base %s', 'generatepress' ), '2' ),
                'slug' => 'base-2',
                'color' => '#f5f5f5',
            ],
            [
                'name' => sprintf( __( 'Base %s', 'generatepress' ), '3' ),
                'slug' => 'base-3',
                'color' => '#eeeeee',
            ],
        ];
    }

    public function registerGeneratePressStyles($styles, $saved_styles, $options) {
        $styles = $this->setDefaultStylesFields($styles);

        $styles_new = [];
        foreach ($styles as $key => $style) {
            if (!in_array($style['customSelector'], $saved_styles)) {
                $styles_new[] = $style;
            }
        }

        if (is_array($styles_new) && count($styles_new) > 0) {
            $generatepress_styles = array_merge($options['typography'], $styles_new);
            $options['typography'] = $generatepress_styles;
            update_option('generate_settings', $options);
        }

        return $options;
    }

    public function setDefaultStylesFields($styles) {
        $default_fields = [
            'customSelector' => '',
            'fontFamily' => '',
            'fontWeight' => '',
            'textTransform' => '',
            'textDecoration' => '',
            'fontStyle' => '',
            'fontSize' => '',
            'fontSizeTablet' => '',
            'fontSizeMobile' => '',
            'lineHeight' => '',
            'lineHeightTablet' => '',
            'lineHeightMobile' => '',
            'letterSpacing' => '',
            'letterSpacingTablet' => '',
            'letterSpacingMobile' => '',
            'marginBottom' => '',
            'marginBottomTablet' => '',
            'marginBottomMobile' => '',
            'marginBottomUnit' => '',
        ];

        $new_styles = [];
        foreach ($styles as $style) {
            $set_styles = array_merge($default_fields, $style);
            $set_styles['selector'] = 'custom';
            $set_styles['module'] = 'core';
            $set_styles['group'] = 'other';
            $new_styles[] = $set_styles;
        }

        return $new_styles;
    }

    public function registerStylesCss($block, $styles) {
        $new_styles = [];
        foreach ($styles as $style) {
            if (!isset($style['customSelector']) || empty($style['customSelector'])) continue;

            $selector = $style['customSelector'];
            unset($style['customSelector']);
            
            $css_array = [];
            $css_array_tablet = [];
            $css_array_mobile = [];
            foreach ($style as $attribute => $value) {
                if (!$this->validAttribute($attribute)) continue;

                if (in_array($attribute, ['fontSizeTablet', 'lineHeightTablet', 'letterSpacingTablet'])) {
                    $tem_css_tablet = $this->convertAttribute($attribute, $value);
                    if (!empty($tem_css_tablet)) {
                        $css_array_tablet[] = $tem_css_tablet;
                    }

                    continue;
                }

                if (in_array($attribute, ['fontSizeMobile', 'lineHeightMobile', 'letterSpacingMobile'])) {
                    $tem_css_mobile = $this->convertAttribute($attribute, $value);
                    if (!empty($tem_css_mobile)) {
                        $css_array_mobile[] = $tem_css_mobile;
                    }

                    continue;
                }
                
                $tem_css = $this->convertAttribute($attribute, $value);
                if (!empty($tem_css)) {
                    $css_array[] = $tem_css;
                }
            }

            if (is_array($css_array) && count($css_array) > 0) {
                $new_styles[] = sprintf('%s { %s }', $selector,implode(' ', $css_array));
            }

            if (is_array($css_array_tablet) && count($css_array_tablet) > 0) {
                $new_styles[] = sprintf('@media (max-width: 1024px) { %s { %s }}', $selector,implode(' ', $css_array_tablet));
            }

            if (is_array($css_array_mobile) && count($css_array_mobile) > 0) {
                $new_styles[] = sprintf('@media (max-width: 768px) { %s { %s }}', $selector,implode(' ', $css_array_mobile));
            }
        }

        $block_name = $block->getBlockName();
        $css_file_block = $this->getCssFileBlock($block_name);

        if (empty($css_file_block)) {
           error_log(print_r([
                'message' => 'RDG Blocks / registerStylesCss: Block css file not found.',
                'block_name' => $block_name,
            ], true));

            return '';
        }

        $this->setCssFileBlock($css_file_block, $new_styles);
    }

    public function setCssFileBlock($css_file, $styles) {
        try {
            # Check if the block styles file exists
            $file_name = RDGBLOCKS_PLUGIN_DIR.'dist/'.$css_file;
            if (!file_exists($file_name)) {
               error_log(print_r([
                    'message' => 'RDG Blocks / setCssFileBlock: Block style file not found.',
                    'css_file' => $css_file,
                ], true));
    
                return;
            }

            # Get the content of the styles file
            $check_content_file = file_get_contents($file_name);

            # Clean old styles
            $clear_css = preg_replace('/\/\*open-auto-code\*\/[\s\S]+?\/\*close-auto-code\*\//', '', $check_content_file);
            
            # Update possible new styles in the block
            $spaces = (strlen($check_content_file) == strlen($clear_css)) ? "\n\n" : "";
            $css_new = $clear_css.$spaces."/*open-auto-code*/".implode(' ', $styles)."/*close-auto-code*/";
            file_put_contents($file_name, $css_new, LOCK_EX);
        } catch (\Exception $exception) {
           error_log(print_r([
                'message' => sprintf('RDG Blocks / setCssFileBlock: %s', $exception->getMessage()),
                'css_file' => $css_file,
                'styles' => $styles,
            ], true));
        }
    }

    public function getCssFileBlock($block_name) {
        try {
            if (!file_exists(RDGBLOCKS_PLUGIN_DIR.'dist/manifest.json')) {
               error_log(print_r([
                    'message' => 'RDG Blocks / getCssFileBlock: Manifest file not found.',
                    'block_name' => $block_name,
                ], true));
    
                return '';
            }
    
            $manifest = RDGBLOCKS_PLUGIN_DIR.'dist/manifest.json';
            $blocks_data = file_get_contents($manifest);
            $blocks_data_array = json_decode($blocks_data, true);

            if (is_array($blocks_data_array) && count($blocks_data_array) > 0) {
                if (isset($blocks_data_array[str_replace('-', '_', $block_name).'.css'])) {
                    return $blocks_data_array[str_replace('-', '_', $block_name).'.css'];
                }
            }
        } catch (\Exception $exception) {
           error_log(print_r([
                'message' => sprintf('RDG Blocks / getCssFileBlock: %s', $exception->getMessage()),
                'block_name' => $block_name,
            ], true));
        }

        return '';
    }

    public function convertAttribute($attribute, $value) {
        #Options: normal, bold, 100, 200, 300, 400, 500, 600, 700, 800, 900
        if ($attribute == 'fontWeight') {
            return sprintf('font-weight: %s;', $value);
        }

        #Options: uppercase, lowercase, capitalize, initial
        if ($attribute == 'textTransform') {
            return sprintf('text-transform: %s;', $value);
        }

        #Options: none, underline
        if ($attribute == 'textDecoration') {
            return sprintf('text-decoration: %s;', $value);
        }

        #Options: normal, italic, oblique, initial
        if ($attribute == 'fontStyle') {
            return sprintf('font-style: %s;', $value);
        }

        #Options: 15px, 2.5rem, 1.7em, 10%
        if (in_array($attribute, ['fontSize', 'fontSizeTablet', 'fontSizeMobile'])) {
            return sprintf('font-size: %s;', $value);
        }

        #Options: 15px, 2.5rem, 1.7em, 10%
        if (in_array($attribute, ['lineHeight', 'lineHeightTablet', 'lineHeightMobile'])) {
            return sprintf('line-height: %s;', $value);
        }

        #Options: 15px, 2.5rem, 1.7em, 10%
        if (in_array($attribute, ['letterSpacing', 'letterSpacingTablet', 'letterSpacingMobile'])) {
            return sprintf('letter-spacing: %s;', $value);
        }

        return '';
    }

    public function validAttribute($attribute) {
        return in_array($attribute, ['fontWeight', 'fontSize', 'fontSizeTablet', 'fontSizeMobile', 'textTransform', 
            'textDecoration', 'fontStyle', 'lineHeight', 'lineHeightTablet', 'lineHeightMobile', 'letterSpacing', 
        'letterSpacingTablet', 'letterSpacingMobile']);
    }

    public function getBaseColors() {
        return [
            ['name' => 'color-white','slug' => 'color-white','color' => '#FFFFFF'],
            ['name' => 'color-black','slug' => 'color-black','color' => '#111111'],
            ['name' => 'color-primary','slug' => 'color-primary','color' => '#3a96e0'],
            ['name' => 'color-primary-dark','slug' => 'color-primary-dark','color' => '#03467d'],
            ['name' => 'color-primary-dark-light','slug' => 'color-primary-dark-light','color' => '#0160ac'],
            ['name' => 'color-gray','slug' => 'color-gray','color' => '#F1F1F1'],
            ['name' => 'color-gray-line','slug' => 'color-gray-line','color' => '#CCC'],
            ['name' => 'color-danger','slug' => 'color-danger','color' => '#e11414'],
            ['name' => 'color-danger-dark','slug' => 'color-danger-dark','color' => '#891010'],
            ['name' => 'color-danger-light','slug' => 'color-danger-light','color' => '#fc6363'],
            ['name' => 'color-warning','slug' => 'color-warning','color' => '#e69305'],
            ['name' => 'color-warning-dark','slug' => 'color-warning-dark','color' => '#9f6809'],
            ['name' => 'color-warning-light','slug' => 'color-warning-light','color' => '#f5c776'],
            ['name' => 'color-success','slug' => 'color-success','color' => '#00bc00'],
            ['name' => 'color-success-dark','slug' => 'color-success-dark','color' => '#244d0e'],
            ['name' => 'color-success-light','slug' => 'color-success-light','color' => '#68f96e'],
        ];
    }

    public function getPlayerName($player_id, $players, $field = 'full-name') {
        if (empty($player_id) || !is_array($players) || (is_array($players) && count($players) == 0) || !isset($players[$player_id])) {
            return $player_id;
        }

        $first_name = isset($players[$player_id]['first_name']) && !empty($players[$player_id]['first_name']) ? $players[$player_id]['first_name'] : '';
        $last_name = isset($players[$player_id]['last_name']) && !empty($players[$player_id]['last_name']) ? $players[$player_id]['last_name'] : '';

        if ($field == 'full-name') {
            if (!empty($first_name) || !empty($last_name)) {
                return $first_name.' '.$last_name;
            }
        }

        if ($field == 'first_name') {
            return $first_name;
        }

        if ($field == 'last_name') {
            return $last_name;
        }

        return $player_id;
    }

    public function checkExistsTraceFunction($traces, $max_trace, $functions) {
        try {
            if (is_array($traces) && count($traces) > 0) {
                $traces_serialize = $this->arrayToString($traces);

                foreach ($functions as $function) {
                    if (strpos($traces_serialize, $function) !== false) {
                        return true;
                    }
                }
            }
        } catch (\Exception $exception) {
            error_log(print_r([
                'message' => sprintf('RDG Blocks / getBacktrace: %s', $exception->getMessage()),
                'max_trace' => $max_trace,
                'functions' => $functions,
            ], true));
        }

        return false;
    }

    public function getBacktraceConfig() {
        $backtrace_config = [
            'max_trace' => 30,
            'functions' => ['wp_update_post', 'wp_insert_post', 'edit_post'],
        ];

        try {
            if (defined('RDG_BLOCK_BACKTRACE')) {
                $backtrace_config = json_decode(RDG_BLOCK_BACKTRACE, true);
            }
        } catch (\Exception $exception) {
            error_log(print_r([
                'message' => sprintf('RDG Blocks / getBacktraceConfig: %s', $exception->getMessage()),
                'backtrace_config' => $backtrace_config,
            ], true));
        }

        return $backtrace_config;
    }

    public function arrayToString($array, $separator = ",") {
        $flatArray = [];

        array_walk_recursive($array, function($value, $key) use (&$flatArray) {
            if ($key == 'function') {
                $flatArray[] = $value;
            }
        });

        return implode($separator, $flatArray);
    }

    public function getShGameSlug() {
        if (defined('SHG_SLUG')) {
            $slug = json_decode(SHG_SLUG, true);
        } else {
            error_log(print_r([
                'message' => RDGBLOCKS_NAME_SLUG.': The constant SHG_SLUG is not defined.',
            ], true));

            $slug = [
                'slug' => 'previews',
                'label' => 'Previews',
            ];
        }

        return $slug;
    }

    public function getBlocksCacheListName() {
        return RDGBLOCKS_NAME_SLUG.':cache';
    }

    public function getRedisConnect() {
        try {
            $redis = new Redis();
            $redis->connect(WP_REDIS_HOST, WP_REDIS_PORT);

            // Select Redis database (defaults to 0 if not defined)
            // Uses the same database as WordPress Redis Object Cache for consistency
            $redis_db = defined('WP_REDIS_DATABASE') ? WP_REDIS_DATABASE : 0;
            $redis->select($redis_db);

            return $redis;
        } catch (\Exception $exception) {
            error_log(print_r([
                'exception' => sprintf('RDG Blocks / getRedisConnect: %s', $exception->getMessage()),
            ], true));
        }

        return null;
    }

    public function getCacheList($redis) {
        if (is_null($redis)) {
            $redis = $this->getRedisConnect();
        }

        if (!is_null($redis)) {
            return $redis->lrange($this->getBlocksCacheListName(), 0, -1);
        }

        return [];
    }

    public function addCacheList($redis, $name, $refresh, $data) {
        try {
            if (is_null($redis)) {
                $redis = $this->getRedisConnect();
            }

            $redis->rpush($this->getBlocksCacheListName(), $name);
            $redis->set($name, json_encode($data), $refresh * 60 * 60);

            return true;
        } catch (\Exception $exception) {
            error_log(print_r([
                'exception' => sprintf('RDG Blocks / addCacheList: %s', $exception->getMessage()),
                'name' => $name,
                'refresh' => $refresh,
                'data' => $data,
            ], true));
        }

        return false;
    }

    public function getCacheBlock($name) {
        try {
            if (is_null($redis)) {
                $redis = $this->getRedisConnect();
            }

            $redis->get($name, json_encode($data), $refresh * 60 * 60);

            return true;
        } catch (\Exception $exception) {
            error_log(print_r([
                'exception' => sprintf('RDG Blocks / addCacheList: %s', $exception->getMessage()),
                'name' => $name,
                'refresh' => $refresh,
                'data' => $data,
            ], true));
        }

        return false;
    }
}
