<?php
/**
 * Content Indexer - Crawls site content and stores in chunks
 *
 * @package ContentReply_AI
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

class WPSC_Indexer {

    /**
     * Maximum characters per chunk
     */
    private $chunk_size = 1500;

    /**
     * Index all published content
     */
    public function index_all_content() {
        global $wpdb;

        // Get configured post types
        $post_types = get_option( 'wpsc_post_types', array( 'page', 'post' ) );

        if ( empty( $post_types ) ) {
            return;
        }

        // Clear existing index
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared
        $wpdb->query( "TRUNCATE TABLE `" . $wpdb->prefix . "wpsc_content_chunks`" );

        // Get excluded pages
        $excluded = get_option( 'wpsc_excluded_pages', array() );

        // Query all published posts
        $args = array(
            'post_type'      => $post_types,
            'post_status'    => 'publish',
            'posts_per_page' => -1,
            'post__not_in'   => ! empty( $excluded ) ? $excluded : array( 0 ),
        );

        $posts = get_posts( $args );

        foreach ( $posts as $post ) {
            $this->index_post( $post );
        }

        // Update last indexed timestamp
        update_option( 'wpsc_last_indexed', current_time( 'mysql' ) );
    }

    /**
     * Index a single post into chunks
     */
    public function index_post( $post ) {
        global $wpdb;

        // Get clean text content
        $content = $this->clean_content( $post->post_content );
        $title = sanitize_text_field( $post->post_title );
        $url = get_permalink( $post->ID );
        $post_type = $post->post_type;

        // Prepend title to content for context
        $full_content = "Title: {$title}\n\n{$content}";

        // Split into chunks
        $chunks = $this->split_into_chunks( $full_content );

        foreach ( $chunks as $index => $chunk ) {
            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
            $wpdb->insert(
                $wpdb->prefix . 'wpsc_content_chunks',
                array(
                    'post_id'       => $post->ID,
                    'post_title'    => $title,
                    'post_url'      => esc_url( $url ),
                    'post_type'     => sanitize_key( $post_type ),
                    'chunk_content' => sanitize_textarea_field( $chunk ),
                    'chunk_index'   => (int) $index,
                    'indexed_at'    => current_time( 'mysql' ),
                ),
                array( '%d', '%s', '%s', '%s', '%s', '%d', '%s' )
            );
        }
    }

    /**
     * Clean HTML content to plain text
     */
    private function clean_content( $content ) {
        // Remove shortcodes
        $content = strip_shortcodes( $content );

        // Remove HTML tags
        $content = wp_strip_all_tags( $content );

        // Remove extra whitespace
        $content = preg_replace( '/\s+/', ' ', $content );

        // Trim
        $content = trim( $content );

        return $content;
    }

    /**
     * Split content into manageable chunks
     */
    private function split_into_chunks( $content ) {
        $chunks = array();
        $sentences = preg_split( '/(?<=[.!?])\s+/', $content );
        $current_chunk = '';

        foreach ( $sentences as $sentence ) {
            if ( strlen( $current_chunk . ' ' . $sentence ) > $this->chunk_size ) {
                if ( ! empty( $current_chunk ) ) {
                    $chunks[] = trim( $current_chunk );
                }
                $current_chunk = $sentence;
            } else {
                $current_chunk .= ' ' . $sentence;
            }
        }

        // Add remaining content
        if ( ! empty( trim( $current_chunk ) ) ) {
            $chunks[] = trim( $current_chunk );
        }

        return $chunks;
    }

    /**
     * Search indexed content for relevant chunks
     *
     * @param string $query Search query.
     * @param int    $limit Maximum results to return.
     * @return array Array of matching content chunks.
     */
    public function search_relevant_content( $query, $limit = 5 ) {
        global $wpdb;

        $cache_key = 'wpsc_search_' . md5( $query . $limit );
        $results = wp_cache_get( $cache_key, 'wpsc' );

        if ( false === $results ) {
            // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery
            // phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
            $results = $wpdb->get_results(
                $wpdb->prepare(
                    "SELECT post_title, post_url, chunk_content, MATCH(chunk_content) AGAINST(%s IN NATURAL LANGUAGE MODE) AS relevance FROM `" . $wpdb->prefix . "wpsc_content_chunks` WHERE MATCH(chunk_content) AGAINST(%s IN NATURAL LANGUAGE MODE) ORDER BY relevance DESC LIMIT %d",
                    $query,
                    $query,
                    $limit
                )
            );
            // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery
            // phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared

            // Fallback to LIKE search if FULLTEXT returns nothing
            if ( empty( $results ) ) {
                $keywords = array_filter( explode( ' ', $query ), function ( $word ) {
                    return strlen( $word ) > 3;
                });

                if ( ! empty( $keywords ) ) {
                    // Limit to max 5 keywords for search
                    $keywords = array_slice( array_values( $keywords ), 0, 5 );
                    $wpsc_like_vals = array();

                    foreach ( $keywords as $keyword ) {
                        $wpsc_like_vals[] = '%' . $wpdb->esc_like( $keyword ) . '%';
                    }

                    $wpsc_keyword_count = count( $wpsc_like_vals );

                    // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared
                    if ( 1 === $wpsc_keyword_count ) {
                        $results = $wpdb->get_results( $wpdb->prepare( "SELECT post_title, post_url, chunk_content FROM `" . $wpdb->prefix . "wpsc_content_chunks` WHERE chunk_content LIKE %s LIMIT %d", $wpsc_like_vals[0], $limit ) );
                    } elseif ( 2 === $wpsc_keyword_count ) {
                        $results = $wpdb->get_results( $wpdb->prepare( "SELECT post_title, post_url, chunk_content FROM `" . $wpdb->prefix . "wpsc_content_chunks` WHERE chunk_content LIKE %s OR chunk_content LIKE %s LIMIT %d", $wpsc_like_vals[0], $wpsc_like_vals[1], $limit ) );
                    } elseif ( 3 === $wpsc_keyword_count ) {
                        $results = $wpdb->get_results( $wpdb->prepare( "SELECT post_title, post_url, chunk_content FROM `" . $wpdb->prefix . "wpsc_content_chunks` WHERE chunk_content LIKE %s OR chunk_content LIKE %s OR chunk_content LIKE %s LIMIT %d", $wpsc_like_vals[0], $wpsc_like_vals[1], $wpsc_like_vals[2], $limit ) );
                    } elseif ( 4 === $wpsc_keyword_count ) {
                        $results = $wpdb->get_results( $wpdb->prepare( "SELECT post_title, post_url, chunk_content FROM `" . $wpdb->prefix . "wpsc_content_chunks` WHERE chunk_content LIKE %s OR chunk_content LIKE %s OR chunk_content LIKE %s OR chunk_content LIKE %s LIMIT %d", $wpsc_like_vals[0], $wpsc_like_vals[1], $wpsc_like_vals[2], $wpsc_like_vals[3], $limit ) );
                    } else {
                        $results = $wpdb->get_results( $wpdb->prepare( "SELECT post_title, post_url, chunk_content FROM `" . $wpdb->prefix . "wpsc_content_chunks` WHERE chunk_content LIKE %s OR chunk_content LIKE %s OR chunk_content LIKE %s OR chunk_content LIKE %s OR chunk_content LIKE %s LIMIT %d", $wpsc_like_vals[0], $wpsc_like_vals[1], $wpsc_like_vals[2], $wpsc_like_vals[3], $wpsc_like_vals[4], $limit ) );
                    }
                    // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQL.NotPrepared
                }
            }

            wp_cache_set( $cache_key, $results, 'wpsc', 300 );
        }

        return $results ? $results : array();
    }

    /**
     * Get total indexed chunks count
     *
     * @return int Number of indexed chunks.
     */
    public function get_index_count() {
        global $wpdb;

        $cache_key = 'wpsc_index_count';
        $count = wp_cache_get( $cache_key, 'wpsc' );

        if ( false === $count ) {
            // phpcs:disable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            $count = (int) $wpdb->get_var( "SELECT COUNT(*) FROM `" . $wpdb->prefix . "wpsc_content_chunks`" );
            // phpcs:enable WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
            wp_cache_set( $cache_key, $count, 'wpsc', 300 );
        }

        return (int) $count;
    }
}
