<?php

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

/**
 * HELPER COMMENT START
 * 
 * This class is used to bring your plugin to life. 
 * All the other registered classed bring features which are
 * controlled and managed by this class.
 * 
 * Within the add_hooks() function, you can register all of 
 * your WordPress related actions and filters as followed:
 * 
 * add_action( 'my_action_hook_to_call', array( $this, 'the_action_hook_callback', 10, 1 ) );
 * or
 * add_filter( 'my_filter_hook_to_call', array( $this, 'the_filter_hook_callback', 10, 1 ) );
 * or
 * add_shortcode( 'my_shortcode_tag', array( $this, 'the_shortcode_callback', 10 ) );
 * 
 * Once added, you can create the callback function, within this class, as followed: 
 * 
 * public function the_action_hook_callback( $some_variable ){}
 * or
 * public function the_filter_hook_callback( $some_variable ){}
 * or
 * public function the_shortcode_callback( $attributes = array(), $content = '' ){}
 * 
 * 
 * HELPER COMMENT END
 */

/**
 * Class Rdg_Blocks_Run
 *
 * Thats where we bring the plugin to life
 *
 * @package		RDGBLOCKS
 * @subpackage	Classes/Rdg_Blocks_Run
 * @author		RDGCorp
 * @since		1.0.0
 */
class Rdg_Blocks_Run {
    /**
     * Our Rdg_Blocks_Run constructor 
     * to run the plugin logic.
     *
     * @since 1.0.0
     */

    function __construct() {
        $this->add_hooks();
    }

    /**
     * ######################
     * ###
     * #### WORDPRESS HOOKS
     * ###
     * ######################
     */

    /**
     * Registers all WordPress and plugin related hooks
     *
     * @access	private
     * @since	1.0.0
     * @return	void
     */

    private function add_hooks() {
        add_action('admin_enqueue_scripts', array( $this, 'enqueue_backend_scripts_and_styles'), 20);
        add_action('acf/init', array( $this, 'add_custom_acf_options_page'), 20);
        register_activation_hook(RDGBLOCKS_PLUGIN_FILE, array( $this, 'activation_hook_callback'));
        add_action('acf/input/admin_enqueue_scripts', array( $this, 'custom_acf_admin_enqueue_scripts'));

        add_action('admin_menu', [$this, 'rdg_add_admin_page']);

    }

    public function rdg_add_admin_page() {
        add_menu_page(
            'Blocks Cache',
            'RDG Blocks Cache',
            'manage_options',
            'rdg-cached-blocks',
            [$this, 'rdg_display_cached_blocks'],
            'dashicons-database',
            82
        );
    }

    public function rdg_display_cached_blocks() {
        $cache = new Rdg_Blocks_Cache();
        $connect = $cache->getRedisConnect();

        if (!$connect) {
            echo '<div class="wrap">';
            echo '<h1>Redis connection error</h1>';
            echo '<div class="notice notice-warning"><p><strong>Redis:</strong> Redis connection failed.</p></div>';
            echo '</div>';
            return;
        }

        $per_pages_valid = [20, 30, 50];
        $filter_type = isset($_GET['filter_type']) ? sanitize_text_field($_GET['filter_type']) : null;
        $filter_type_id = isset($_GET['filter_type_id']) ? sanitize_text_field($_GET['filter_type_id']) : null;
        $filter_block_type = isset($_GET['filter_block_type']) ? sanitize_text_field($_GET['filter_block_type']) : null;
        $filter_block_status = isset($_GET['filter_block_status']) ? sanitize_text_field($_GET['filter_block_status']) : null;
        $per_page = isset($_GET['filter_per_page']) ? sanitize_text_field($_GET['filter_per_page']) : 20;
        $per_page = in_array($per_page, $per_pages_valid) ? $per_page : 20;
        $current_page = isset($_GET['paged']) ? sanitize_text_field($_GET['paged']) : 1;

        $data_filter_type = [];
        $data_filter_type_ids = [];
        $data_filter_block_types = [];
        $data_filter_block_status = ['active', 'retrying', 'paused'];
        $blocks = $cache->getCacheList();

        $filtered_blocks = [];
        foreach ($blocks as $block) {
            [$block_name, $block_type, $block_type_id, $cache_name] = explode(':', $block);

            if (!in_array($block_type, $data_filter_type)) {
                $data_filter_type[] = $block_type;
            }

            if (!in_array($block_type_id, $data_filter_type_ids)) {
                $data_filter_type_ids[] = $block_type_id;
            }

            if (!in_array($block_name, $data_filter_block_types)) {
                $data_filter_block_types[] = $block_name;
            }

            if (!empty($filter_type) && $block_type !== $filter_type) continue;
            if (!empty($filter_type_id) && $block_type_id !== $filter_type_id) continue;
            if (!empty($filter_block_type) && $block_name !== $filter_block_type) continue;

            if (!empty($filter_block_status)) {
                $failed_name = $cache->getCacheFailedName($block);
                $failed_block = $cache->getCacheBlock($failed_name);

                if (
                    ($filter_block_status === 'active' && !empty($failed_block)) ||
                    ($filter_block_status === 'retrying' && (empty($failed_block) || $failed_block === RDG_BLOCK_CACHE_FAILED_RETRY)) ||
                    ($filter_block_status === 'paused' && $failed_block !== RDG_BLOCK_CACHE_FAILED_RETRY)
                ) {
                    continue;
                }
            }

            $data_block_json = $cache->getCacheBlock($block);
            if (empty($data_block_json)) {
                $cache->delCacheBlock($block);
                continue;
            }

            $filtered_blocks[] = $block;
        }

        $total_items = count($filtered_blocks);
        $total_pages = ceil($total_items / $per_page);
        $offset = ($current_page - 1) * $per_page;
        $blocks_paginated = array_slice(array_values($filtered_blocks), $offset, $per_page);

        echo '<div class="wrap">';
        echo '<h1>Cached Blocks in Redis</h1>';
        echo '<table class="widefat fixed filters_cache">';
        echo '<thead><tr><th>';

        echo '<select class="filter_cache" id="filter_type">';
        echo '<option value="">All Post Types</option>';
        echo '</select>';

        echo '<select class="filter_cache" id="filter_type_id">';
        echo '<option value="">All Post IDs</option>';
        echo '</select>';

        echo '<select class="filter_cache" id="filter_block_type">';
        echo '<option value="">All RDG Blocks</option>';
        echo '</select>';

        echo '<select class="filter_cache" id="filter_block_status">';
        echo '<option value="">All Status</option>';
        echo '</select>';

        echo '<select class="filter_cache" id="filter_per_page">';
            $selected = 20;
            foreach ($per_pages_valid as $option) {
                $selected = ($per_page == $option) ? 'selected' : '';
                echo "<option value='{$option}' {$selected}>{$option}</option>";
            }
        echo '</select>';

        echo '<a name="redis-cache-delete-all" href="#" class="button">Delete All</a>';
        echo '<a name="redis-cache-delete-selected" href="#" class="button">Delete Selected</a>';
        echo '<a name="redis-cache-filter-clear" href="#" class="button">Reset Filter</a>';

        echo '</th></tr></thead><tbody>';
        echo '</tbody></table>';
        echo '</div>';

        echo '<div class="wrap">';
        echo '<table class="widefat fixed filters_cache_data">';
        echo '<thead><tr>';
        echo '<th class="item">#</th>';
        echo '<th class="time">Time</th>';
        echo '<th class="name">Name</th>';
        echo '<th class="request">Request</th>';
        echo '<th class="data">Data</th>';
        echo '<th class="actionsb">Actions</th>';
        echo '</tr></thead>';
        echo '<tbody>';

        $i = 1;
        foreach ($blocks_paginated as $block) {
            $data_block_json = $cache->getCacheBlock($block);
            $time = $cache->getCacheBlockTime($block);
            $data_block = json_decode($data_block_json, true);
            
            echo '<tr class="item_'.$block.'">';
            echo '<td>' . $offset + $i . '</td>';
            echo '<td>' . $time . '</td>';
            echo '<td>' . esc_html($block) . '</td>';
            echo '<td><pre style="max-height: 5rem;">' . print_r($data_block['api_attributes'], true) . '</pre></td>';
            echo '<td class="api_response_item_'.$block.'"><pre style="max-height: 5rem;">' . print_r($data_block['api_response'], true) . '</pre></td>';
            echo '<td class="actions">';
            echo '<a name="redis-cache-delete" data-cache="'.$block.'" href="#" class="button">Delete</a>';
            echo '<a name="redis-cache-update" data-cache="'.$block.'" href="#" class="button">Generate</a>';
            echo '</td>';
            echo '</tr>';

            $i++;
        }

        ?>
        <script>
            let jsonData = <?php echo json_encode([
                'data_filter_type' => $data_filter_type,
                'data_filter_type_ids' => $data_filter_type_ids,
                'data_filter_block_types' => $data_filter_block_types,
                'data_filter_block_status' => $data_filter_block_status,
                'selected' => [
                    'filter_type' => $filter_type,
                    'filter_type_id' => $filter_type_id,
                    'filter_block_type' => $filter_block_type,
                    'filter_block_status' => $filter_block_status,
                ],
            ]); ?>;
        </script>
        <?php

        echo '</tbody></table>';
        echo '</div>';

        echo '<div class="wrap pagination_cache_data"><nav class="cache-pagination">';
            for ($i = 1; $i <= $total_pages; $i++) {
                $url = add_query_arg([
                    'paged' => $i,
                    'filter_type' => $filter_type,
                    'filter_type_id' => $filter_type_id,
                    'filter_block_type' => $filter_block_type,
                    'filter_block_status' => $filter_block_status,
                    'filter_per_page' => $per_page,
                ], admin_url('admin.php?page=rdg-cached-blocks'));

                $active = ($i == $current_page) ? 'active' : '';
                if ($active) $url = '#';

                echo "<a href='{$url}' class='{$active}'>{$i}</a>";
            }
        echo '</nav></div>';

    }


    public function custom_acf_admin_enqueue_scripts() {
        wp_enqueue_script( 'custom-acf-input-js', RDGBLOCKS_PLUGIN_URL.'core/includes/assets/js/ajax_response.js', false, '1.0.0' );
    }

    /**
     * ######################
     * ###
     * #### WORDPRESS HOOK CALLBACKS
     * ###
     * ######################
     */

    /**
     * Enqueue the backend related scripts and styles for this plugin.
     * All of the added scripts andstyles will be available on every page within the backend.
     *
     * @access	public
     * @since	1.0.0
     *
     * @return	void
     */

    public function enqueue_backend_scripts_and_styles($hook) {
        wp_enqueue_style('rdgblocks-backend-styles', RDGBLOCKS_PLUGIN_URL.'core/includes/assets/css/backend-styles.css', [], RDGBLOCKS_VERSION, 'all');
        wp_enqueue_script('rdgblocks-backend-scripts', RDGBLOCKS_PLUGIN_URL.'core/includes/assets/js/backend-scripts.js', [], RDGBLOCKS_VERSION, false);
        wp_localize_script('rdgblocks-backend-scripts', 'rdgblocks', [
            'plugin_name' => __(RDGBLOCKS_NAME, RDGBLOCKS_NAME_SLUG),
        ]);
        wp_localize_script('rdgblocks-backend-scripts', 'rdg_block_var', [
            'ajaxurl' => admin_url('admin-ajax.php'),
        ]);

        if ($hook == 'toplevel_page_rdg-cached-blocks') {
            wp_enqueue_script('rdgblocks-cache-scripts', RDGBLOCKS_PLUGIN_URL.'core/includes/assets/js/rdg-blocks-cache.js', [], RDGBLOCKS_VERSION, false);
        }
    }

    /**
     * Add the Advanced Custom fields
     * options pages
     *
     * @access	public
     * @since	1.0.0
     * @link	https://www.advancedcustomfields.com/resources/acf_add_options_page/
     *
     * @return	void
     */

    public function add_custom_acf_options_page() {
        // Check function exists.
        if(function_exists('acf_add_options_page')) {
            // Register options page.
            acf_add_options_page([
                'page_title' => __('RDG Blocks'),
                'menu_title' => __('RDG Blocks'),
                'menu_slug' => RDGBLOCKS_NAME_SLUG,
                'capability' => 'edit_posts',
                'redirect' => true
            ]);

            global $rdgb;
            if (!empty($rdgb)) {
                $menus = $rdgb->helpers->getMenus();

                $menus[] = [
                    'page_title'  => __('Cache Maintenance'),
                    'menu_title'  => 'Cache Maintenance',
                    'parent_slug' => RDGBLOCKS_NAME_SLUG,
                ];

                $menus[] = [
                    'page_title'  => __('Categories Maintenance'),
                    'menu_title'  => 'Categories Maintenance',
                    'parent_slug' => RDGBLOCKS_NAME_SLUG,
                ];

                $menus[] = [
                    'page_title'  => __('Images Maintenance'),
                    'menu_title'  => 'Images Maintenance',
                    'parent_slug' => RDGBLOCKS_NAME_SLUG,
                ];

                $menus[] = [
                    'page_title'  => 'Resources',
                    'menu_title'  => 'Resources',
                    'parent_slug' => RDGBLOCKS_NAME_SLUG,
                ];

                $menus[] = [
                    'page_title'  => __('Settings'),
                    'menu_title'  => 'Settings',
                    'parent_slug' => RDGBLOCKS_NAME_SLUG,
                ];

                $menus[] = [
                    'page_title'  => 'Sports Categories',
                    'menu_title'  => 'Sports Categories',
                    'parent_slug' => RDGBLOCKS_NAME_SLUG,
                ];

                // $menus[] = [
                //     'page_title'  => 'Redis Cache',
                //     'menu_title'  => 'Redis Cache',
                //     'parent_slug' => RDGBLOCKS_NAME_SLUG,
                // ];

                function compareMenuTitle($a, $b) {
                    return strcmp($a['menu_title'], $b['menu_title']);
                }

                $order_menu = array_values($menus);
                usort($order_menu, 'compareMenuTitle');

                foreach ($order_menu as $key => $menu) {
                    acf_add_options_page(array(
                        'page_title'  => $menu['page_title'],
                        'menu_title'  => $menu['menu_title'],
                        'parent_slug' => RDGBLOCKS_NAME_SLUG,
                    ));
                }
            }
        }
    }

    

    /**
     * ####################
     * ### Activation/Deactivation hooks
     * ####################
     */
        
    /*
    * This function is called on activation of the plugin
    *
    * @access	public
    * @since	1.0.0
    *
    * @return	void
    */

    public function activation_hook_callback() {
        if (!function_exists('is_plugin_active')) {
            require_once ABSPATH . 'wp-admin/includes/plugin.php';
        }
        
        if (!is_plugin_active('advanced-custom-fields-pro/acf.php') && !is_plugin_active('advanced-custom-fields/acf.php')) {
            deactivate_plugins(plugin_basename(__FILE__));
            wp_die(
                'RDGBLOCKS requires Advanced Custom Fields Pro to be active.<br /> <b>Please activate ACF before activating this plugin.</  b>',
                'Activation Error',
                array('back_link' => true)
            );
        }
    }
}

add_action('wp_ajax_nopriv_rdg_blocks_delete_cache_all','deleteAllRdgBlocksCache');
add_action('wp_ajax_rdg_blocks_delete_cache_all','deleteAllRdgBlocksCache');

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

    if (!$connect) {
        error_log(sprintf('%s / deleteAllRdgBlocksCache: Redis connection failed.', RDGBLOCKS_NAME));
        echo 'RDG Blocks: Could not delete cache.';
        wp_die();
    }

    $deleted = $cache->delAllCache();
    if ($deleted) {
        error_log(sprintf('%s / deleteAllRdgBlocksCache: Delete all cache.', RDGBLOCKS_NAME));
        echo 'success';
        wp_die();
    }

    error_log(sprintf('%s / deleteAllRdgBlocksCache: Could not delete all cache.', RDGBLOCKS_NAME));
    echo 'RDG Blocks: Could not delete all cache.';
    wp_die();
}

add_action('wp_ajax_nopriv_rdg_blocks_delete_cache_selected','deleteSelectedRdgBlocksCache');
add_action('wp_ajax_rdg_blocks_delete_cache_selected','deleteSelectedRdgBlocksCache');

function deleteSelectedRdgBlocksCache() {
    $selected = $_POST['selected'];
    if (empty($selected)) wp_die();

    $selected_array = explode(',', $selected);
    if (!is_array($selected_array) || count($selected_array) == 0) {
        error_log(sprintf('%s / deleteSelectedRdgBlocksCache: Selected is not an array.', RDGBLOCKS_NAME));
        wp_die();
    }

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

    if (!$connect) {
        error_log(sprintf('%s / deleteSelectedRdgBlocksCache: Redis connection failed.', RDGBLOCKS_NAME));
        wp_die();
    }

    $cache_deleted = [];
    
    foreach ($selected_array as $block) {
        if (empty($block)) continue;

        $block_name = $block;
        if (substr($block, 0, 5) == 'item_') {
            $block_name = substr($block, 5);
        }

        $deleted = $cache->delCacheBlock($block_name);
        if ($deleted) {
            $cache_deleted[] = $block_name;
        }
    }

    error_log(print_r([
        'message' => sprintf('%s / deleteSelectedRdgBlocksCache: Delete Selected cache.', RDGBLOCKS_NAME),
        'cache_deleted' => $cache_deleted,
    ], true));
    wp_die();
}

add_action('wp_ajax_nopriv_rdg_blocks_delete_cache','deleteRdgBlocksCache');
add_action('wp_ajax_rdg_blocks_delete_cache','deleteRdgBlocksCache');

function deleteRdgBlocksCache() {
    $cache_name = $_POST['cache'];
    if (empty($cache_name)) wp_die();

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

    if (!$connect) {
        error_log(sprintf('%s / deleteRdgBlocksCache: Redis connection failed.', RDGBLOCKS_NAME));
        echo 'RDG Blocks: Could not delete cache.';
        wp_die();
    }

    $deleted = $cache->delCacheBlock($cache_name);

    if (!$deleted) {
        error_log(sprintf('%s / deleteRdgBlocksCache: Failed to delete cache for %s', RDGBLOCKS_NAME, $cache_name));
        wp_die();
    }

    echo 'success';
    error_log(sprintf('%s / deleteRdgBlocksCache: Delete cache %s', RDGBLOCKS_NAME, $cache_name));

    wp_die();
}

add_action('wp_ajax_nopriv_rdg_blocks_update_cache','updateRdgBlocksCache');
add_action('wp_ajax_rdg_blocks_update_cache','updateRdgBlocksCache');

function updateRdgBlocksCache() {
    $cache_name = $_POST['cache'];
    if (empty($cache_name)) wp_die();

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

    if (!$connect) {
        error_log(sprintf('%s / updateRdgBlocksCache: Redis connection failed.', RDGBLOCKS_NAME));
        echo 'RDG Blocks: Could not update cache.';
        wp_die();
    }

    global $rdgb;
    $block = $cache->getCacheBlock($cache_name);
    $attributes = json_decode($block, true);
    $block_name = explode(':', $cache_name)[0];
    $block = $rdgb->settings->getBlock(str_replace('_', '-', $block_name));

    if (is_array($attributes)) {
        $api_attributes = $attributes['api_attributes'];

        $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
            ]);

            echo 'RDG Blocks: Could not update cache.';

            wp_die();
        }

        $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
            ]);

            echo 'RDG Blocks: Could not update cache.';

            wp_die();
        }

        if ($block->isPreSaved()) {
            $attributes['cache_name'] = $cache_name;
            $attributes['block'] = $block;
            $response_json = $block->getPreSavedData($response_json, $attributes);
        }
        
        $updated = $cache->updateCacheBlock($cache_name, $attributes, $response_json);
        if ($updated) {
            $tems = explode(':', $cache_name);
            $rdgb->helpers->getApiError('update_cache', [
                'page_type' => $tems[1],
                'post_id' => $tems[2],
                'block_name' => $block_name,
            ]);

            print_r($response_json);
        } else{
            echo 'RDG Blocks: Could not update cache.';
        }
    }   

    wp_die();
}

