<?php

use SEOAIC\SEOAICAjaxResponse;

class SeoaicAuditData
{
    private $seoaic;

    public function __construct($_seoaic)
    {
        $this->seoaic = $_seoaic;
        add_action('wp_ajax_seoaic_get_seo_audit_data', [$this, 'get_seo_audit_data'], 2);
        add_action('wp_ajax_seoaic_create_seo_audit', [$this, 'create_seo_audit'], 2);
        add_action('wp_ajax_seoaic_get_page_speed_analysis', [$this, 'get_page_speed_analysis']);
        add_action('wp_ajax_seoaic_get_lighthouse_dates_html', [$this, 'get_lighthouse_dates_html']);
        add_action('wp_ajax_seoaic_get_all_site_links', [$this, 'get_all_site_links']);
    }

    /**
     * Get seo audit data
     *
     */
    public function get_seo_audit_data()
    {
        check_ajax_referer(SeoaicAjaxValidation::ACTION_STRING);

        global $SEOAIC_OPTIONS;

        //dump data cause backend require at least for something
        $data = [
            'version' => 5
        ];

        $result = $this->seoaic->curl->init('api/audit/latest', $data, true, true, true);

        if (!empty($result['auditInfoPages'])) {
            $previousAverage = $SEOAIC_OPTIONS['seoaic_average_score'];
            $currentAverage = $this->setAveragePerformance($result['auditInfoPages']);

            if ($previousAverage === null || $previousAverage !== $currentAverage) {
                $this->seoaic->set_option('seoaic_average_score', $currentAverage);
            }

            $result['errorsDescription'] = $this->errorsDescription();
        }

        $result['crawl_status']['max_crawl_pages'] = getTotalPublishedPostsCount() >= 1000 ? 1000 : getTotalPublishedPostsCount();

        wp_send_json($result);
    }

    /**
     * Request seo audit
     *
     */
    public function create_seo_audit()
    {
        check_ajax_referer(SeoaicAjaxValidation::ACTION_STRING);

        //dump data cause backend require at least for something
        $data = [
            'id' => 5
        ];

        $result = $this->seoaic->curl->init('api/audit/create', $data, true, true, true);

        wp_send_json(
            $result
        );
    }

    private function setAveragePerformance($data)
    {
        $scores = array_column($data, 'onpage_score');
        $averageScore = count($scores) > 0 ? array_sum($scores) / count($scores) : 0;
        return round($averageScore);
    }

    public function errorsDescription()
    {
        $errorData = [
            'high_loading_time' => esc_html__('Page with high loading time indicates whether a page loading time exceeds 3 seconds.', 'seoaic'),
            'is_4xx_code' => esc_html__('Page with 4xx status codes indicates whether a page has 4xx response code.', 'seoaic'),
            'is_5xx_code' => esc_html__('Page with 5xx status codes indicates whether a page has 5xx response code.', 'seoaic'),
            'is_broken' => esc_html__('Broken page indicates whether a page returns a response code less than 200 or greater than 400.', 'seoaic'),
            'high_waiting_time_error' => esc_html__('High Waiting Time Error occurs when the time taken to complete a process or operation exceeds the acceptable or predefined threshold.', 'seoaic'),
            'has_micromarkup_errors' => esc_html__('Page contains microdata markup errors.', 'seoaic'),
            'no_doctype' => esc_html__('Page with no doctype indicates whether a page is without the <!DOCTYPE HTML> declaration.', 'seoaic'),
            'no_h1_tag' => esc_html__('Page with empty or absent h1 tags.', 'seoaic'),
            'https_to_http_links' => esc_html__('HTTPS page has links to HTTP pages.', 'seoaic'),
            'size_greater_than_3mb' => esc_html__('Page with size larger than 3 MB, the page size is exceeding 3 MB.', 'seoaic'),
            'has_render_blocking_resources' => esc_html__('Page with render-blocking resources, the page has render-blocking scripts or stylesheets.', 'seoaic'),
            'low_content_rate' => esc_html__('Page with low content rate indicates whether a page has the plaintext size to page size ratio of less than 0.1.', 'seoaic'),
            'low_character_count' => esc_html__('Indicates whether the page has less than 1024 characters.', 'seoaic'),
            'title_too_short' => esc_html__('Page with short titles indicates whether the content of the title tag is shorter than 30 characters.', 'seoaic'),
            'deprecated_html_tags' => esc_html__('Deprecated HTML tags are allowed but not recommended and are replaced by newer alternatives.', 'seoaic'),
            'duplicate_meta_tags' => esc_html__('Page with duplicate meta tags indicates whether a page has more than one meta tag of the same type.', 'seoaic'),
            'duplicate_title_tag' => esc_html__('Page with more than one title tag indicates whether a page has more than one title tag.', 'seoaic'),
            'no_image_alt' => esc_html__('Images without alt tags.', 'seoaic'),
            'no_image_title' => esc_html__('Images without title tags.', 'seoaic'),
            'no_description' => esc_html__('Pages with no description indicates whether a page has an empty or absent description meta tag.', 'seoaic'),
            'no_title' => esc_html__('Page with no title indicates whether a page has an empty or absent title tag.', 'seoaic'),
            'no_favicon' => esc_html__('Page with no favicon.', 'seoaic'),
            'flash' => esc_html__('Page with flash indicates whether a page has flash elements.', 'seoaic'),
            'frame' => esc_html__('Page with frames indicates whether a page contains frame, iframe, frameset tags.', 'seoaic'),
            'lorem_ipsum' => esc_html__('Page with lorem ipsum indicates whether a page has lorem ipsum content.', 'seoaic'),
            'canonical_chain' => esc_html__('Page with a canonical link pointing to another page that also has a canonical link.', 'seoaic'),
            'canonical_to_redirect' => esc_html__('Page with a canonical link pointing to a redirect.', 'seoaic'),
            'canonical_to_broken' => esc_html__('Page with a canonical link pointing to a broken page.', 'seoaic'),
            'is_orphan_page' => esc_html__('Page with no internal links pointing to it.', 'seoaic'),
            'is_link_relation_conflict' => esc_html__('Page with both followed and nofollowed incoming internal links.', 'seoaic'),
            'redirect_chain' => esc_html__('Page with multiple redirects before the crawler reached it.', 'seoaic'),
            'no_content_encoding' => esc_html__('Page with no content encoding indicates whether a page has no compression algorithm of the content.', 'seoaic'),
            'is_https' => esc_html__('Page without the HTTPS protocol.', 'seoaic'),
            'has_html_doctype' => esc_html__('Page without HTML doctype declaration.', 'seoaic'),
            'canonical' => esc_html__('Page is canonical.', 'seoaic'),
            'has_meta_title' => esc_html__('Page missing a meta title tag.', 'seoaic'),
            'high_character_count' => esc_html__('Indicates whether the page has more than 256,000 characters.', 'seoaic'),
            'high_content_rate' => esc_html__('Page with high content rate indicates whether a page has the plaintext size to page size ratio of more than 0.9.', 'seoaic'),
            'irrelevant_description' => esc_html__('Page with irrelevant description indicates whether the description tag is irrelevant to the page content.', 'seoaic'),
            'irrelevant_title' => esc_html__('Page with irrelevant title indicates whether the title tag is irrelevant to the page content.', 'seoaic'),
            'irrelevant_meta_keywords' => esc_html__('Page with irrelevant meta keywords indicates whether the keywords tag is irrelevant to the page content.', 'seoaic'),
            'title_too_long' => esc_html__('Page with a long title indicates whether the title tag exceeds 65 characters.', 'seoaic'),
            'large_page_size' => esc_html__('Page exceeds the size limit of 1 MB.', 'seoaic'),
            'high_waiting_time' => esc_html__('Page waiting time exceeds 1.5 seconds.', 'seoaic'),
            'has_micromarkup' => esc_html__('Page includes microdata markup.', 'seoaic'),
            'no_encoding_meta_tag' => esc_html__('Page without a meta tag for Content-Type encoding if not explicitly defined in the HTTP header.', 'seoaic'),
            'meta_charset_consistency' => esc_html__('Page with no meta charset tag.', 'seoaic'),
            'low_readability_rate' => esc_html__('Page with a low readability rate indicates a score less than 15 points on the Flesch–Kincaid readability test.', 'seoaic'),
            'seo_friendly_url' => esc_html__('Page with no SEO-friendly URL. Checked by relative path length, special characters, dynamic parameters, and URL relevance.', 'seoaic'),
            'duplicate_description' => esc_html__('Indicates whether a page has a duplicate description', 'seoaic'),
            'default_description' => esc_html__('No description available for this error.', 'seoaic')
        ];

        return $errorData;
    }

    private function request_page_speed_init($url)
    {
        $data = [
            'url' => $url,
        ];
        return $this->seoaic->curl->init('/api/audit/lighthouse/init', $data, true, true, true);
    }

    private function request_page_speed_list($url)
    {
        $_post = wp_unslash($_POST); // phpcs:ignore WordPress.Security.NonceVerification.Recommended,WordPress.Security.NonceVerification.Missing
        $data = [
            'url' => $url,
        ];
        return $this->seoaic->curl->init('/api/audit/lighthouse/list', $data, true, true, true);
    }

    private function request_page_speed_audit($id)
    {
        if (!$id) {
            return null;
        }
        $data = [];
        return $this->seoaic->curl->init('/api/audit/lighthouse/' . $id, $data, true, true, true);
    }

    private function get_lighthouse_dates($url)
    {
        $data = $this->request_page_speed_list($url);

        return array_map(function ($item) {
            return [
                'id' => $item['id'],
                'created_at' => $item['created_at'],
                'status' => $item['status'],
            ];
        }, $data);
    }

    private function get_lighthouse_date_by_id($url, $id)
    {
        $data = $this->request_page_speed_list($url);

        $filteredData = array_filter($data, function ($item) use ($id) {
            return $item['id'] == $id;
        });

        if (!empty($filteredData)) {
            $item = reset($filteredData);
            return [
                'id' => $item['id'],
                'created_at' => $item['created_at'],
                'status' => $item['status'],
            ];
        }

        return null;
    }

    private function remove_helper_link_text($text)
    {
        $pattern = '/\[[^\]]+\]\([^)]+\)/';
        $cleaned_text = preg_replace($pattern, '', $text);
        $cleaned_text = preg_replace('/\s*\.\s*\./', '.', $cleaned_text);
        return esc_html(trim($cleaned_text));
    }

    private function get_score_class($score)
    {
        $normal_score = $score * 100;

        if ($score === null) {
            return '';
        }

        if ($normal_score >= 0 && $normal_score <= 49) {
            return 'bad';
        } elseif ($normal_score >= 50 && $normal_score <= 89) {
            return 'medium';
        } elseif ($normal_score >= 90 && $normal_score <= 100) {
            return 'good';
        }
    }

    private function criticalrequestchain($chains)
    {
        $html = '';

        foreach ($chains as $key => $value) {
            if (is_array($value)) {
                $class = $key === 'request' ? 'request'
                    : ($key === 'children' ? 'children' : 'section requestchain');

                $html .= "<div class=\"{$class}\">" . $this->criticalrequestchain($value) . '</div>';
                continue;
            }

            switch ($key) {
                case 'startTime':
                case 'endTime':
                case 'responseReceivedTime':
                    $value = round($value / 1_000_000, 1) . ' s';
                    break;
                case 'transferSize':
                    $value .= ' B';
                    break;
            }

            $html .= sprintf(
                '<p><strong>%s:</strong> %s</p>',
                htmlspecialchars((string)$key, ENT_QUOTES, 'UTF-8'),
                htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8')
            );
        }

        return $html;
    }

    private function render_table_headings($headings)
    {
        $html = '';
        if (!empty($headings) && is_array($headings)) {
            $html .= '<thead><tr>';
            foreach ($headings as $heading) {
                $label = htmlspecialchars($heading['label'] ?? '', ENT_QUOTES, 'UTF-8');
                $html .= "<th>{$label}</th>";
            }
            $html .= '</tr></thead>';
        }
        return $html;
    }

    private function render_table_rows(array $items, array $headings): string
    {
        $html = '';

        foreach ($items as $item) {
            $html .= '<tr>';
            $html .= $this->render_table_cells($item, $headings);
            $html .= '</tr>';
        }

        return $html;
    }

    private function render_table_cells(array $item, array $headings): string
    {
        $html = '';

        foreach ($headings as $heading) {
            $key = $heading['key'] ?? '';
            $valueType = $heading['valueType'] ?? 'text';
            $value = $item[$key] ?? '';

            switch ($valueType) {
                case 'bytes':
                case 'numeric':
                    $value = number_format((float)$value);
                    break;
                case 'url':
                    $value = '<a href="' . htmlspecialchars($value, ENT_QUOTES, 'UTF-8') . '">' .
                        htmlspecialchars($value, ENT_QUOTES, 'UTF-8') . '</a>';
                    break;
                case 'node':
                    $value = htmlspecialchars($value['nodeLabel'] ?? '', ENT_QUOTES, 'UTF-8');
                    break;
                default:
                    if (is_array($value)) {
                        $value = json_encode($value, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
                    } else {
                        $value = htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8');
                    }
                    break;
            }

            $html .= "<td>{$value}</td>";
        }

        return $html;
    }

    private function render_table_footer(array $data): string
    {
        $savingsMs = $data['overallSavingsMs'] ?? 0;
        $savingsBytes = $data['overallSavingsBytes'] ?? 0;

        if (!$savingsMs && !$savingsBytes) {
            return '';
        }

        $colspan = count($data['headings'] ?? []);

        return sprintf(
            '<tfoot><tr><td colspan="%d">%s %s %s %s %s</td></tr></tfoot>',
            $colspan,
            esc_html__('Overall Savings:', 'seoaic'),
            number_format($savingsMs),
            esc_html__('ms,', 'seoaic'),
            number_format($savingsBytes),
            esc_html__('bytes', 'seoaic')
        );
    }

    private function render_table($data)
    {
        return '<table class="table-opportunity">'
                . $this->render_table_headings($data['headings'])
                . '<tbody>' . $this->render_table_rows($data['items'], $data['headings']) . '</tbody>'
                . $this->render_table_footer($data)
            . '</table>';
    }

    private function get_opportunity($data)
    {
        if (empty($data['items']) || !is_array($data['items'])) {
            return '';
        }

        $isMultipleTables = isset($data['items'][0]['type']) && $data['items'][0]['type'] === 'table';

        $html = '';
        $items = $isMultipleTables ? $data['items'] : [$data];

        foreach ($items as $tableData) {
            $html .= $this->render_table($tableData);
        }

        return $html;
    }

    /**
     * @throws Exception
     */
    private function format_audit_date($dateString)
    {
        $date = new DateTime($dateString);
        return $date->format('d.m.Y | g:ia');
    }

    private function create_date_link($date, $index = false)
    {
        $formatted_date = $this->format_audit_date($date['created_at']);
        $status_loading = $date['status'] === 'created' ? '<span class="analysing">' . esc_html__('Diagnose issues', 'seoaic') . '</span>' : '';

        $first_run = ($index === 0) ? '<li class="seoaic-list-style-none fs-small ls-3">' . esc_html__('First audit') . '</li>' : '';
        $latest_run = ($index === 1) ? '<li class="seoaic-list-style-none fs-small ls-3 mt-40">' . esc_html__('Latest Audits') . '</li>' : '';

        return $first_run . $latest_run . '<li><a href="#" data-status="' . $date['status'] . '" data-audit-id="' . $date['id'] . '">' . $status_loading . '<span class="date">' . $formatted_date . '</span></a></li>';
    }

    public function get_lighthouse_dates_html()
    {
        check_ajax_referer(SeoaicAjaxValidation::ACTION_STRING);

        $_post = wp_unslash($_POST); // phpcs:ignore WordPress.Security.NonceVerification.Recommended,WordPress.Security.NonceVerification.Missing

        if (empty($_post['url'])) {
            SEOAICAjaxResponse::alert('URL not valid or not set')->wpSend();
        }

        $url = $_post['url'];

        if (!empty($_post['rescan'])) {
            $this->request_page_speed_init($url);
        }

        if (!empty($_post['id'])) {
            $id = $_post['id'];
            $date = $this->get_lighthouse_date_by_id($url, $id);
            $send = $this->create_date_link($date);
            wp_send_json($send);
        }

        $dates_available = array_values(array_unique($this->get_lighthouse_dates($url), SORT_REGULAR));

        $dates_available_html = '';
        foreach ($dates_available as $index => $date) {
            $dates_available_html .= $this->create_date_link($date, $index);
        }

        $most_recent = array_reduce($dates_available, function ($carry, $item) {
            if ($carry === null) {
                return $item;
            }
            return strtotime($item['created_at']) > strtotime($carry['created_at']) ? $item : $carry;
        });

        $most_recent_id = $most_recent ? $most_recent['id'] : null;

        $send = [
            'html' => $dates_available_html,
            'most_recent_id' => $most_recent_id
        ];

        if ($most_recent_id) {
            $send['most_recent_id'] = $most_recent_id;
        }

        wp_send_json($send);
    }


    private function device_analysis($categories, $audits, $prefix)
    {

        $performance_refs = $categories['performance']['auditRefs'];
        $accessibility_refs = $categories['accessibility']['auditRefs'];
        $best_practices_refs = $categories['best-practices']['auditRefs'];
        $seo_refs = $categories['seo']['auditRefs'];

        $performance = '<div class="row-line heading"> <div class="title"></div> <div class="score"> ' . esc_html__('Score', 'seoaic') . ' </div> <div class="detail"> ' . esc_html__('Details', 'seoaic') . ' </div> </div>';
        $performanceDiagnosticsRendered = false;
        foreach ((array)$performance_refs as $i => $ref) {
            $get_audits = $this->get_speed_audits_data($audits, $ref);
            if ($ref['group'] === 'metrics') {
                $performance .= '<div class="row-line">';
                $performance .= '<div class="title">' . $get_audits['title'] . '</div>';
                $performance .= '<div class="score ' . $this->get_score_class($get_audits['score']) . '">' . $get_audits['display_value'] . '</div>';
                $performance .= '<div class="detail"><a href="#">' . $this->remove_helper_link_text($get_audits['description']) . '</a></div>';
                $performance .= '</div>';
            }

            if ($ref['group'] === 'diagnostics') {
                if (!$performanceDiagnosticsRendered) {
                    $performance .= '<div class="row-line heading diagnostics"><h3>' . esc_html__('Performance diagnostics', 'seoaic') . '</h3><label for="seoaic_performance_diagnostics_open_' . $prefix . '"></label></div>';
                    $performance .= '<input type="checkbox" id="seoaic_performance_diagnostics_open_' . $prefix . '">';
                    $performanceDiagnosticsRendered = true;
                }
                $performance .= '<div class="row-line diagnostics ' . $get_audits['details_type'] . '">';
                $performance .= '<div class="title">' . $get_audits['title'] . '</div>';
                $performance .= '<div class="score ' . $this->get_score_class($get_audits['score']) . '">' . $get_audits['display_value'] . '</div>';
                $performance .= '<input type="checkbox" id="diagnostics-' . $i . '_' . $prefix . '"><label for="diagnostics-' . $i . '_' . $prefix . '"></label><div class="detail open-more"><p class="sub-description">' . $this->remove_helper_link_text($get_audits['description']) . '</p>'
                    . $get_audits['chains']
                    . $get_audits['get_opportunity']
                    . '</div>';
                $performance .= '</div>';
            }
        }

        $accessibility = $this->detailed_list($accessibility_refs, $audits, $prefix, 'accessibility', esc_html__('Accessibility diagnostics', 'seoaic'));
        $best_practices = $this->detailed_list($best_practices_refs, $audits, $prefix, 'best_practices', esc_html__('Best practices diagnostics', 'seoaic'));
        $seo = $this->detailed_list($seo_refs, $audits, $prefix, 'seo', esc_html__('SEO diagnostics', 'seoaic'));

        return [
            'performance_score' => isset($categories['performance']['score']) ? round($categories['performance']['score'] * 100) : 0,
            'accessibility_score' => isset($categories['accessibility']['score']) ? round($categories['accessibility']['score'] * 100) : 0,
            'best_practices_score' => isset($categories['best-practices']['score']) ? round($categories['best-practices']['score'] * 100) : 0,
            'seo_score' => isset($categories['seo']['score']) ? round($categories['seo']['score'] * 100) : 0,
            'final-screenshot' => $audits['final-screenshot']['details']['data'] ?? '',
            'time-to-interactive' => $audits['interactive']['displayValue'] ?? 'N/A',
            'detailed_performance' => $performance,
            'detailed_accessibility' => $accessibility,
            'detailed_best_practices' => $best_practices,
            'detailed_seo' => $seo
        ];
    }

    private function detailed_list($refs, $audits, $prefix, $metric, $title)
    {
        $html = '';
        $html .= '<div class="row-line heading diagnostics"><h3>' . $title . '</h3><label for="seoaic_' . $metric . '_diagnostics_open_' . $prefix . '"></label></div>';
        $html .= '<input type="checkbox" id="seoaic_' . $metric . '_diagnostics_open_' . $prefix . '">';
        foreach ((array)$refs as $i => $ref) {
            $get_audits = $this->get_speed_audits_data($audits, $ref);
            $html .= $this->diagnostics_rows($get_audits, $metric, $i, $prefix);
        }

        return $html;
    }

    private function get_speed_audits_data($audits, $ref)
    {

        $displayValue = !empty($audits[$ref['id']]['displayValue']) ? $audits[$ref['id']]['displayValue'] : $this->get_score_class($audits[$ref['id']]['score']);
        $details_type = !empty($audits[$ref['id']]['details']['type']) ? $audits[$ref['id']]['details']['type'] : '';
        $chains = $details_type === 'criticalrequestchain' ? $this->criticalrequestchain($audits[$ref['id']]['details']['chains']) : '';
        $get_opportunity = $details_type === 'opportunity' || $details_type === 'table' || $details_type === 'list' ? $this->get_opportunity($audits[$ref['id']]['details']) : '';
        $title = !empty($audits[$ref['id']]['title']) ? $audits[$ref['id']]['title'] : '';
        $description = !empty($audits[$ref['id']]['description']) ? $audits[$ref['id']]['description'] : '';
        $score = !empty($audits[$ref['id']]['score']) ? $audits[$ref['id']]['score'] : 0;

        return [
            'display_value'=> $displayValue,
            'details_type'=> $details_type,
            'chains'=> $chains,
            'get_opportunity'=> $get_opportunity,
            'title'=> $title,
            'description'=> $description,
            'score'=> $score
        ];
    }

    private function diagnostics_rows($get_audits, $metric, $index, $prefix)
    {
        $html = '';
        $html .= '<div class="row-line diagnostics ' . $get_audits['details_type'] . '">';
        $html .= '<div class="title">' . esc_html($get_audits['title']) . '</div>';
        $html .= '<div class="score ' . $this->get_score_class($get_audits['score']) . '">' . $get_audits['display_value'] . '</div>';
        $html .= '<input type="checkbox" id="' . $metric . '-' . $index . '_' . $prefix . '"><label for="' . $metric . '-' . $index . '_' . $prefix . '"></label><div class="detail open-more"><p class="sub-description">' . $this->remove_helper_link_text($get_audits['description']) . '</p>'
            . $get_audits['chains']
            . $get_audits['get_opportunity']
            . '</div>';
        $html .= '</div>';

        return $html;
    }

    public function get_page_speed_analysis()
    {
        check_ajax_referer(SeoaicAjaxValidation::ACTION_STRING);

        $_post = wp_unslash($_POST); // phpcs:ignore WordPress.Security.NonceVerification.Recommended,WordPress.Security.NonceVerification.Missing

        $id = $_post['id'];
        $result = $this->request_page_speed_audit($id);

        $mobile = $result['audit_data_mobile'] ?? [];
        $desktop = $result['audit_data_desktop'] ?? [];

        $send = [
            'id' => $id,
            'status' => $result['status']
        ];

        if ($mobile || $desktop) {
            $send['mobile'] = $this->device_analysis($mobile['categories'], $mobile['audits'], 'mobile');
            $send['desktop'] = $this->device_analysis($desktop['categories'], $desktop['audits'], 'desktop');
        }

        wp_send_json($send);
    }

    private function search_string_processing($search)
    {
        if (filter_var($search, FILTER_VALIDATE_URL)) {
            preg_match('/([^\/]+)\/?$/', parse_url($search, PHP_URL_PATH), $matches);
            if (!empty($matches[1])) {
                return preg_replace('/[-_]+/', ' ', $matches[1]);
            } else {
                return ' ';
            }
        }

        return $search;
    }

    private function get_home_id()
    {
        global $wpdb;
        $home_page_id = $wpdb->get_var("SELECT option_value FROM $wpdb->options WHERE option_name = 'page_on_front' LIMIT 1");
        return intval($home_page_id);
    }

    public function get_all_site_links($offset = 0, $limit = 10, $return = false, $get_home = false, $with_total = false, $exclude_ids = [], $included_ids = [])
    {
        $post = filter_input_array(INPUT_POST, [
            'offset' => FILTER_VALIDATE_INT,
            'limit'  => FILTER_VALIDATE_INT,
            'search' => FILTER_SANITIZE_SPECIAL_CHARS,
            'post_type' => FILTER_SANITIZE_SPECIAL_CHARS,
            'exclude_ids' => FILTER_SANITIZE_SPECIAL_CHARS,
            'include_ids' => FILTER_SANITIZE_SPECIAL_CHARS,
            'select_key_pages' => FILTER_VALIDATE_BOOLEAN,
            'is_seoaic_posted' => FILTER_VALIDATE_BOOLEAN,
            'suggested_pages' => FILTER_SANITIZE_SPECIAL_CHARS,
        ]);

        $is_multi_lang = function_exists('pll_get_post_language') || defined('ICL_LANGUAGE_CODE');

        if (!empty($post['limit'])) {
            $offset = $post['offset'] ?? $offset;
            $limit = $post['limit'];
        }

        $search = !empty($post['search']) ? $this->search_string_processing(trim($post['search'])) : '';

        $exclude_ids_post = !empty($post['exclude_ids']) ? array_filter(array_map('intval', explode(',', $post['exclude_ids']))) : [];
        $exclude_ids = array_unique(array_merge($exclude_ids_post, array_map('intval', (array)$exclude_ids)));

        $post_included_ids = !empty($post['include_ids']) ? array_filter(array_map('intval', explode(',', $post['include_ids']))) : [];
        $included_ids = array_unique(array_merge((array)$included_ids, $post_included_ids));

        $data = [];
        $home_url = home_url('/');
        $home_page_id = $this->get_home_id();

        if ($home_page_id != 0) {
            $home_page_title = get_the_title($home_page_id);
            $home_url = get_the_permalink($home_page_id);
        } else {
            $home_page_title = esc_html__('Home', 'seoaic');
        }

        if ($offset === 0 && $home_page_title && !in_array($home_page_id, $exclude_ids) && empty($post['select_key_pages'])) {
            $data[] = [
                'id' => $home_page_id,
                'text' => $with_total ? $home_page_title : $home_page_title . " ({$home_url})",
                'url' => $home_url
            ];
        }

        if ($get_home && !empty($data[0])) {
            return $data[0];
        }

        $post_types = !empty($post['post_type']) ? $post['post_type'] : seoaic_get_post_types();

        if (!empty($post['suggested_pages']) && empty($search) && empty($included_ids) && $offset === 0) {
            $suggested_pages = array_filter(array_map('intval', explode(',', $post['suggested_pages'])));
            if (!empty($suggested_pages)) {
                $query_args_suggested = [
                    'post_type' => $post_types,
                    'post_status' => 'publish',
                    'posts_per_page' => -1,
                    'post__in' => $suggested_pages,
                    'orderby' => 'none',
                    'suppress_filters' => false,
                ];

                if ($is_multi_lang) {
                    $query_args_suggested['lang'] = '';
                }

                $suggested_query = new WP_Query($query_args_suggested);

                $posts_by_id = [];
                foreach ($suggested_query->posts as $post_item) {
                    $posts_by_id[$post_item->ID] = $post_item;
                }

                foreach ($suggested_pages as $id) {
                    if (isset($posts_by_id[$id])) {
                        $post_item = $posts_by_id[$id];
                        $data[] = [
                            'id' => $post_item->ID,
                            'text' => $with_total ? $post_item->post_title : "{$post_item->post_title} (" . get_permalink($post_item->ID) . ")",
                            'url' => get_permalink($post_item->ID)
                        ];
                    }
                }

                $exclude_ids = array_merge($exclude_ids, $suggested_pages);
            }
        }

        $excluded_taxonomies = ['elementor_library_type', 'wp_theme'];
        $taxonomies = array_diff(get_taxonomies(['show_in_nav_menus' => true], 'names'), $excluded_taxonomies);

        $query_args = [
            'post_type' => $post_types,
            'post_status' => 'publish',
            'posts_per_page' => $limit,
            'offset' => $offset,
            'suppress_filters' => false,
        ];

        if ($is_multi_lang) {
            $query_args['lang'] = '';
            $query_args['suppress_filters'] = false;
        }

        if (!empty($included_ids)) {
            $query_args['post__in'] = $included_ids;
        } else {
            if (!empty($search)) {
                $query_args['s'] = $search;
                array_shift($data);
            } else {
                if ($home_page_id && !in_array($home_page_id, $exclude_ids)) {
                    $query_args['post__not_in'][] = $home_page_id;
                }
            }
            if (!empty($exclude_ids)) {
                $query_args['post__not_in'] = array_merge($query_args['post__not_in'] ?? [], $exclude_ids);
            }
        }

        $query = new WP_Query($query_args);
        $loaded_count = 0;

        foreach ($query->posts as $post) {
            $post_url = get_permalink($post->ID);
            $post_title = $post->post_title;

            if (!empty($search) && stripos($post_title, $search) === false && stripos($post_url, $search) === false) {
                continue;
            }

            $data[] = [
                'id' => $post->ID,
                'text' => $with_total ? $post_title : "{$post_title} ({$post_url})",
                'url' => $post_url
            ];
            $loaded_count++;
        }

        $exclude_taxonomies = true;

        if (!$exclude_taxonomies) {
            if ($loaded_count < $limit) {
                $remaining = $limit - $loaded_count;
                $term_offset = max(0, $offset - $query->found_posts);

                $term_args = [
                    'taxonomy' => $taxonomies,
                    'hide_empty' => false,
                    'number' => $remaining,
                    'offset' => $term_offset,
                ];

                if ($is_multi_lang) {
                    $term_args['lang'] = '';
                    $term_args['suppress_filters'] = false;
                }

                if (!empty($search)) {
                    $term_args['search'] = $search;
                }

                $terms = get_terms($term_args);

                if (!is_wp_error($terms) && !empty($terms)) {
                    foreach ($terms as $term) {
                        $term_link = get_term_link($term->term_id);
                        $term_name = $term->name;

                        if (!empty($search) && stripos($term_name, $search) === false && stripos($term_link, $search) === false) {
                            continue;
                        }

                        $data[] = [
                            'id' => $term->term_id,
                            'text' => "{$term_name} ({$term_link})",
                            'url' => $term_link
                        ];
                    }
                }
            }
        }

        if ($with_total) {
            $total = $query->found_posts;
            $pages = $limit > 0 ? (int)ceil($total / $limit) : 1;

            return [
                'total' => $total,
                'pages' => $pages,
                'data' => $data
            ];
        }

        if ($return) {
            return $data;
        }

        wp_send_json($data);
    }
}
