<?php
/**
 * Main plugin admin controller.
 */

if (!defined('ABSPATH')) {
    exit; // Exit if accessed directly.
}

class AILM_Admin
{

    private $plugin_name;
    private $version;
    private $core;
    private $settings_tab;
    private $stats_tab;
    private $faq_tab;
    private $clicks_tab;
    private $review_queue_tab;

    public function __construct($plugin_name, $version, $core)
    {
        $this->plugin_name = $plugin_name;
        $this->version = $version;
        $this->core = $core;

        require_once plugin_dir_path(__FILE__) . 'class-ailm-settings-tab.php';
        require_once plugin_dir_path(__FILE__) . 'class-ailm-stats-tab.php';
        require_once plugin_dir_path(__FILE__) . 'class-ailm-faq-tab.php';
        require_once plugin_dir_path(__FILE__) . '../modules/pagerank/class-ailm-pagerank.php';

        $this->settings_tab = new AILM_Settings_Tab($this->plugin_name, $this->version, $this->core);
        $this->stats_tab = new AILM_Stats_Tab($this->plugin_name, $this->version, $this->core);
        $this->faq_tab = new AILM_FAQ_Tab($this->plugin_name, $this->version, $this->core);

        add_action('admin_enqueue_scripts', array($this, 'enqueue_admin_assets'));
        add_action('admin_menu', array($this, 'add_plugin_admin_menu'));
        add_action('admin_notices', array($this, 'display_limit_reached_notice'));

        // AJAX для поиска постов в настройках
        add_action('wp_ajax_ailm_search_posts', array($this, 'ajax_search_posts'));
        add_action('wp_ajax_ailm_get_dashboard_analytics', array($this, 'ajax_get_dashboard_analytics'));
        add_action('wp_ajax_ailm_get_inbound_links_details', array($this, 'ajax_get_inbound_links_details'));
        add_action('wp_ajax_ailm_dashboard_delete_inbound_link', array($this, 'ajax_dashboard_delete_inbound_link'));
        add_action('wp_ajax_ailm_dashboard_create_direct_link', array($this, 'ajax_dashboard_create_direct_link'));
        add_action('wp_ajax_ailm_index_selected_post', array($this, 'ajax_index_selected_post'));


        // Инициализация модуля PageRank
        new AILM_PageRank_Engine();
        // CSV
        require_once plugin_dir_path(__FILE__) . 'class-ailm-csv-handler.php';
        new AILM_CSV_Handler($this->plugin_name);

        // Clicks Stats — early init so admin_post hooks are registered before HTML output
        require_once plugin_dir_path(__FILE__) . '../modules/clicks-stats/class-ailm-clicks-admin.php';
        $this->clicks_tab = new AILM_Clicks_Admin();

        // Review Queue — early init so admin_enqueue_scripts fires before page render
        require_once plugin_dir_path(__FILE__) . '../modules/review-queue/class-ailm-review-queue-admin.php';
        $this->review_queue_tab = new AILM_Review_Queue_Admin();
    }

    public function enqueue_admin_assets($hook)
    {
        if (strpos($hook, $this->plugin_name) !== false) {

            wp_enqueue_style(
                $this->plugin_name . '-admin-settings',
                plugin_dir_url(__FILE__) . '../assets/admin-settings.css',
                array(),
                time(),
                'all'
            );

            // Подключаем Select2
            wp_enqueue_style('select2', 'https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css', array(), '4.1.0');
            wp_enqueue_script('select2', 'https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js', array('jquery'), '4.1.0', true);

            // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            $tab = isset($_GET['tab']) ? sanitize_text_field(wp_unslash($_GET['tab'])) : 'dashboard';

            // Скрипты для страницы настроек
            if ($tab === 'settings') {
                wp_enqueue_script(
                    'ailm-settings-js',
                    plugin_dir_url(__FILE__) . '../assets/admin-settings.js',
                    array('jquery', 'select2'),
                    $this->version,
                    true
                );
                wp_localize_script('ailm-settings-js', 'ailmSettings', array(
                    'ajax_url' => admin_url('admin-ajax.php'),
                    'nonce' => wp_create_nonce('ailm_settings_nonce'),
                ));
            }

            if ($tab === 'stats') {
                wp_enqueue_script('ailm-stats-js', plugin_dir_url(__FILE__) . '../assets/admin-stats.js', array('jquery'), $this->version, true);
                wp_localize_script('ailm-stats-js', 'ailmStats', array(
                    'ajax_url' => admin_url('admin-ajax.php'),
                    'nonce' => wp_create_nonce('ailm_stats_nonce'),
                    'i18n' => array(
                        'no_recipients' => esc_html__('No recipients found.', 'Internal-auto-links-manager'),
                    )
                ));
            }

            if ($tab === 'dashboard' || $tab === 'orphan-rescue') {
                wp_enqueue_script('ailm-orphan-js', plugin_dir_url(__FILE__) . '../assets/admin-orphan.js', array('jquery'), time(), true);
                wp_localize_script('ailm-orphan-js', 'ailmOrphan', array(
                    'ajax_url' => admin_url('admin-ajax.php'),
                    'nonce' => wp_create_nonce('ailm_orphan_nonce'),
                    'i18n' => array(
                        'no_orphans' => esc_html__('No orphans found.', 'Internal-auto-links-manager'),
                        'rescue' => esc_html__('Rescue', 'Internal-auto-links-manager'),
                        'saving' => esc_html__('Saving...', 'Internal-auto-links-manager'),
                        'save_stop_words' => esc_html__('Save Stop Words', 'Internal-auto-links-manager'),
                        'err_save_stop_words' => esc_html__('Error saving stop words.', 'Internal-auto-links-manager'),
                        'err_connection' => esc_html__('Connection error.', 'Internal-auto-links-manager'),
                        'no_keywords' => esc_html__('No clear keywords found. Please enter them manually below.', 'Internal-auto-links-manager'),
                        'err_analyze' => esc_html__('Error analyzing article. Please check your connection.', 'Internal-auto-links-manager'),
                        'err_no_keyword_selected' => esc_html__('Please select or enter at least one keyword.', 'Internal-auto-links-manager'),
                        'posts_checked' => esc_html__('posts checked', 'Internal-auto-links-manager'),
                        'donors_found' => esc_html__('donors found', 'Internal-auto-links-manager'),
                        'search_failed' => esc_html__('Search failed: ', 'Internal-auto-links-manager'),
                        'err_db_scan' => esc_html__('Connection error during database scan.', 'Internal-auto-links-manager'),
                        'try_broader' => esc_html__('Try Broader Keywords', 'Internal-auto-links-manager'),
                        'found' => esc_html__('Found', 'Internal-auto-links-manager'),
                        'donors' => esc_html__('Donors', 'Internal-auto-links-manager'),
                        'select_articles' => esc_html__('Select the articles you want to link from. All of these have passed safety checks (outbound limits, H2 zones, etc).', 'Internal-auto-links-manager'),
                        'donor_context' => esc_html__('Donor Article & Context', 'Internal-auto-links-manager'),
                        'edit' => esc_html__('Edit', 'Internal-auto-links-manager'),
                        'err_select_donor' => esc_html__('Please select at least one donor article.', 'Internal-auto-links-manager'),
                        'creating_links' => esc_html__('Creating Links...', 'Internal-auto-links-manager'),
                        'success_links_created' => esc_html__('Success! Links have been instantly created on the live site.', 'Internal-auto-links-manager'),
                        'error' => esc_html__('Error: ', 'Internal-auto-links-manager'),
                        'err_creating_rules' => esc_html__('Connection error while creating rules.', 'Internal-auto-links-manager'),
                        'no_matches_html' => wp_kses_post(__('<h3 style="margin-top:12px;">No perfect matches found.</h3><p style="color:#86868b; margin-bottom: 24px;">None of the scanned articles contained these keywords outside of headers/existing links, or they reached their outbound limit.</p>', 'Internal-auto-links-manager')),
                        'view' => esc_html__('View', 'Internal-auto-links-manager'),
                    )
                ));
            }

            if ($tab === 'dashboard') {
                wp_enqueue_script('ailm-dashboard-js', plugin_dir_url(__FILE__) . '../assets/admin-dashboard.js', array('jquery'), time(), true);
            }

        }
    }

    /**
     * AJAX handler for the Unified Dashboard Table data.
     */
    public function ajax_get_dashboard_analytics()
    {
        check_ajax_referer('ailm_orphan_nonce', 'nonce');

        if (!current_user_can('manage_options')) {
            wp_send_json_error();
        }

        // Sync indexed status from SaaS so checkmarks are always fresh
        if (class_exists('AILM_OpenAI_Provider')) {
            $provider = new AILM_OpenAI_Provider();
            $sync_resp = $provider->saas_get_indexed_ids();
            if (!is_wp_error($sync_resp) && isset($sync_resp['indexed_ids'])) {
                global $wpdb;
                // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
                $wpdb->query("DELETE FROM {$wpdb->postmeta} WHERE meta_key = '_ailm_is_indexed'");
                $indexed_ids = $sync_resp['indexed_ids'];
                if (!empty($indexed_ids)) {
                    $time = current_time('mysql');
                    $values = [];
                    foreach ($indexed_ids as $id) {
                        $values[] = $wpdb->prepare("(%d, %s, %s)", $id, '_ailm_is_indexed', $time);
                    }
                    foreach (array_chunk($values, 500) as $chunk) {
                        $wpdb->query("INSERT INTO {$wpdb->postmeta} (post_id, meta_key, meta_value) VALUES " . implode(', ', $chunk));
                    }
                }
            }
        }

        $posts = get_posts(array(
            'numberposts' => 1000,
            'post_type' => array('post', 'page'),
            'post_status' => 'publish',
            'suppress_filters' => true,
        ));

        // Bulk-load all counts in two queries via Repository.
        $outbound_counts = AILM_Link_Repository::get_bulk_outbound_counts('internal');
        $inbound_counts = AILM_Link_Repository::get_bulk_inbound_counts('internal');

        $data = array();
        foreach ($posts as $p) {
            $data[] = array(
                'id' => $p->ID,
                'title' => html_entity_decode(get_the_title($p->ID), ENT_QUOTES, 'UTF-8'),
                'date' => get_the_date('M j, Y', $p->ID),
                'type' => ucfirst($p->post_type),
                'inbound' => isset($inbound_counts[$p->ID]) ? $inbound_counts[$p->ID] : 0,
                'outbound' => isset($outbound_counts[$p->ID]) ? $outbound_counts[$p->ID] : 0,
                'pagerank' => AILM_PageRank_Engine::get_post_pr($p->ID),
                'is_indexed' => get_post_meta($p->ID, '_ailm_is_indexed', true) ? true : false,
                'edit_url' => get_edit_post_link($p->ID, 'raw'),
                'url' => get_permalink($p->ID),
            );
        }

        wp_send_json_success($data);
    }

    /**
     * AJAX handler to index a specific post selected from the dashboard.
     */
    public function ajax_index_selected_post()
    {
        check_ajax_referer('ailm_orphan_nonce', 'nonce');

        if (!current_user_can('manage_options')) {
            wp_send_json_error('Unauthorized access.');
        }

        $post_id = isset($_POST['post_id']) ? absint($_POST['post_id']) : 0;
        if (!$post_id) {
            wp_send_json_error('Missing post ID.');
        }

        $post = get_post($post_id);
        if (!$post || empty($post->post_content)) {
            wp_send_json_error('Post not found or empty content.');
        }

        if (!class_exists('AILM_OpenAI_Provider')) {
            require_once dirname(__DIR__) . '/modules/ai-core/providers/class-ailm-openai-provider.php';
        }
        $provider = new AILM_OpenAI_Provider();

        $response = $provider->saas_index_document($post_id, $post->post_content);

        if (is_wp_error($response)) {
            wp_send_json_error(array('message' => $response->get_error_message()));
        }

        update_post_meta($post_id, '_ailm_is_indexed', current_time('mysql'));

        wp_send_json_success();
    }


    /**
     * AJAX поиск постов для черного списка
     */
    public function ajax_search_posts()
    {
        if (!current_user_can('manage_options')) {
            wp_send_json_error();
        }

        $nonce = isset($_REQUEST['nonce']) ? sanitize_text_field(wp_unslash($_REQUEST['nonce'])) : '';
        if (!wp_verify_nonce($nonce, 'ailm_settings_nonce') && !wp_verify_nonce($nonce, 'ailm_orphan_nonce')) {
            wp_send_json_error('Invalid security token.');
        }

        $search_text = isset($_GET['q']) ? sanitize_text_field(wp_unslash($_GET['q'])) : '';
        $post_types = get_option('ailm_allowed_post_types', array('post', 'page'));

        $query = new WP_Query(array(
            's' => $search_text,
            'post_type' => $post_types,
            'posts_per_page' => 15,
            'post_status' => 'publish',
        ));

        $results = array();
        if ($query->have_posts()) {
            while ($query->have_posts()) {
                $query->the_post();
                $results[] = array(
                    'id' => get_the_ID(),
                    'text' => html_entity_decode(get_the_title(), ENT_QUOTES, 'UTF-8') . ' (ID: ' . get_the_ID() . ')',
                );
            }
        }
        wp_reset_postdata();

        wp_send_json_success($results);
    }

    public function ajax_dashboard_create_direct_link()
    {
        check_ajax_referer('ailm_orphan_nonce', 'nonce');
        if (!current_user_can('manage_options')) {
            wp_send_json_error('Permission denied.');
        }

        $donor_id = isset($_POST['donor_id']) ? absint($_POST['donor_id']) : 0;
        $target_id = isset($_POST['target_id']) ? absint($_POST['target_id']) : 0;
        $anchor = isset($_POST['anchor']) ? sanitize_text_field(wp_unslash($_POST['anchor'])) : '';

        if (!$donor_id || !$target_id || empty($anchor)) {
            wp_send_json_error('Missing parameters.');
        }
        if ($donor_id === $target_id) {
            wp_send_json_error('Cannot link an article to itself.');
        }

        if (!class_exists('AILM_Link_Builder')) {
            require_once plugin_dir_path(__DIR__) . 'includes/class-ailm-link-builder.php';
        }
        if (!class_exists('AILM_DOM_Helper')) {
            require_once plugin_dir_path(__DIR__) . 'includes/class-ailm-dom-helper.php';
        }

        $link_builder = new AILM_Link_Builder(null);

        if (!$link_builder->can_inject_phrase($donor_id, $anchor)) {
            wp_send_json_error('Link insertion rejected. Limits exceeded, phrase already occupied, or restricted HTML zone.');
        }

        $donor_post = get_post($donor_id);
        if (!$donor_post) {
            wp_send_json_error('Donor post not found.');
        }
        $target_url = get_permalink($target_id);

        $target_limit = (int) get_option('ailm_target_limit', 5);
        if (class_exists('AILM_Link_Repository')) {
            $inbound_count = AILM_Link_Repository::get_active_inbound_rule_count($target_id);
        } else {
            $inbound_count = (int) get_post_meta($target_id, '_ailm_inbound_count', true);
        }
        if ($inbound_count >= $target_limit) {
            wp_send_json_error('The target post has reached its incoming links limit (' . $inbound_count . '/' . $target_limit . ').');
        }

        $skip_chars = (int) get_option('ailm_skip_chars', 100);
        $gap = (int) get_option('ailm_min_gap', 200);

        $dom_helper = new AILM_DOM_Helper($donor_post->post_content);
        $virtual_text = $dom_helper->get_virtual_text();

        $escaped_parts = array_map(function ($p) {
            return str_replace("'", "['''`´]", preg_quote($p, '/'));
        }, preg_split('/\s+/u', trim($anchor), -1, PREG_SPLIT_NO_EMPTY));
        $fuzzy_kw = implode('[\p{Z}\s\p{P}\p{S}]+', $escaped_parts);
        $pattern = '/(?<![\p{L}\p{N}])(' . $fuzzy_kw . ')(?![\p{L}\p{N}])/iu';

        if (!preg_match_all($pattern, $virtual_text, $matches, PREG_OFFSET_CAPTURE)) {
            wp_send_json_error('The exact phrase "' . esc_html($anchor) . '" was not found in the donor article.');
        }

        if (!class_exists('AILM_Link_Repository')) {
            require_once plugin_dir_path(__DIR__) . 'includes/class-ailm-link-repository.php';
        }

        $existing_rules = (array) AILM_Link_Repository::get_rules_for_donor($donor_id);

        // Build occupied ranges from manual links and existing active rules.
        $occupied_ranges = array();
        $manual_link_positions = (array) $dom_helper->get_manual_links_positions();
        foreach ($manual_link_positions as $pos) {
            $occupied_ranges[] = array('start' => max(0, $pos - $gap), 'end' => $pos + $gap);
        }

        foreach ($existing_rules as $rule) {
            $item_occ = (int) $rule->occurrence;
            $rule_parts = array_map(function ($p) {
                return str_replace("'", "['''`´]", preg_quote($p, '/'));
            }, preg_split('/\s+/u', trim($rule->anchor), -1, PREG_SPLIT_NO_EMPTY));
            $rule_fuzzy = implode('[\p{Z}\s\p{P}\p{S}]+', $rule_parts);
            $rule_pattern = '/(?<![\p{L}\p{N}])(' . $rule_fuzzy . ')(?![\p{L}\p{N}])/iu';

            if (preg_match_all($rule_pattern, $virtual_text, $rule_matches, PREG_OFFSET_CAPTURE)) {
                $current_match_idx = 0;
                foreach ($rule_matches[0] as $rule_match) {
                    $current_match_idx++;
                    if ($current_match_idx === $item_occ) {
                        $char_offset = mb_strlen(substr($virtual_text, 0, $rule_match[1]), 'UTF-8');
                        $char_length = mb_strlen($rule_match[0], 'UTF-8');
                        $occupied_ranges[] = array(
                            'start' => max(0, $char_offset - $gap),
                            'end' => $char_offset + $char_length + $gap,
                        );
                        break;
                    }
                }
            }
        }

        $selected_word = '';
        $selected_occurrence = 0;

        $current_match_idx = 0;
        foreach ($matches[0] as $match) {
            $current_match_idx++;
            $found_word = $match[0];
            $byte_offset = $match[1];
            $char_offset = mb_strlen(substr($virtual_text, 0, $byte_offset), 'UTF-8');
            $char_length = mb_strlen($found_word, 'UTF-8');

            if ($char_offset < $skip_chars) {
                continue;
            }

            $overlap = false;
            foreach ($occupied_ranges as $range) {
                if ($char_offset < $range['end'] && ($char_offset + $char_length) > $range['start']) {
                    $overlap = true;
                    break;
                }
            }

            if (!$overlap) {
                $selected_word = $found_word;
                $selected_occurrence = $current_match_idx;
                break;
            }
        }

        if ($selected_occurrence === 0) {
            wp_send_json_error('No valid insertion point found. The phrase is either inside the Skip Intro zone or too close to another link.');
        }

        // Duplicate check against the selected word.
        foreach ($existing_rules as $existing) {
            if ((int) $existing->target_id === $target_id && mb_strtolower($existing->anchor, 'UTF-8') === mb_strtolower($selected_word, 'UTF-8')) {
                wp_send_json_error('This exact link already exists.');
            }
        }

        AILM_Link_Repository::add_rule(
            $donor_id,
            $target_url,
            $selected_word,
            'manual_dashboard',
            $selected_occurrence
        );

        $result = $link_builder->inject_physical_links($donor_id);
        if (!$result) {
            wp_send_json_error('Link injection failed. The content may have changed or the target phrase is no longer available.');
        }

        $inbound_count = (int) get_post_meta($target_id, '_ailm_inbound_count', true);
        update_post_meta($target_id, '_ailm_inbound_count', $inbound_count + 1);

        if (class_exists('AILM_Scout_Scanner')) {
            AILM_Scout_Scanner::process_post($donor_id);
        }

        wp_send_json_success();
    }

    public function ajax_get_inbound_links_details()
    {
        check_ajax_referer('ailm_orphan_nonce', 'nonce');

        if (!current_user_can('manage_options'))
            wp_send_json_error();

        $target_id = isset($_POST['post_id']) ? absint(wp_unslash($_POST['post_id'])) : 0;
        if (!$target_id) {
            wp_send_json_error('Invalid post ID.');
        }

        // Single query: get all inbound internal links for this target.
        $raw_links = AILM_Link_Repository::get_inbound_links($target_id, 'internal');

        $links = array();
        foreach ($raw_links as $link) {
            $donor_id = (int) $link->donor_id;
            $links[] = array(
                'donor_id' => $donor_id,
                'donor_title' => html_entity_decode(get_the_title($donor_id), ENT_QUOTES, 'UTF-8'),
                'donor_url' => get_permalink($donor_id),
                'keyword' => $link->anchor,
                'type' => $link->origin, // 'plugin' or 'manual'
            );
        }

        wp_send_json_success($links);
    }

    /**
     * Shared helper to remove a specific donor from a surgical rule and clean up frozen links.
     *
     * @param int    $target_id Target post ID.
     * @param int    $donor_id  Donor post ID.
     * @param string $keyword   The anchor phrase.
     * @return true|WP_Error True on success, WP_Error on failure.
     */
    public static function remove_surgical_donor($target_id, $donor_id, $keyword)
    {
        if (!class_exists('AILM_Link_Repository')) {
            require_once plugin_dir_path(__DIR__) . 'includes/class-ailm-link-repository.php';
        }

        $rule_deleted = false;
        $rules = AILM_Link_Repository::get_rules_for_donor($donor_id);
        foreach ($rules as $rule) {
            if ((int) $rule->target_id === (int) $target_id && mb_strtolower($rule->anchor, 'UTF-8') === mb_strtolower($keyword, 'UTF-8')) {
                AILM_Link_Repository::delete_rule($rule->id);
                $rule_deleted = true;
                break;
            }
        }

        // Remove physical link from HTML
        if (!class_exists('AILM_DOM_Helper')) {
            require_once plugin_dir_path(__DIR__) . 'includes/class-ailm-dom-helper.php';
        }

        $donor_post = get_post($donor_id);
        $target_url = get_permalink($target_id);
        $physically_removed = false;

        if ($donor_post && !empty($donor_post->post_content) && $target_url) {
            $is_elementor = class_exists('AILM_Elementor_Handler') && AILM_Elementor_Handler::is_elementor_post($donor_id);
            $global_modified = false;

            $process_html = function ($html) use (&$global_modified, $target_url, $keyword) {
                $dom_helper = new AILM_DOM_Helper($html);
                if ($dom_helper->unwrap_link($target_url, $keyword)) {
                    $global_modified = true;
                    return $dom_helper->get_html();
                }
                return $html;
            };

            if ($is_elementor) {
                AILM_Elementor_Handler::process_content($donor_id, $process_html);
                if ($global_modified)
                    $physically_removed = true;
            } else {
                $new_content = $process_html($donor_post->post_content);
                if ($global_modified) {
                    wp_update_post([
                        'ID' => $donor_id,
                        'post_content' => $new_content
                    ]);
                    $physically_removed = true;
                }
            }
        }

        if ($physically_removed && class_exists('AILM_Scout_Scanner')) {
            AILM_Scout_Scanner::process_post($donor_id);
        }

        if (!$rule_deleted && !$physically_removed) {
            return new WP_Error('not_found', __('Link not found in database or physical content.', 'Internal-auto-links-manager'));
        }

        $inbound = (int) get_post_meta($target_id, '_ailm_inbound_count', true);
        update_post_meta($target_id, '_ailm_inbound_count', max(0, $inbound - 1));

        if (class_exists('AILM_Scout_Scanner')) {
            AILM_Scout_Scanner::process_post($donor_id);
        }

        return true;
    }

    public function ajax_dashboard_delete_inbound_link()
    {
        check_ajax_referer('ailm_orphan_nonce', 'nonce');

        if (!current_user_can('edit_posts')) {
            wp_send_json_error('Permission denied.');
        }

        $donor_id = isset($_POST['donor_id']) ? absint($_POST['donor_id']) : 0;
        $target_id = isset($_POST['target_id']) ? absint($_POST['target_id']) : 0;

        $word = isset($_POST['word']) ? sanitize_text_field(wp_unslash($_POST['word'])) : '';
        if (empty($word) && isset($_POST['anchor']))
            $word = sanitize_text_field(wp_unslash($_POST['anchor']));
        if (empty($word) && isset($_POST['keyword']))
            $word = sanitize_text_field(wp_unslash($_POST['keyword']));

        if (!$donor_id || !$target_id || empty($word)) {
            wp_send_json_error('Missing parameters. Received: ' . wp_json_encode($_POST));
        }

        $result = self::remove_surgical_donor($target_id, $donor_id, $word);

        if (is_wp_error($result)) {
            wp_send_json_error($result->get_error_message());
        }

        wp_send_json_success();
    }

    public function add_plugin_admin_menu()
    {
        add_menu_page(
            __('Link Mesh', 'Internal-auto-links-manager'),
            __('Link Mesh', 'Internal-auto-links-manager'),
            'manage_options',
            $this->plugin_name,
            array($this, 'display_plugin_setup_page'),
            'dashicons-admin-links',
            90
        );

        add_submenu_page(
            $this->plugin_name,
            __('Dashboard', 'Internal-auto-links-manager'),
            __('Dashboard', 'Internal-auto-links-manager'),
            'manage_options',
            $this->plugin_name,
            array($this, 'display_plugin_setup_page')
        );

        add_submenu_page(
            $this->plugin_name,
            __('Review Queue', 'Internal-auto-links-manager'),
            __('Review Queue', 'Internal-auto-links-manager'),
            'manage_options',
            $this->plugin_name . '-review-queue',
            array($this, 'display_plugin_setup_page')
        );

        add_submenu_page(
            $this->plugin_name,
            __('FAQ / Help', 'Internal-auto-links-manager'),
            __('FAQ / Help', 'Internal-auto-links-manager'),
            'manage_options',
            $this->plugin_name . '-faq',
            array($this, 'display_plugin_setup_page')
        );
    }

    public function display_plugin_setup_page()
    {
        if (!current_user_can('manage_options'))
            return;

        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        $active_tab = isset($_GET['tab']) ? sanitize_text_field(wp_unslash($_GET['tab'])) : 'dashboard';

        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        if (isset($_GET['page']) && $_GET['page'] === $this->plugin_name . '-review-queue') {
            $active_tab = 'review-queue';
        }
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        if (isset($_GET['page']) && $_GET['page'] === $this->plugin_name . '-faq') {
            $active_tab = 'faq';
        }
        ?>
        <div class="wrap ailm-wrap">
            <h1><?php esc_html_e('Link Mesh: Internal Links SEO Logic', 'Internal-auto-links-manager'); ?></h1>

            <?php
            // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            if (isset($_GET['ailm_notice'])) {
                // phpcs:ignore WordPress.Security.NonceVerification.Recommended
                $this->display_admin_notices(sanitize_key(wp_unslash($_GET['ailm_notice'])));
            }

            $this->display_progress_notice();

            // phpcs:ignore WordPress.Security.NonceVerification.Recommended
            if (isset($_GET['simulation_id'])) {
                // phpcs:ignore WordPress.Security.NonceVerification.Recommended
                $sim_id = sanitize_key(wp_unslash($_GET['simulation_id']));
                $sim_data = get_transient($sim_id);
                if ($sim_data) {
                    $this->display_simulation_notice($sim_data, $sim_id);
                }
            }
            ?>

            <h2 class="nav-tab-wrapper" style="margin-top: 20px;">
                <style>
                    .ailm-wrap {
                        max-width: 100% !important;
                    }

                    .ailm-tabs-container {
                        display: flex !important;
                        width: 100% !important;
                    }

                    .ailm-tab {
                        flex: 1 !important;
                        text-align: center;
                        padding: 15px 5px !important;
                        font-size: 16px !important;
                    }

                    #wpfooter {
                        display: none !important;
                    }
                </style>
                <nav class="ailm-tabs-container">
                    <a href="?page=<?php echo esc_attr($this->plugin_name); ?>&tab=dashboard"
                        class="ailm-tab <?php echo $active_tab === 'dashboard' ? 'is-active' : ''; ?>"><?php esc_html_e('Dashboard', 'Internal-auto-links-manager'); ?></a>
                    <a href="?page=<?php echo esc_attr($this->plugin_name); ?>&tab=settings"
                        class="ailm-tab <?php echo $active_tab === 'settings' ? 'is-active' : ''; ?>"><?php esc_html_e('Bulk Settings', 'Internal-auto-links-manager'); ?></a>
                    <a href="?page=<?php echo esc_attr($this->plugin_name); ?>&tab=clicks"
                        class="ailm-tab <?php echo $active_tab === 'clicks' ? 'is-active' : ''; ?>"><?php esc_html_e('Click Stats', 'Internal-auto-links-manager'); ?></a>
                    <a href="?page=<?php echo esc_attr($this->plugin_name); ?>&tab=keyword-intelligence"
                        class="ailm-tab <?php echo $active_tab === 'keyword-intelligence' ? 'is-active' : ''; ?>"><?php esc_html_e('Keyword Intelligence', 'Internal-auto-links-manager'); ?></a>
                    <a href="?page=<?php echo esc_attr($this->plugin_name); ?>&tab=scout"
                        class="ailm-tab <?php echo $active_tab === 'scout' ? 'is-active' : ''; ?>"><?php esc_html_e('404 Scout', 'Internal-auto-links-manager'); ?></a>
                    <a href="?page=<?php echo esc_attr($this->plugin_name); ?>-review-queue"
                        class="ailm-tab <?php echo $active_tab === 'review-queue' ? 'is-active' : ''; ?>"><?php esc_html_e('Review Queue', 'Internal-auto-links-manager'); ?></a>
                    <a href="?page=<?php echo esc_attr($this->plugin_name); ?>-faq"
                        class="ailm-tab <?php echo $active_tab === 'faq' ? 'is-active' : ''; ?>"><?php esc_html_e('FAQ / Help', 'Internal-auto-links-manager'); ?></a>
                    <div
                        style="margin-left:auto; display:flex; align-items:center; gap:12px; padding:0 10px; white-space:nowrap;">
                        <span style="font-size:15px; font-weight:500; color:#1d1d1f;">🪙
                            <?php echo esc_html(get_option('linkmesh_tokens_balance', '--')); ?></span>
                        <a href="https://linkmesh.co/" target="_blank" class="button button-primary"
                            style="font-size:13px; line-height:1.8; min-height:24px;">Top Up ↑</a>
                    </div>
                </nav>
            </h2>

            <?php
            switch ($active_tab) {
                case 'dashboard':
                    if (!class_exists('AILM_Dashboard_Admin')) {
                        require_once plugin_dir_path(__FILE__) . '../modules/dashboard/class-ailm-dashboard-admin.php';
                    }
                    $dashboard_admin = new AILM_Dashboard_Admin($this->plugin_name, $this->version, $this->core);
                    $dashboard_admin->render_tab();
                    break;
                case 'settings':
                    $this->settings_tab->render_tab();
                    break;
                case 'orphan-rescue':
                    if (!class_exists('AILM_Orphan_Admin')) {
                        require_once plugin_dir_path(__FILE__) . '../modules/orphan-rescue/class-ailm-orphan-admin.php';
                    }
                    $orphan_admin = new AILM_Orphan_Admin($this->plugin_name, $this->version, $this->core);
                    $orphan_admin->render_tab();
                    break;
                case 'stats':
                    $this->stats_tab->render_tab();
                    break;
                case 'clicks':
                    $this->clicks_tab->render_tab();
                    break;
                case 'keyword-intelligence':
                    require_once plugin_dir_path(__FILE__) . '../modules/keyword-intelligence/class-ailm-ki-admin.php';
                    require_once plugin_dir_path(__FILE__) . '../modules/keyword-intelligence/class-ailm-ki-analyzer.php';
                    require_once plugin_dir_path(__FILE__) . '../modules/keyword-intelligence/class-ailm-ki-data-provider.php';
                    $ki_admin = new AILM_KI_Admin();
                    $ki_admin->render_tab();
                    break;
                case 'scout':
                    if (!class_exists('AILM_Scout_Admin')) {
                        require_once plugin_dir_path(__FILE__) . '../modules/404-scout/class-ailm-scout-admin.php';
                    }
                    $scout_admin = new AILM_Scout_Admin();
                    $scout_admin->render_tab();
                    break;
                case 'review-queue':
                    $this->review_queue_tab->render_tab();
                    break;
                case 'faq':
                    $this->faq_tab->render_tab();
                    break;
            }
            ?>
        </div>
        <?php
    }

    private function display_progress_notice()
    {
        $job_status = get_option('ailm_freeze_job_status');
        if (!$job_status)
            return;

        if ($job_status === 'running') {
            $total = (int) get_option('ailm_freeze_job_total_posts', 1);
            $processed = (int) get_option('ailm_freeze_job_processed_posts', 0);
            $percent = $total > 0 ? round(($processed / $total) * 100) : 0;
            ?>
            <div class="ailm-card" style="border-left: 4px solid #f5a623; margin-bottom: 24px; padding: 20px;">
                <h3 style="margin-top: 0; font-size: 16px; color: #1d1d1f; display:flex; align-items:center; gap:8px;">
                    <span class="dashicons dashicons-update-alt"></span>
                    <?php esc_html_e('Freeze Job in Progress...', 'Internal-auto-links-manager'); ?>
                </h3>
                <p class="ailm-description" style="margin-bottom: 16px; font-size: 13px;">
                    <?php esc_html_e('The plugin is processing articles in the background. Please do not close this page.', 'Internal-auto-links-manager'); ?>
                </p>
                <div
                    style="width: 100%; background: #e8e8ed; border-radius: 6px; overflow: hidden; height: 12px; margin-bottom: 8px;">
                    <div id="ailm-freeze-progress-bar"
                        style="width: <?php echo esc_attr($percent); ?>%; background: #0071e3; height: 100%; transition: width 0.5s ease;">
                    </div>
                </div>
                <div style="display:flex; justify-content:space-between; font-size:12px; color:#86868b; font-weight:600;">
                    <span id="ailm-freeze-progress-text"><?php echo esc_html(number_format_i18n($processed)); ?> /
                        <?php echo esc_html(number_format_i18n($total)); ?>
                        <?php esc_html_e('posts processed', 'Internal-auto-links-manager'); ?></span>
                    <span id="ailm-freeze-percent-text"><?php echo esc_html($percent); ?>%</span>
                </div>
            </div>
            <script>
                jQuery(document).ready(function ($) {
                    var ailmProgressTimer = setInterval(function () {
                        $.ajax({
                            url: ajaxurl,
                            type: 'POST',
                            data: {
                                action: 'ailm_check_freeze_progress',
                                nonce: '<?php echo esc_js(wp_create_nonce("ailm_freeze_progress_nonce")); ?>'
                            },
                            success: function (response) {
                                if (response.success) {
                                    var d = response.data;
                                    $('#ailm-freeze-progress-bar').css('width', d.percent + '%');
                                    $('#ailm-freeze-progress-text').text(d.proc_fmt + ' / ' + d.total_fmt + ' <?php echo esc_js(__('posts processed', 'Internal-auto-links-manager')); ?>');
                                    $('#ailm-freeze-percent-text').text(d.percent + '%');

                                    if (d.status === 'complete' || d.status === '') {
                                        clearInterval(ailmProgressTimer);
                                        window.location.reload();
                                    }
                                }
                            }
                        });
                    }, 2000);
                });
            </script>
            <?php
        } elseif ($job_status === 'complete') {
            ?>
            <div class="ailm-card" style="border-left: 4px solid #34c759; margin-bottom: 24px; padding: 20px; position:relative;">
                <h3 style="margin-top: 0; font-size: 16px; color: #1d1d1f; display:flex; align-items:center; gap:8px;"><span
                        class="dashicons dashicons-saved" style="color:#34c759;"></span>
                    <?php esc_html_e('Freeze Job Complete!', 'Internal-auto-links-manager'); ?></h3>
                <p class="ailm-description" style="margin:0; font-size: 13px;">
                    <?php esc_html_e('All links have been processed and frozen. You can now see the results in the "Frozen Links Report" tab.', 'Internal-auto-links-manager'); ?>
                </p>
            </div>
            <?php
            delete_option('ailm_freeze_job_status');
            delete_option('ailm_freeze_job_total_posts');
            delete_option('ailm_freeze_job_processed_posts');
        }
    }

    private function display_simulation_notice($sim_data, $sim_id)
    {
        $total_links = number_format_i18n($sim_data['total_links']);
        $total_recipients = number_format_i18n($sim_data['total_recipients']);
        $total_orphans = number_format_i18n($sim_data['orphan_count']);
        ?>
        <div id="ailm-simulation-notice" class="ailm-card"
            style="border-left: 4px solid #0071e3; padding: 20px; position: relative; margin-bottom: 24px;">
            <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>">
                <input type="hidden" name="action" value="ailm_handle_actions">
                <input type="hidden" name="action_nocsrf" value="ailm_dismiss_simulation">
                <input type="hidden" name="simulation_id" value="<?php echo esc_attr($sim_id); ?>">
                <?php wp_nonce_field('ailm_dismiss_sim', 'ailm_dismiss_nonce'); ?>
                <button type="submit" class="notice-dismiss" style="text-decoration: none;"></button>
            </form>
            <h3 style="margin-top: 0; font-size:16px; color:#1d1d1f; display:flex; align-items:center; gap:8px;"><span
                    class="dashicons dashicons-visibility" style="color:#0071e3;"></span>
                <?php esc_html_e('Simulation Results', 'Internal-auto-links-manager'); ?></h3>
            <p class="ailm-description" style="font-size:13px; margin-bottom:12px;">
                <?php esc_html_e('Based on your rules, here is a proposal for link distribution. This is a simulation, no links have been created yet.', 'Internal-auto-links-manager'); ?>
            </p>
            <ul style="list-style-type: disc; padding-left: 20px; font-size:14px; color:#1d1d1f; margin-bottom:16px;">
                <li><b><?php esc_html_e('Total Links to Create:', 'Internal-auto-links-manager'); ?></b>
                    <?php echo esc_html($total_links); ?></li>
                <li><b><?php esc_html_e('Articles Receiving Links:', 'Internal-auto-links-manager'); ?></b>
                    <?php echo esc_html($total_recipients); ?></li>
                <li><b><?php esc_html_e('Orphan Articles Remaining:', 'Internal-auto-links-manager'); ?></b>
                    <?php echo esc_html($total_orphans); ?></li>
            </ul>
            <p style="font-size:14px; color:#1d1d1f;">
                <b><?php esc_html_e('Top 5 Categories Targeted:', 'Internal-auto-links-manager'); ?></b>
                <?php
                if (empty($sim_data['top_cats'])) {
                    echo '<em style="color:#86868b;">' . esc_html__('None', 'Internal-auto-links-manager') . '</em>';
                } else {
                    $cat_strings = [];
                    foreach ($sim_data['top_cats'] as $cat => $count) {
                        $cat_strings[] = esc_html($cat) . ' (' . number_format_i18n($count) . ')';
                    }
                    echo esc_html(implode(', ', $cat_strings));
                }
                ?>
            </p>
            <div
                style="background: #fff8e6; border-left: 4px solid #f5a623; padding: 12px 16px; border-radius: 6px; margin-top: 16px; font-size: 13px; color: #1d1d1f; display: flex; align-items: center; gap: 8px;">
                <span class="dashicons dashicons-info"
                    style="color: #f5a623; font-size: 18px; width: 18px; height: 18px;"></span>
                <span><strong><?php esc_html_e('Note:', 'Internal-auto-links-manager'); ?></strong>
                    <?php esc_html_e('Final results will slightly vary (usually a few percent lower).', 'Internal-auto-links-manager'); ?></span>
            </div>
            <hr style="border:0; border-top:1px solid #e8e8ed; margin:16px 0;">
            <div style="display: flex; align-items: center; gap: 15px;">
                <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" style="margin: 0;">
                    <input type="hidden" name="action" value="ailm_handle_actions">
                    <input type="hidden" name="submit_action" value="ailm_start_freeze_job">
                    <input type="hidden" name="simulation_id" value="<?php echo esc_attr($sim_id); ?>">
                    <?php wp_nonce_field('ailm_form_nonce'); ?>
                    <button type="submit" class="button button-primary"
                        onclick="return confirm('<?php echo esc_js(__('This will start a background process to create/update links across your site. Are you sure?', 'Internal-auto-links-manager')); ?>')"><?php esc_html_e('Apply &amp; Freeze This Plan', 'Internal-auto-links-manager'); ?></button>
                </form>
                <form method="post" action="<?php echo esc_url(admin_url('admin-post.php')); ?>" style="margin: 0;">
                    <input type="hidden" name="action" value="ailm_handle_actions">
                    <input type="hidden" name="submit_action" value="ailm_run_shuffled_simulation">
                    <?php wp_nonce_field('ailm_form_nonce'); ?>
                    <button type="submit"
                        class="button button-secondary"><?php esc_html_e('Shuffle &amp; Find Another Variation', 'Internal-auto-links-manager'); ?></button>
                </form>
            </div>
        </div>
        <?php
    }

    /**
     * Display a warning notice if the index hard limit (10 000 posts) has been reached.
     * Only shown on plugin admin pages.
     */
    public function display_limit_reached_notice()
    {
        if (!get_option('linkmesh_index_limit_reached', false)) {
            return;
        }

        // Only show on this plugin's admin pages
        // phpcs:ignore WordPress.Security.NonceVerification.Recommended
        if (!isset($_GET['page']) || strpos($_GET['page'], $this->plugin_name) !== 0) {
            return;
        }
        ?>
        <div class="notice notice-warning is-dismissible">
            <p><?php esc_html_e('⚠️ Index limit reached: 10 000 posts. Please upgrade your plan to continue indexing.', 'Internal-auto-links-manager'); ?>
            </p>
        </div>
        <?php
    }

    private function display_admin_notices($notice_key)
    {
        $notices = [
            'csv_imported' => ['color' => '#34c759', 'icon' => 'dashicons-saved', 'message' => __('CSV database successfully imported.', 'Internal-auto-links-manager')],
            'csv_sync_success' => ['color' => '#34c759', 'icon' => 'dashicons-update-alt', 'message' => __('CSV Sync complete: Links updated successfully.', 'Internal-auto-links-manager')],
            'csv_error' => ['color' => '#d93025', 'icon' => 'dashicons-warning', 'message' => __('Error: No file uploaded, or invalid CSV format.', 'Internal-auto-links-manager')],
            'settings_saved' => ['color' => '#34c759', 'icon' => 'dashicons-saved', 'message' => __('Settings saved! A new simulation has been generated below.', 'Internal-auto-links-manager')],
            'settings_saved_only' => ['color' => '#34c759', 'icon' => 'dashicons-saved', 'message' => __('Global Settings saved successfully! (Simulation was skipped)', 'Internal-auto-links-manager')],
            'cache_purged' => ['color' => '#34c759', 'icon' => 'dashicons-saved', 'message' => __('Pool cache cleared!', 'Internal-auto-links-manager')],
            'counters_reset' => ['color' => '#f5a623', 'icon' => 'dashicons-warning', 'message' => __('Inbound link counters reset to 0!', 'Internal-auto-links-manager')],
            'all_unfrozen' => ['color' => '#d93025', 'icon' => 'dashicons-warning', 'message' => __('ALL LINKS UNFROZEN! You can now apply a new plan.', 'Internal-auto-links-manager')],
            'freeze_started' => ['color' => '#0071e3', 'icon' => 'dashicons-info', 'message' => __('Freeze job started! This will run in the background. You can check the Frozen Links Report in a few minutes to see progress.', 'Internal-auto-links-manager')],
            'rule_deleted' => ['color' => '#34c759', 'icon' => 'dashicons-trash', 'message' => __('Route deleted successfully and links removed from site.', 'Internal-auto-links-manager')],
            'manual_synced' => ['color' => '#34c759', 'icon' => 'dashicons-saved', 'message' => __('Manual links successfully synced and added to database!', 'Internal-auto-links-manager')],
        ];
        if (isset($notices[$notice_key])) {
            $notice = $notices[$notice_key];
            echo '<div class="ailm-card" style="border-left: 4px solid ' . esc_attr($notice['color']) . '; margin-bottom: 24px; padding: 16px 20px; display:flex; align-items:center; gap:12px;">';
            echo '<span class="dashicons ' . esc_attr($notice['icon']) . '" style="color:' . esc_attr($notice['color']) . '; font-size:24px; width:24px; height:24px;"></span>';
            echo '<span style="font-weight: 500; font-size: 14px; color: #1d1d1f;">' . esc_html($notice['message']) . '</span>';
            echo '</div>';
        }
    }
}
