<?php
// Silence may be golden, but sometimes words paint the canvas of understanding.

namespace Plugli\Linksy\SearchAndReplace\Admin\Partials\SearchAndReplace;

use Exception;
use Linksy\SearchAndReplace\Plugli\Linksy\Common\Helpers\Ajax;
use Linksy\SearchAndReplace\Plugli\Linksy\Common\Helpers\Utils as HelpersUtils;
use Linksy\SearchAndReplace\Plugli\Linksy\Common\Helpers\WP_Cron_Manager;
use Linksy\SearchAndReplace\Plugli\Standard\Admin\Partials\Partials as _Partials;
use Linksy\SearchAndReplace\Plugli\Standard\Helpers\Database\Database;
use Linksy\SearchAndReplace\Plugli\Standard\Helpers\Option;
use Plugli\Linksy\SearchAndReplace\Admin\Partials\SearchAndReplace\Events\PeriodicLinkAnalysisCronEvent;
use Plugli\Linksy\SearchAndReplace\Admin\Partials\SearchAndReplace\Events\RunLinkAnalysisCronEvent;
use Plugli\Linksy\SearchAndReplace\Helpers\Post\Post;

/**
 * Search and Replace class.
 */
class SearchAndReplace extends _Partials
{
    use AjaxActions, Utils;

    public $setup_status;
    public $run_link_analysis_event;
    public $periodic_link_analysis_event;

    public function admin_init()
    {
        $this->setup_status = Option::get(LINKSYAI_SAR_OPTION_SETUP_COMPLETE, false);
        $this->page = $this->plugin_name . '-search-and-replace';
        $this->run_link_analysis_event = new RunLinkAnalysisCronEvent('linksy_search_and_replace_analyze_links_interval');
        $this->periodic_link_analysis_event = new PeriodicLinkAnalysisCronEvent('weekly');

        if ($this->setup_status) {
            $post_types = ['post', 'page'];
            foreach ($post_types as $type) {
                $this->action('trash_'.$type, 'on_post_deleted');
                $this->action('save_post_'.$type, 'on_post_created');
            }
        }

        $this->action(Ajax::prefix('search_and_replace_sync_posts'), 'linksy_search_and_replace_sync_posts');
        $this->action(Ajax::prefix('search_and_replace_search_links'), 'linksy_search_and_replace_search_links');
        $this->action(Ajax::prefix('search_and_replace_search_anchors'), 'linksy_search_and_replace_search_anchors');
        $this->action(Ajax::prefix('search_and_replace_search_titles'), 'linksy_search_and_replace_search_titles');
        $this->action(Ajax::prefix('search_and_replace_search_urls'), 'linksy_search_and_replace_search_urls');
        $this->action(Ajax::prefix('search_and_replace_rescan_broken_links'), 'linksy_search_and_replace_rescan_broken_links');
        $this->action(Ajax::prefix('search_and_replace_search_broken_links'), 'linksy_search_and_replace_search_broken_links');
        $this->action(Ajax::prefix('search_and_replace_ignore_links'), 'linksy_search_and_replace_ignore_links');
        $this->action(Ajax::prefix('search_and_replace_undo_ignore_links'), 'linksy_search_and_replace_undo_ignore_links');
        $this->action(Ajax::prefix('search_and_replace_recheck_links'), 'linksy_search_and_replace_recheck_links');
        $this->action(Ajax::prefix('search_and_replace_replace_links'), 'linksy_search_and_replace_replace_links');
        $this->action(Ajax::prefix('search_and_replace_replace_match_links'), 'linksy_search_and_replace_replace_match_links');
        $this->action(Ajax::prefix('search_and_replace_remove_match_links'), 'linksy_search_and_replace_remove_match_links');
        $this->action(Ajax::prefix('search_and_replace_unlink_links'), 'linksy_search_and_replace_unlink_links');
        $this->action(Ajax::prefix('search_and_replace_replace_anchors'), 'linksy_search_and_replace_replace_anchors');
        $this->action(Ajax::prefix('search_and_replace_replace_match_anchors'), 'linksy_search_and_replace_replace_match_anchors');
        $this->action(Ajax::prefix('search_and_replace_remove_match_anchors'), 'linksy_search_and_replace_remove_match_anchors');
        $this->action(Ajax::prefix('search_and_replace_replace_titles'), 'linksy_search_and_replace_replace_titles');
        $this->action(Ajax::prefix('search_and_replace_remove_titles'), 'linksy_search_and_replace_remove_titles');
        $this->action(Ajax::prefix('search_and_replace_replace_urls'), 'linksy_search_and_replace_replace_urls');
        $this->action(Ajax::prefix('search_and_replace_remove_urls'), 'linksy_search_and_replace_remove_urls');
        $this->action(Ajax::prefix('search_and_replace_unlink_anchors'), 'linksy_search_and_replace_unlink_anchors');
        $this->action(Ajax::prefix('search_and_replace_fix_anchors'), 'linksy_search_and_replace_fix_anchors');
        $this->action(Ajax::prefix('search_and_replace_retain_best_links'), 'linksy_search_and_replace_retain_best_links');
        $this->action(Ajax::prefix('search_and_replace_retain_best_anchors'), 'linksy_search_and_replace_retain_best_anchors');
        $this->action(Ajax::prefix('search_and_replace_item_details'), 'linksy_search_and_replace_item_details');
        $this->action(Ajax::prefix('search_and_replace_fetch_db_list'), 'linksy_search_and_replace_fetch_db_list');
        $this->action(Ajax::prefix('search_and_replace_search_db'), 'linksy_search_and_replace_search_db');
        $this->action(Ajax::prefix('search_and_replace_replace_db'), 'linksy_search_and_replace_replace_db');
        $this->action(Ajax::prefix('search_and_replace_search_offset_db'), 'linksy_search_and_replace_search_offset_db');

        $this->schedule_custom_cron_events();
    }

    public function register_admin_page()
    {
        add_submenu_page(
            'tools.php',                         
            'Linksy Search and Replace',                   
            'Linksy Search and Replace',              
            'manage_options',                     
            $this->page,
            array($this, 'display_page')
        );

        $this->enqueue_files();
    }

    public function enqueue_scripts()
    {
        parent::enqueue_scripts();

        $types = ['post', 'page'];

        $categories = array_map(
            function ($cat) {
                return [
                'value' => $cat->cat_ID,
                'label' => $cat->cat_name,
                ];
            },
            get_categories()
        );
        
        wp_add_inline_script(
            $this->plugin_name,
            "var LINKSYAI_SAR_SETUP_STATUS = " . wp_json_encode(($this->setup_status === null || $this->setup_status) ? 'complete' : 'incomplete')
        );

        wp_add_inline_script($this->plugin_name, "var LINKSYAI_SAR_POST_TYPES = " . wp_json_encode($types));
        wp_add_inline_script($this->plugin_name, "var LINKSYAI_SAR_POST_CATEGORIES = " . wp_json_encode($categories));

        // enqueue main scripts
        $scripts = [
            [
                $this->page . '-datatable',
                $this->plugin_base_dir . "/assets/js/datatable.vue.js",
                [$this->plugin_name . '-vue',]
            ],
            [
                $this->page . '-pagination',
                $this->plugin_base_dir . "/assets/js/pagination.vue.js",
                [$this->plugin_name . '-vue',],
            ],
            [
                $this->page . '-link-replacer',
                plugin_dir_url(__FILE__) . "_build/js/helpers/link-replacer.js",
                [],
            ],
            [
                $this->page . '-broken-links-helper',
                plugin_dir_url(__FILE__) . "_build/js/helpers/broken-links-helper.js",
                [],
            ],
            [
                $this->page . '-anchor-replacer',
                plugin_dir_url(__FILE__) . "_build/js/helpers/anchor-replacer.js",
                [],
            ],
            [
                $this->page . '-title-replacer',
                plugin_dir_url(__FILE__) . "_build/js/helpers/title-replacer.js",
                [],
            ],
            [
                $this->page . '-url-replacer',
                plugin_dir_url(__FILE__) . "_build/js/helpers/url-replacer.js",
                [],
            ],
            [
                $this->page . '-db-replacer',
                plugin_dir_url(__FILE__) . "_build/js/helpers/db-replacer.js",
                [],
            ],
            [
                $this->page . '-setup-page',
                plugin_dir_url(__FILE__) . "_build/js/components/setup.js",
                [
                    $this->page . '-notification-modal'
                ],
            ],
            [
                $this->page . '-pages-column',
                plugin_dir_url(__FILE__) . "_build/js/components/pages-column.js",
                [],
            ],
            [
                $this->page . '-database-user-controls',
                plugin_dir_url(__FILE__) . "_build/js/components/database-user-controls.js",
                [],
            ],
            [
                $this->page . '-db-filters',
                plugin_dir_url(__FILE__) . "_build/js/components/db-filters.js",
                [],
            ],
            [
                $this->page . '-search-and-replace-filter',
                plugin_dir_url(__FILE__) . "_build/js/components/search-and-replace-filter.js",
                [],
            ],
            [
                $this->page . '-user-controls',
                plugin_dir_url(__FILE__) . "_build/js/components/user-controls.js",
                [],
            ],
            [
                $this->page . '-bulk-action',
                plugin_dir_url(__FILE__) . "_build/js/components/bulk-action.js",
                [],
            ],
            [
                $this->page . '-sources-column',
                plugin_dir_url(__FILE__) . "_build/js/components/sources-column.js",
                [],
            ],
            [
                $this->page . '-links-column',
                plugin_dir_url(__FILE__) . "_build/js/components/links-column.js",
                [],
            ],
            [
                $this->page . '-link-occurrence',
                plugin_dir_url(__FILE__) . "_build/js/components/link-occurrence.js",
                [],
            ],
            [
                $this->page . '-notification-modal',
                plugin_dir_url(__FILE__) . "_build/js/components/notification-modal.js",
                [],
            ],
            [
                $this->page . '-table-header',
                plugin_dir_url(__FILE__) . "_build/js/components/table-header.js",
                [],
            ],
            [
                $this->page . '-link-replace',
                plugin_dir_url(__FILE__) . "_build/js/tabs/link-replace.vue.js",
                [
                    $this->page . '-link-replacer',
                    $this->page . '-bulk-action',
                    $this->page . '-user-controls',
                    $this->page . '-link-occurrence',
                    $this->page . '-table-header',
                    $this->page . '-sources-column',
                    $this->page . '-links-column',
                    $this->page . '-search-and-replace-filter'
                ],
            ],
            [
                $this->page . '-broken-links',
                plugin_dir_url(__FILE__) . "_build/js/tabs/broken-links.vue.js",
                [
                    $this->page . '-broken-links-helper',
                    $this->page . '-bulk-action',
                    $this->page . '-user-controls',
                    $this->page . '-search-and-replace-filter',
                ],
            ],
            [
                $this->page . '-anchor-replace',
                plugin_dir_url(__FILE__) . "_build/js/tabs/anchor-replace.vue.js",
                [
                    $this->page . '-anchor-replacer',
                    $this->page . '-bulk-action',
                    $this->page . '-user-controls',
                    $this->page . '-link-occurrence',
                    $this->page . '-sources-column',
                    $this->page . '-links-column',
                    $this->page . '-table-header',
                    $this->page . '-search-and-replace-filter',
                ],
            ],
            [
                $this->page . '-title-replace',
                plugin_dir_url(__FILE__) . "_build/js/tabs/title-replace.vue.js",
                [
                    $this->page . '-title-replacer',
                    $this->page . '-bulk-action',
                    $this->page . '-user-controls',
                    $this->page . '-link-occurrence',
                    $this->page . '-table-header',
                    $this->page . '-search-and-replace-filter',
                ],
            ],
            [
                $this->page . '-url-replace',
                plugin_dir_url(__FILE__) . "_build/js/tabs/url-replace.vue.js",
                [
                    $this->page . '-url-replacer',
                    $this->page . '-user-controls',
                    $this->page . '-link-occurrence',
                    $this->page . '-table-header',
                    $this->page . '-bulk-action',
                    $this->page . '-search-and-replace-filter',
                ],
            ],
            [
                $this->page . '-db-replace',
                plugin_dir_url(__FILE__) . "_build/js/tabs/db-replace.vue.js",
                [
                    $this->page . '-pages-column',
                    $this->page . '-bulk-action',
                    $this->page . '-database-user-controls',
                    $this->page . '-db-filters',
                ],
            ],
            [
                $this->page . '-rescan-links',
                plugin_dir_url(__FILE__) . "_build/js/tabs/rescan-links.vue.js",
                [
                    $this->page . '-notification-modal'
                ],
            ],
            [
                $this->page,
                plugin_dir_url(__FILE__) . "_build/js/app.js",
                [
                    $this->page . '-datatable',
                    $this->page . '-link-replace',
                    $this->page . '-anchor-replace',
                    $this->page . '-title-replace',
                    $this->page . '-db-replace',
                    $this->page . '-rescan-links',
                    $this->page . '-setup-page'
                ],
            ]
        ];

        foreach ($scripts as $script) {
            wp_enqueue_script(
                $script[0],
                $script[1],
                $script[2],
                $this->plugin_version,
                true
            );
        }
    }

    public function enqueue_styles()
    {
        parent::enqueue_styles();

        wp_enqueue_style(
            $this->page . '-datatable',
            $this->plugin_base_dir . "/assets/css/datatable.vue.css",
            array(),
            $this->plugin_version,
            'all'
        );

        wp_enqueue_style(
            $this->page . '-setup-page',
            plugin_dir_url(__FILE__) . "_build/css/setup.css",
            array(),
            $this->plugin_version,
            'all'
        );

        wp_enqueue_style(
            $this->page,
            plugin_dir_url(__FILE__) . "_build/css/app.css",
            array(),
            $this->plugin_version,
            'all'
        );
    }

    private function schedule_custom_cron_events()
    {
        if (get_option('linksy_link_analysis_cron_enabled', false)) {
            WP_Cron_Manager::add_event($this->run_link_analysis_event);
        }

        WP_Cron_Manager::add_event($this->periodic_link_analysis_event);
    }

    public function display_page()
    {
        $this->render_view('SearchAndReplace', []);
    }

    public function on_post_created($post_id)
    {
        $post = new Post($post_id);
        $this->refresh_links($post);
    }

    public function on_post_deleted($post_id)
    {
        try {
            Database::table("linksy_links")->where('post_id', $post_id)->delete();
        } catch (Exception $e) {
            HelpersUtils::error_log($e->getMessage());
        }
    }

    public function refresh_links($post, $setup = false)
    {
        $anchors = $post->get_content_links();

        // get old links
        $old_links = Database::table("linksy_links")->where('post_id', $post->get_ID())->select(['anchor', 'to_post_id', 'score'])->get();

        // delete all that exists in case of update
        Database::table("linksy_links")->where('post_id', $post->get_ID())->delete();

        $data = [];
        foreach ($anchors as $a) {
            $link = [
                'post_id'          => $post->get_ID(),
                'post_type'        => $post->get_type(),
                'post_title'       => $post->get_title(),
                'raw_url'          => $a['link'],
                'clean_url'        => esc_url_raw($a['link']),
                'anchor'           => $a['text'],
                'to_post_id'       => $a['to_post_id'],
                'is_internal'      => $a['is_internal'],
                'is_broken'        => $a['is_broken'],
                'aria_label'       => $a['aria_label'],
                'target_attribute' => $a['target_attribute'],
                'rel'              => $a['rel'],
                'host'             => $a['host'],
                'meta'             => wp_json_encode($a['meta']),
                'score'            => null,
            ];

            $old_links_index = false;

            foreach ($old_links as $k => $v) {
                if ($v->anchor == $a['text'] && $v->to_post_id == $a['to_post_id']) {
                    $old_links_index = $k;
                    break;
                }
            }

            if ($old_links_index !== false) {
                $link['score'] = ($old_links[$old_links_index])->score;
            }

            $data[] = $link;
        }

        if (count($data)) {
            Database::table("linksy_links")->insertMultiple(
                [
                'post_id',
                'post_type',
                'post_title',
                'raw_url',
                'clean_url',
                'anchor',
                'to_post_id',
                'is_internal',
                'is_broken',
                'aria_label',
                'target_attribute',
                'rel',
                'host',
                'meta',
                'score',
                ],
                $data
            );
        }

        if ($setup) Option::set(LINKSYAI_SAR_OPTION_SETUP_COMPLETE, true);

        $this->refresh_broken_links($post);
    }
}
