<?php

namespace Datalumo\Search;

use Datalumo\PhpSdk\Exceptions\DatalumoException;
use WP_Query;

class SearchInterceptor
{
    private bool $summarisable = false;

    public function __construct()
    {
        add_filter('posts_pre_query', [$this, 'interceptSearch'], 10, 2);
        add_action('wp_enqueue_scripts', [$this, 'enqueueAssets']);
        add_action('wp_footer', [$this, 'enqueueSummaryAssets']);
        add_action('wp_ajax_datalumo_summarise', [$this, 'handleSummarise']);
        add_action('wp_ajax_nopriv_datalumo_summarise', [$this, 'handleSummarise']);
    }

    /**
     * @param \WP_Post[]|null $posts
     * @return \WP_Post[]|null
     */
    public function interceptSearch(?array $posts, WP_Query $query): ?array
    {
        if (! $this->shouldIntercept($query)) {
            return $posts;
        }

        $searchTerm = $query->get('s');

        if (empty($searchTerm)) {
            return $posts;
        }

        $integrationId = $query->get('datalumo_integration') ?: datalumo_get_search_integration_id();

        if (empty($integrationId)) {
            return $posts;
        }

        $sort = $this->buildSort($query);

        if ($sort === null) {
            // Orderby is set but not mappable to a Datalumo sort field.
            // Let native WordPress search handle this query.
            return $posts;
        }

        $page = max(1, (int) $query->get('paged', 1));
        $perPage = (int) get_option('posts_per_page', 10);
        $postType = $query->get('post_type');

        $payload = [
            'query'    => $searchTerm,
            'page'     => $page,
            'per_page' => $perPage,
        ];

        if($postType !== 'any') {
            $payload['meta']['post_type'] = $postType;
        }

        if (! empty($sort)) {
            $payload['sort'] = $sort;
        }

        try {
            $sdk = datalumo_sdk();
            $result = $sdk->integrations()->search($integrationId, $payload);
        } catch (DatalumoException $e) {
            return null;
        }

        $this->summarisable = ! empty($result->summarisable);
        $query->datalumo_summarisable = $this->summarisable;

        if (empty($result->data)) {
            $query->found_posts = 0;
            $query->max_num_pages = 0;

            return [];
        }

        $sourceIds = array_filter(array_map(function ($entry) {
            return $entry->sourceId ? (int) $entry->sourceId : null;
        }, $result->data));

        if (empty($sourceIds)) {
            $query->found_posts = 0;
            $query->max_num_pages = 0;

            return [];
        }

        $localPosts = get_posts([
            'post__in'       => $sourceIds,
            'orderby'        => 'post__in',
            'post_type'      => 'any',
            'post_status'    => 'publish',
            'posts_per_page' => count($sourceIds),
        ]);

        $query->found_posts = $result->total;
        $query->max_num_pages = $result->lastPage;

        return $localPosts;
    }

    private function shouldIntercept(WP_Query $query): bool
    {
        if (is_admin()) {
            return false;
        }

        $isDatalumoQuery = (bool) $query->get('datalumo');

        if (! $isDatalumoQuery && (! $query->is_search() || ! $query->is_main_query())) {
            return false;
        }

        if (! datalumo_is_configured() || ! datalumo_is_search_enhanced() || empty(datalumo_get_search_integration_id())) {
            return false;
        }

        if (! $isDatalumoQuery) {
            $allowedPostTypes = datalumo_get_search_post_types();

            if (! empty($allowedPostTypes)) {
                $queryPostType = $query->get('post_type');

                if (empty($queryPostType) || $queryPostType === 'any') {
                    $queryPostType = get_post_types(['public' => true, 'exclude_from_search' => false]);
                } elseif (! is_array($queryPostType)) {
                    $queryPostType = [$queryPostType];
                }

                if (! array_intersect($queryPostType, $allowedPostTypes)) {
                    return false;
                }
            }
        }

        return true;
    }

    public function enqueueAssets(): void
    {
        if (! is_search() || ! datalumo_is_configured() || ! datalumo_is_search_enhanced()) {
            return;
        }

        $baseUrl = datalumo_get_base_url();
        $searchIntegrationId = datalumo_get_search_integration_id();

        // Enqueue the SDK for click tracking if a search integration is configured
        if ($searchIntegrationId) {
            wp_enqueue_script(
                'datalumo-sdk',
                $baseUrl . '/embed/datalumo.js',
                [],
                null,
                ['strategy' => 'defer', 'in_footer' => true]
            );

            wp_add_inline_script('datalumo-sdk', sprintf(
                'document.addEventListener("DOMContentLoaded",function(){Datalumo.trackClicks("%s",{container:".wp-block-query, main, #content, .site-content",baseUrl:"%s"})});',
                esc_js($searchIntegrationId),
                esc_url($baseUrl)
            ));
        }

        if (! datalumo_is_search_summary_enabled() || ! $this->summarisable) {
            return;
        }

        wp_enqueue_style('datalumo-search-summary', plugins_url('resources/css/search-summary.css', DATALUMO_FILE), [], DATALUMO_VERSION);
    }

    public function enqueueSummaryAssets(): void
    {
        if (! is_search() || ! $this->summarisable || ! datalumo_is_search_summary_enabled()) {
            return;
        }

        wp_enqueue_script('datalumo-search-summary', plugins_url('resources/js/search-summary.js', DATALUMO_FILE), [], DATALUMO_VERSION, true);
        wp_localize_script('datalumo-search-summary', 'datalumoSearch', [
            'ajaxUrl'          => admin_url('admin-ajax.php'),
            'nonce'            => wp_create_nonce('datalumo_summarise'),
            'query'            => get_search_query(),
            'loadingText'      => __('Generating AI summary...', 'datalumo'),
            'headingText'      => __('AI Summary', 'datalumo'),
            'showMoreText'     => __('Show more', 'datalumo'),
            'showLessText'     => __('Show less', 'datalumo'),
            'summarySelector'  => datalumo_get_search_summary_selector(),
            'summaryPosition'  => datalumo_get_search_summary_position(),
        ]);
    }

    /**
     * Translate the query's orderby/order into a Datalumo sort spec.
     *
     * @return array<int, array{field: string, type: string, direction: string}>|null
     *   - []    No sort — Datalumo's semantic relevance ranking is used.
     *   - [...] Sort spec to send with the search payload.
     *   - null  Orderby is set but unmappable — caller should bail to native WP.
     */
    private function buildSort(WP_Query $query): ?array
    {
        $orderby = (string) $query->get('orderby');

        // Themes often force orderby=date on search via pre_get_posts, which
        // overrides semantic relevance. Only honor a non-relevance orderby on
        // search queries when it was explicitly requested in the URL.
        if ($query->is_search() && ! isset($_GET['orderby'])) {
            return [];
        }

        $relevanceValues = apply_filters('datalumo_relevance_orderby_values', ['', 'relevance'], $query);

        if (in_array($orderby, $relevanceValues, true)) {
            return [];
        }

        $order = strtolower((string) ($query->get('order') ?: 'desc'));
        $direction = $order === 'asc' ? 'asc' : 'desc';

        $sort = $this->defaultOrderbyMap($orderby, $direction, $query);
        $sort = apply_filters('datalumo_map_orderby_to_sort', $sort, $orderby, $direction, $query);

        if (is_array($sort) && ! empty($sort)) {
            return $sort;
        }

        return null;
    }

    /**
     * @return array<int, array{field: string, type: string, direction: string}>|null
     */
    private function defaultOrderbyMap(string $orderby, string $direction, WP_Query $query): ?array
    {
        switch ($orderby) {
            case 'date':
            case 'post_date':
                return [['field' => 'published_at', 'type' => 'date', 'direction' => $direction]];

            case 'modified':
            case 'post_modified':
                return [['field' => 'modified_at', 'type' => 'date', 'direction' => $direction]];

            case 'title':
            case 'post_title':
                return [['field' => 'title', 'type' => 'text', 'direction' => $direction]];

            case 'meta_value':
                $metaKey = (string) $query->get('meta_key');
                return $metaKey !== ''
                    ? [['field' => $metaKey, 'type' => 'text', 'direction' => $direction]]
                    : null;

            case 'meta_value_num':
                $metaKey = (string) $query->get('meta_key');
                return $metaKey !== ''
                    ? [['field' => $metaKey, 'type' => 'number', 'direction' => $direction]]
                    : null;
        }

        return null;
    }

    public function handleSummarise(): void
    {
        if (! check_ajax_referer('datalumo_summarise', 'nonce', false)) {
            wp_send_json_error(['message' => __('Invalid security token.', 'datalumo')], 403);
        }

        if (! datalumo_is_configured() || ! datalumo_is_search_enhanced() || ! datalumo_is_search_summary_enabled()) {
            wp_send_json_error(['message' => __('Search summary is not enabled.', 'datalumo')], 400);
        }

        $query = sanitize_text_field(wp_unslash($_GET['query'] ?? ''));

        if (empty($query)) {
            wp_send_json_error(['message' => __('No search query provided.', 'datalumo')], 400);
        }

        $integrationId = sanitize_text_field(wp_unslash($_GET['integration_id'] ?? '')) ?: datalumo_get_search_integration_id();

        if (empty($integrationId)) {
            wp_send_json_error(['message' => __('No search integration configured.', 'datalumo')], 400);
        }

        $locale = sanitize_text_field(wp_unslash($_GET['locale'] ?? '')) ?: substr(get_locale(), 0, 2);

        try {
            $sdk = datalumo_sdk();
            $response = $sdk->integrations()->summarise($integrationId, [
                'query'  => $query,
                'format' => 'html',
                'locale' => $locale,
            ]);
        } catch (DatalumoException $e) {
            wp_send_json_error(['message' => $e->getMessage()], 500);
        }

        wp_send_json_success([
            'summary'              => wp_kses_post($response->summary),
            'references'           => $response->references,
            'has_relevant_results' => $response->hasRelevantResults ?? true,
        ]);
    }
}
