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

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

use Exception;
use Plugli\Linksy\SearchAndReplace\Admin\Partials\SearchAndReplace\Helpers\LinkReplace;
use Plugli\Linksy\SearchAndReplace\Admin\Partials\SearchAndReplace\Helpers\AnchorReplace;
use Plugli\Linksy\SearchAndReplace\Admin\Partials\SearchAndReplace\Helpers\TitleReplace;
use Plugli\Linksy\SearchAndReplace\Admin\Partials\SearchAndReplace\Helpers\DatabaseReplace;
use Plugli\Linksy\SearchAndReplace\Admin\Partials\SearchAndReplace\Helpers\BrokenLinks;
use Plugli\Linksy\SearchAndReplace\Admin\Partials\SearchAndReplace\Helpers\UrlReplace;
use Linksy\SearchAndReplace\Plugli\Linksy\Common\Helpers\Ajax;
use Linksy\SearchAndReplace\Plugli\Standard\Helpers\Database\Database;
use Linksy\SearchAndReplace\Plugli\Standard\Helpers\Request;
use Plugli\Linksy\SearchAndReplace\Helpers\Post\Post;

trait AjaxActions
{
    public function linksy_search_and_replace($type)
    {
        try {
            $page = Request::get('page', 0, FILTER_VALIDATE_INT);
            $limit = Request::get('limit', 10, FILTER_VALIDATE_INT);
            $search = Request::get('search', '', FILTER_DEFAULT);
            $search_mode = Request::get('search_mode', 'EXACT', FILTER_DEFAULT);
            $filter_mode = Request::get('filter_mode', '', FILTER_DEFAULT);
            $filter_query = Request::get('filter_query', '', FILTER_DEFAULT);
            $filters = json_decode(Request::get('filter', '[]', FILTER_DEFAULT));
            $selected_tables = json_decode(Request::get('selected_tables', '[]', FILTER_DEFAULT));

            $handler_class = $this->get_handler_class($type);

            $instance = new $handler_class(
                $search,
                (array) $filters,
                $filter_mode
            );

            if ($type === 'DATABASE') {
                $data = $instance->get($search_mode, $filter_query, $selected_tables);
            } else {
                $data = $instance->get($search_mode, $filter_query);
            }

            $results = $this->prepare_results($handler_class, $data, $page, $limit);

            Ajax::success( $results );
        } catch (Exception $e) {
            Ajax::error($e->getMessage());
        }
    }

    public function linksy_search_and_replace_search_links()
    {
        $this->linksy_search_and_replace('SEARCH_LINKS');
    }

    public function linksy_search_and_replace_search_anchors()
    {
        $this->linksy_search_and_replace('SEARCH_ANCHORS');
    }

    public function linksy_search_and_replace_search_titles()
    {
        $this->linksy_search_and_replace('SEARCH_TITLES');
    }

    public function linksy_search_and_replace_search_urls()
    {
        $this->linksy_search_and_replace('SEARCH_URLS');
    }

    public function linksy_search_and_replace_search_broken_links() {
        $this->linksy_search_and_replace('BROKEN_LINKS');
    }
    
    public function linksy_search_and_replace_search_db()
    {
        $this->linksy_search_and_replace('DATABASE');
    }

    public function linksy_search_and_replace_search_offset_db()
    {
        try {
            $search = Request::get('search', '', FILTER_DEFAULT);
            $search_mode = Request::get('search_mode', 'EXACT', FILTER_DEFAULT);
            $filter_mode = Request::get('filter_mode', '', FILTER_DEFAULT);
            $item = json_decode(Request::get('item', '[]', FILTER_DEFAULT));
            $filters = json_decode(Request::get('filter', '[]', FILTER_DEFAULT));

            $instance = new DatabaseReplace(
                $search,
                (array) $filters,
                $filter_mode
            );

            $data = $instance->getNextItems($search_mode, $item);

            Ajax::success( $data );
        } catch (Exception $e) {
            Ajax::error($e->getMessage());
        }
    }

    public function linksy_search_and_replace_replace_db()
    {
        try {
            global $wpdb;

            $search_mode = Request::post('search_mode');
            $replacement = $search_mode === 'CONTAINS' ? Request::post('db_replacement') : json_decode(Request::post('db_replacement'));
            $search = $search_mode === 'CONTAINS' ? Request::post('search') : json_decode(Request::post('search'));
            $items = json_decode(Request::post('items', '[]'));

            $stats = [
                'failed' => [],
                'replaced' => [],
            ];

            foreach ($items as $table) {
                $table_name = str_replace($wpdb->prefix, '', $table->table_name);
        
                foreach ($table->columns as $column) {
                    $column_name = $column->column_name;
        
                    foreach ($column->items as $item) {
                        $item_result = (array) $item;
                        $firstKey = array_key_first($item_result);

                        $queryBuilder = Database::table($table_name)
                                ->where($firstKey, $item_result[$firstKey]);

                        if ($search_mode === 'CONTAINS' && stripos($item->value, $search) !== false) {
                            $new_value = str_ireplace($search, $replacement, $item->value);
                        } elseif ($search_mode === 'STARTS_ENDS_WITH' && is_array($search) && is_array($replacement)) {
                            $raw_column = (array) $queryBuilder->select([$column_name])->one();
                            $column_value = $raw_column[$column_name];

                            if (strpos($item->value, $search[0]) === 0 && substr($item->value, -strlen($search[1])) === $search[1]) {
                                $modified_value = $replacement[0] . substr($item->value, strlen($search[0]), -strlen($search[1])) . $replacement[1];
                        
                                $new_value = preg_replace('/' . preg_quote($item->value, '/') . '/', $modified_value, $column_value, 1);
                            } else {
                                $stats['failed'][] = [
                                    'table' => $table_name,
                                    'item' => $item
                                ];
                                continue;
                            }
                        } else {
                            $stats['failed'][] = [
                                'table' => $table_name,
                                'item' => $item
                            ];
                            continue;
                        }

                        $updated = Database::table($table_name)->where($firstKey, $item_result[$firstKey])->set($column_name, $new_value)->update();

                        if ($updated) {
                            $stats['replaced'][] = [
                                'table' => $table_name,
                                'item' => $item
                            ];
                        } else {
                            $stats['failed'][] = [
                                'table' => $table_name,
                                'item' => $item
                            ];
                        }
                    }
                }
            }

            Ajax::success($stats);
        } catch (Exception $e) {
            Ajax::error($e->getMessage());
        }
    }

    public function linksy_search_and_replace_fetch_db_list() {
        try {
            global $wpdb;
            $tables = $wpdb->get_results("SHOW TABLES", ARRAY_N);

            Ajax::success(
                array_map(function($table) {
                    return (is_array($table) && count($table) === 1 && is_string($table[0])) ? $table[0] : $table;
                }, $tables)
            );
        } catch (Exception $e) {
            Ajax::error($e->getMessage());
        }
    }

    public function linksy_search_and_replace_item_details() {
        try {
            global $wpdb;

            $option = Request::post('option', 'get');
            $item = json_decode(Request::post('item', '[]'));
            $table_name = str_replace($wpdb->prefix, '', Request::post('table_name', ''));

            $response = [];

            if (empty($item) || empty($table_name)) {
                Ajax::error('Invalid item or table name');
                return;
            }

            $item_result = (array) $item->result;
            $firstKey = array_key_first($item_result);

            $queryBuilder = Database::table($table_name)
                    ->where($firstKey, $item_result[$firstKey]);

            if ($option === 'set') {
                $queryBuilder->set($item->column, $item->result->value)->update();

                Ajax::success('Item updated successfully');
            } else {
                $query = $queryBuilder->one();

                $item_details = (array) $query;
                unset($item_details[$item->column]);

                $response = [
                    'selected_details' => [
                        $item->column => $query->{$item->column}
                    ],
                    'other_details' => $item_details,
                ];

                Ajax::success($response);
            }
        } catch (Exception $e) {
            Ajax::error($e->getMessage());
        }
    }

    public function linksy_search_and_replace_recheck_links()
    {
        try {
            $item = json_decode(Request::post('item', '[]'));

            $stats = [
                'failed' => [],
                'replaced' => []
            ];

            $result = $this->linksy_broken_link_check($item);

            $broken_links = Database::table('linksy_broken_links');
            $existing_record = $broken_links->where('url', $item->url)->where('anchor', $item->anchor)->one();
            
            if ($existing_record) {
                $result['check_count'] = $existing_record->check_count + 1;
                $result['is_dismissed'] = $existing_record->is_dismissed;

                if ($result['check_count'] >= 3 && !$result['http_code']) {
                    $result['http_code'] = 408;
                    $result['status_code'] = 408;
                } 

                $deleted = $broken_links->where('url', $item->url)->where('anchor', $item->anchor)->where('post_id', $item->post_id)->delete();

                if ($deleted) {
                    $broken_links->insert($result);
                    $stats['replaced'][] = $result;
                } else { $stats['failed'][] = $item->url; }
            }

            Ajax::success($stats);
        } catch (Exception $e) {
            Ajax::error($e->getMessage());
        }
    }

    public function linksy_search_and_replace_ignore_links()
    {
        $this->process_ignored_links(true);
    }

    public function linksy_search_and_replace_undo_ignore_links()
    {
        $this->process_ignored_links(false);
    }

    public function linksy_search_and_replace_replace_links()
    {
        try {
            $link_replacement = strtolower(Request::postOrFail('link_replacement'));
            $item = json_decode(Request::post('item', '[]'));
            $is_broken = Request::post('is_broken', false);
            
            if (!filter_var($link_replacement, FILTER_VALIDATE_URL)) {
                throw new Exception('Replacement link must be a valid URL');
            }

            $stats = [
                'failed' => [],
                'replaced' => [],
            ];

            $links = $is_broken 
                ? [['view_url' => $item->url, 'anchor' => $item->anchor, 'link_replacement' => $link_replacement]] 
                : array_map(fn($a) => 
                    [
                        'view_url' => $item->link,
                        'anchor' => $a->anchor,
                        'link_replacement' => $link_replacement
                    ],
                    $item->anchors
                );

            // run action and update the stats
            $post = new Post($item->post_id);
            $stats = array_merge($stats, $post->replace_links($links, true, false));

            if ($is_broken && !empty($stats['replaced'])) {
                $this->update_linksy_broken_link($item, $link_replacement);
            }

            Ajax::success($stats);
        } catch (Exception $e) {
            Ajax::error($e->getMessage());
        }
    }

    public function linksy_search_and_replace_replace_match_links()
    {
        try {
            $keyword = Request::post('keyword', '');
            $link_replacement = Request::postOrFail('link_replacement');
            $item = json_decode(Request::post('item', '[]'));

            $stats = [
                'failed' => [],
                'replaced' => [],
            ];
            $site_url = get_site_url();

            $link = $item->link;
            $parsed_url = wp_parse_url($link);

            if (in_array($keyword, ['http', 'https'])) {
                $new_path = $parsed_url['path'];
                $replacement = rtrim($link_replacement) . '://' . $parsed_url['host'] . strtolower($new_path);
            } elseif (strpos($link, $site_url) !== false) {
                $path = str_replace($site_url, '', $link);
                $new_path = rtrim(preg_replace('/-+/', '-', str_ireplace($keyword, $link_replacement, rtrim($path, '/'))), '-');
                $replacement = $site_url . strtolower($new_path);
            } else {
                $path = isset($parsed_url['path']) ? $parsed_url['path'] : '';
                $new_path = rtrim(preg_replace('/-+/', '-', str_ireplace($keyword, $link_replacement, rtrim($path, '/'))), '-');
                $replacement = $parsed_url['scheme'] . '://' . $parsed_url['host'] . strtolower($new_path);
            }

            $links = array_map(
                function ($a) use ($link, $replacement) {
                    return [
                    'view_url' => $link,
                    'anchor' => $a->anchor,
                    'link_replacement' => strtolower($replacement)
                    ];
                }, $item->anchors
            );

            // run action and update the stats
            $post = new Post($item->post_id);
            $stats = array_merge($stats, $post->replace_links($links, true, false));

            Ajax::success($stats);
        } catch (Exception $e) {
            Ajax::error($e->getMessage());
        }
    }

    public function linksy_search_and_replace_remove_match_links()
    {
        try {
            $item = json_decode(Request::post('item', '[]'));

            $stats = [
                'failed' => [],
                'replaced' => [],
            ];

            $keyword = Request::post('keyword', '');
            $link = $item->link;
            $parsed_url = wp_parse_url($link);
            $site_url = get_site_url();

            if (strpos($link, $site_url) !== false) {
                $path = str_replace($site_url, '', $link);
                $new_path = rtrim(preg_replace('/-+/', '-', str_ireplace($keyword, '', rtrim($path, '/'))), '-');
                $replacement = $site_url . strtolower($new_path);
            } else {
                $path = isset($parsed_url['path']) ? $parsed_url['path'] : '';
                $new_path = rtrim(preg_replace('/-+/', '-', str_ireplace($keyword, '', rtrim($path, '/'))), '-');
                $replacement = $parsed_url['scheme'] . '://' . $parsed_url['host'] . strtolower($new_path);
            }

            if (strpos($link, $keyword) !== false) {
                $links = array_map(
                    function ($a) use ($link, $replacement) {
                        return [
                        'view_url' => $link,
                        'anchor' => $a->anchor,
                        'link_replacement' => strtolower($replacement)
                        ];
                    }, $item->anchors
                );
            } else {
                $stats['failed'][] = $link;
            }

            // run action and update the stats
            $post = new Post($item->post_id);
            $stats = array_merge($stats, $post->replace_links($links, true, false));

            Ajax::success($stats);
        } catch (Exception $e) {
            Ajax::error($e->getMessage());
        }
    }

    public function linksy_search_and_replace_unlink_links()
    {
        try {
            $item = json_decode(Request::post('item', '[]'));
            $is_broken = Request::post('is_broken', false);

            $stats = [
                'failed' => [],
                'deleted' => [],
            ];

            $links = isset($item->anchor)
                ? [['view_url' => $item->url, 'view_link' => $item->url, 'anchor' => $item->anchor]] 
                : array_map(fn($a) => ['view_url' => $item->link, 'view_link' => $item->link, 'anchor' => $a->anchor], $item->anchors);

            // run action and update the stats
            $post = new Post($item->post_id);
            $stats = array_merge($stats, $post->delete_links($links, false));

            //TODO: refactor
            if ($is_broken && !empty($stats['deleted'])) {
                Database::table("linksy_broken_links")->where('anchor', $item->anchor)->where('url', $item->url)->where('post_id', $item->post_id)->delete();
            }

            Ajax::success($stats);
        } catch (Exception $e) {
            Ajax::error($e->getMessage());
        }
    }

    public function linksy_search_and_replace_retain_best_links()
    {
        $this->linksy_search_and_replace_unlink_links();
    }

    public function linksy_search_and_replace_replace_titles()
    {
        try {
            $replacement = Request::postOrFail('title_replacement');
            $keyword = Request::post('keyword', '');
            $items = json_decode(Request::post('items', '[]'), true);

            $stats = [
                'replaced' => [],
                'failed' => [],
            ];

            foreach ($items as $item) {
                $title = strtolower($item['source']);
                $post_id = (int)$item['post_id'];
                
                if (strpos($title, $keyword) !== false || preg_match("/" . preg_quote($keyword, '/') . "/i", $title)) {
                    $new_title = str_ireplace($keyword, $replacement, $item['source']);
                }

                $post = new Post($post_id);
                $result = $post->update_title($new_title);

                $result ?  $stats['replaced'][] = $post_id : $stats['failed'][] = $post_id;
            }

            Ajax::success($stats);
        } catch (Exception $e) {
            Ajax::error($e->getMessage());
        }
    }

    public function linksy_search_and_replace_remove_titles()
    {
        try {
            $items = json_decode(Request::post('items', '[]'), true);
            $keyword = Request::post('keyword', '');
            $stats = [
                'replaced' => [],
                'failed' => [],
            ];

            foreach ($items as $item) {
                $title = strtolower($item['source']);
                $post_id = (int)$item['post_id'];

                if (strpos($title, $keyword) !== false  || preg_match("/" . preg_quote($keyword, '/') . "/i", $title)) {
                    $new_title = preg_replace('/\s+/', ' ', str_ireplace($keyword, '', $item['source']));
                }

                $post = new Post($post_id);
                $result = $post->update_title(trim($new_title));

                $result ?  $stats['replaced'][] = $post_id : $stats['failed'][] = $post_id;
            }

            Ajax::success($stats);
        } catch (Exception $e) {
            Ajax::error($e->getMessage());
        }
    }

    public function linksy_search_and_replace_replace_urls()
    {
        try {
            $replacement = Request::postOrFail('url_replacement');
            $keyword = Request::post('keyword', '');
            $items = json_decode(Request::post('items', '[]'), true);

            $stats = [
                'replaced' => [],
                'failed' => [],
            ];

            foreach ($items as $item) {
                $link = strtolower($item['link']);
                $post_id = (int)$item['post_id'];
                
                if (strpos($link, $keyword) !== false || preg_match("/" . preg_quote($keyword, '/') . "/i", $link)) {
                    $new_link = str_ireplace($keyword, $replacement, $item['link']);
                    $new_link = preg_replace('/\s+/', ' ', $new_link);
                    $new_link = preg_replace('/-+/', '-', $new_link);
                    $new_link = preg_replace('/(^-+)|(-+$)/', '', $new_link);
                }

                $result = Database::table('posts')
                    ->where('ID', $post_id)
                    ->set('post_name', $new_link)
                    ->update();
                    
                $result ? $stats['replaced'][] = $post_id : $stats['failed'][] = $post_id;
            }

            Ajax::success($stats);
        } catch (Exception $e) {
            Ajax::error($e->getMessage());
        }
    }

    public function linksy_search_and_replace_remove_urls()
    {
        try {
            $items = json_decode(Request::post('items', '[]'), true);
            $keyword = Request::post('keyword', '');
            $stats = [
                'replaced' => [],
                'failed' => [],
            ];

            foreach ($items as $item) {
                $link = strtolower($item['link']);
                $post_id = (int)$item['post_id'];

                if (strpos($link, $keyword) !== false  || preg_match("/" . preg_quote($keyword, '/') . "/i", $link)) {
                    $new_link = str_ireplace($keyword, '', $item['link']);
                    $new_link = preg_replace('/\s+/', ' ', $new_link);
                    $new_link = preg_replace('/-+/', '-', $new_link);
                    $new_link = preg_replace('/(^-+)|(-+$)/', '', $new_link);
                    $new_link = preg_replace('/-+(\s)|(\s)-+/', '$1$2', $new_link);
                    $new_link = trim($new_link);
                }

                $result = Database::table('posts')
                    ->where('ID', $post_id)
                    ->set('post_name', $new_link)
                    ->update();

                $result ?  $stats['replaced'][] = $post_id : $stats['failed'][] = $post_id;
            }

            Ajax::success($stats);
        } catch (Exception $e) {
            Ajax::error($e->getMessage());
        }
    }

    public function linksy_search_and_replace_replace_anchors()
    {
        try {
            $anchor_replacement = Request::postOrFail('anchor_replacement');
            $items = json_decode(Request::post('items', '[]'));

            $stats = [
                'failed' => [],
                'replaced' => [],
            ];

            foreach ($items as $item) {
                $anchors = [
                    'view_url' => $item->link,
                    'anchor' => $item->anchor,
                    'anchor_replacement' => $anchor_replacement
                ];

                // update the stats
                $post = new Post($item->post_id);
                $stats = array_merge($stats, $this->replace_anchors($post, [$anchors]));
            }

            Ajax::success($stats);
        } catch (Exception $e) {
            Ajax::error($e->getMessage());
        }
    }

    public function linksy_search_and_replace_replace_match_anchors()
    {
        try {
            $anchor_replacement = Request::postOrFail('anchor_replacement');
            $items = json_decode(Request::post('items', '[]'));

            $stats = [
                'failed' => [],
                'replaced' => [],
            ];

            foreach ($items as $item) {
                $keyword = Request::post('keyword', '');
            
                $hyphenPattern = '/(?:\s*-|^)' . preg_quote($keyword, '/') . '(?:-\s*)/i';
            
                if (preg_match($hyphenPattern, $item->anchor)) {
                    throw new Exception('Error: Word mismatch.');
                } else {
                    $replacement = str_replace($keyword, $anchor_replacement, $item->anchor);
                }
            
                $anchor_data = [
                    'view_url' => $item->link,
                    'anchor' => $item->anchor,
                    'anchor_replacement' => trim(preg_replace('/\s*([.,])\s*/', '$1 ', preg_replace('/\s+/', ' ', $replacement)))
                ];
                
                // update the stats
                $post = new Post($item->post_id);
                $stats = array_merge($stats, $this->replace_anchors($post, [$anchor_data]));
            }

            Ajax::success($stats);
        } catch (Exception $e) {
            Ajax::error($e->getMessage());
        }
    }

    public function linksy_search_and_replace_remove_match_anchors()
    {
        try {
            $items = json_decode(Request::post('items', '[]'));

            $stats = [
                'failed' => [],
                'replaced' => [],
            ];

            foreach ($items as $item) {
                $keyword = Request::post('keyword', '');
            
                $replacement = preg_replace('/\s+/', ' ', str_ireplace($keyword, '', $item->anchor));
                $hyphenPattern = '/(?:\s*-|^)' . preg_quote($keyword, '/') . '(?:-\s*)/i';
            
                if (preg_match($hyphenPattern, $item->anchor)) {
                    throw new Exception('Error: Word mismatch.');
                } else {
                    $anchor_replacement = trim(preg_replace('/\s*([.,])\s*/', '$1 ', $replacement));
                }
            
                $anchor_data = [
                    'view_url' => $item->link,
                    'anchor' => $item->anchor,
                    'anchor_replacement' => $anchor_replacement
                ];
            
                // run action and update the stats
                $post = new Post($item->post_id); // Assuming $item still has post_id
                $stats = array_merge_recursive($stats, $this->replace_anchors($post, [$anchor_data]));
            }

            Ajax::success($stats);
        } catch (Exception $e) {
            Ajax::error($e->getMessage());
        }
    }

    public function linksy_search_and_replace_unlink_anchors()
    {
        try {
            $items = json_decode(Request::post('items', '[]')); 

            $stats = [
                'failed' => [],
                'deleted' => [],
            ];
            foreach ($items as $item) {
                $anchors = [
                    'view_url' => $item->link,
                    'view_link' => $item->link,
                    'anchor' => $item->anchor,
                ];

                // instantiate the post with the given id
                $post = new Post($item->post_id);

                // run action and update the stats
                $stats = array_merge($stats, $post->delete_links([$anchors], false));
            }

            Ajax::success($stats);
        } catch (Exception $e) {
            Ajax::error($e->getMessage());
        }
    }

    public function linksy_search_and_replace_fix_anchors()
    {
        try {
            $items = json_decode(Request::post('items', '[]'));

            $stats = [
                'failed' => [],
                'fixed' => [],
            ];
            foreach ($items as $item) {
                $anchors = [
                    'view_url' => $item->link,
                    'anchor' => $item->anchor,
                ];

                $post = new Post($item->post_id);

                $stats = array_merge($stats, $this->fix_anchors($post, $anchors));
            }

            Ajax::success($stats);
        } catch (Exception $e) {
            Ajax::error($e->getMessage());
        }
    }

    public function linksy_search_and_replace_retain_best_anchors()
    {
        $this->linksy_search_and_replace_unlink_anchors();
    }

    public function linksy_search_and_replace_rescan_broken_links()
    {
        try {
            $message = 'Rescan initiated successfully. Will run in the background.';

            if (get_option('linksy_link_analysis_cron_enabled', false)) {
                $message = 'Rescan job already in progress.';
            } else {
                update_option('linksy_link_analysis_cron_enabled', true);
                update_option('linksy_link_analysis_offset', 0);
            }
            
            Ajax::success([
                'message' => $message
            ]);
        } catch (Exception $e) {
            Ajax::error($e->getMessage());
        }
    }

    private function process_ignored_links(bool $ignore)
    {
        try {
            $item = json_decode(Request::post('item', '[]'));

            $stats = [
                'failed' => [],
                'replaced' => []
            ];

            $broken_links = Database::table('linksy_broken_links');
            $existing_record = $broken_links->where('url', $item->url)
                                            ->where('anchor', $item->anchor)
                                            ->where('post_id', $item->post_id)
                                            ->one();

            if ($existing_record) {
                $broken_links->where('url', $item->url)
                            ->where('post_id', $item->post_id)
                            ->where('anchor', $item->anchor)
                            ->set('is_dismissed', $ignore ? 1 : 0)
                            ->update();

                $stats['replaced'][] = $item;
            } else {
                $stats['failed'][] = $item;
            }

            Ajax::success($stats);
        } catch (Exception $e) {
            Ajax::error($e->getMessage());
        }
    }
    
    private function get_handler_class($type)
    {
        switch ($type) {
            case 'SEARCH_LINKS':
                return LinkReplace::class;
            case 'SEARCH_ANCHORS':
                return AnchorReplace::class;
            case 'SEARCH_TITLES':
                return TitleReplace::class;
            case 'SEARCH_URLS':
                return UrlReplace::class;
            case 'BROKEN_LINKS':
                return BrokenLinks::class;
            case 'DATABASE':
                return DatabaseReplace::class;
            default:
                throw new Exception('Invalid type');
        }
    }

    private function prepare_results($handler_class, $data, $page, $limit)
    {
        if ($handler_class === BrokenLinks::class) {
            return [
                'total' => count($data['data']),
                'total_links' => $data['total_links'],
                'total_redirects' => $data['total_redirects'],
                'total_warning' => $data['total_warning'],
                'total_broken' => $data['total_broken'],
                'total_timeout' => $data['total_timeout'],
                'total_ignored' => $data['total_ignored'],
                'results' => array_slice(
                    array_values($data['data']),
                    $page * $limit,
                    $limit
                )
            ];
        }

        $results = array_slice(array_values($data), $page * $limit, $limit);

        $response = [
            'total' => count($data),
            'results' => $results
        ];

        if ($handler_class === DatabaseReplace::class) {
            $response['tables'] = array_column($data, 'table_name');
        }

        return $response;
    }

    public function linksy_search_and_replace_sync_posts()
    {
        try {
            $setup = Request::get('setup', false);

            $opts = [
                'fields'      => 'ids',
                'numberposts' => -1,
                'post_status' => 'publish',
                'post_type'   => ['post', 'page'],
            ];
            
            $published = get_posts($opts);

            if (count($published)) {
                $new_posts = [];
                foreach ($published as $id) {
                    $post = new Post($id);
                    $this->refresh_links($post, $setup);
                }
            }

            Ajax::success(
                [
                'published' => count($published)
                ]
            );
        } catch (Exception $e) {
            Ajax::error($e->getMessage());
        }
    }

}
