<?php

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

class Niwa_AI_Site_Knowledge_Extractor {
    const MAX_THEME_MOD_LENGTH = 2000;
    const MIN_WIDGET_TEXT_LENGTH = 10;
    const MAX_SECTION_CHARS = 20000;

    public function extract_full_site_content() {
        $sections = array();

        $sections[] = $this->extract_site_basics();
        $sections[] = $this->extract_theme_mods();
        $sections[] = $this->extract_acf_options();
        $sections[] = $this->extract_menus();
        $sections[] = $this->extract_widgets();
        $sections[] = $this->extract_text_options();
        $sections[] = $this->extract_agent_profile();
		$frontend_snapshot = $this->extract_frontend_snapshot();
		$sections[] = $frontend_snapshot ?: $this->extract_home_page();

        $key_pages = $this->extract_key_pages_snapshots();
        if ( ! empty( $key_pages ) && is_array( $key_pages ) ) {
            foreach ( $key_pages as $page_section ) {
                $sections[] = $page_section;
            }
        }

        $sections = array_filter(
            $sections,
            function ( $section ) {
                return is_array( $section ) && ! empty( $section['text'] );
            }
        );

		return $this->dedupe_sections( array_values( $sections ) );
    }

	private function dedupe_sections( $sections ) {
		$unique = array();
		$seen   = array();
		foreach ( (array) $sections as $section ) {
			if ( ! is_array( $section ) || empty( $section['text'] ) ) {
				continue;
			}
			$key = hash( 'sha256', preg_replace( '/\s+/u', ' ', trim( (string) $section['text'] ) ) );
			if ( isset( $seen[ $key ] ) ) {
				continue;
			}
			$seen[ $key ] = true;
			$unique[]     = $section;
		}
		return $unique;
	}

    private function extract_site_basics() {
        $site_name = get_bloginfo( 'name' );
        $site_desc = get_bloginfo( 'description' );
        $home      = home_url( '/' );

        $text = "Site: {$site_name} - {$home}";
        if ( $site_desc ) {
            $text .= "\nTagline: {$site_desc}";
        }

        return array(
            'title'       => 'Site Information',
            'text'        => $this->clip_text( $text ),
            'url'         => $home,
            'source_type' => 'site_basics',
        );
    }

    private function extract_theme_mods() {
        $mods = get_theme_mods();

        if ( ! is_array( $mods ) || empty( $mods ) ) {
            return null;
        }

        $lines = array();
        foreach ( $mods as $key => $value ) {
            if ( is_string( $value ) ) {
                $value = $this->sanitize_text( $value );
                if ( $value !== '' && strlen( $value ) <= self::MAX_THEME_MOD_LENGTH ) {
                    $lines[] = $key . ': ' . $value;
                }
            }
        }

        if ( empty( $lines ) ) {
            return null;
        }

        return array(
            'title'       => 'Theme Settings',
            'text'        => $this->clip_text( "Theme mods:\n" . implode( "\n", $lines ) ),
            'url'         => home_url( '/' ),
            'source_type' => 'theme_mods',
        );
    }

    private function extract_acf_options() {
        if ( ! function_exists( 'get_fields' ) ) {
            return null;
        }

        $acf = get_fields( 'option' );
        if ( ! is_array( $acf ) || empty( $acf ) ) {
            return null;
        }

        $lines = array();
        foreach ( $acf as $key => $value ) {
            if ( is_string( $value ) ) {
                $value = $this->sanitize_text( $value );
                if ( $value !== '' ) {
                    $lines[] = $key . ': ' . $value;
                }
            }
        }

        if ( empty( $lines ) ) {
            return null;
        }

        return array(
            'title'       => 'Site Options (ACF)',
            'text'        => $this->clip_text( "ACF Options:\n" . implode( "\n", $lines ) ),
            'url'         => home_url( '/' ),
            'source_type' => 'acf_options',
        );
    }

    private function extract_menus() {
        $menus = wp_get_nav_menus();

        if ( ! is_array( $menus ) || empty( $menus ) ) {
            return null;
        }

        $parts = array();
        foreach ( $menus as $menu ) {
            $items = wp_get_nav_menu_items( $menu->term_id );
            if ( ! $items ) {
                continue;
            }
            $lines = array();
            foreach ( $items as $item ) {
                $title = trim( (string) $item->title );
                $url   = trim( (string) $item->url );
                if ( '' !== $title ) {
                    $lines[] = $url ? ( $title . ' - ' . $url ) : $title;
                }
            }
            if ( ! empty( $lines ) ) {
                $parts[] = 'Menu: ' . $menu->name . "\n" . implode( "\n", $lines );
            }
        }

        if ( empty( $parts ) ) {
            return null;
        }

        return array(
            'title'       => 'Navigation Menus',
            'text'        => $this->clip_text( implode( "\n\n", $parts ) ),
            'url'         => home_url( '/' ),
            'source_type' => 'menus',
        );
    }

    private function extract_widgets() {
        $all_options = wp_load_alloptions();
        $widget_texts = array();

        foreach ( $all_options as $option_name => $option_value ) {
            if ( strpos( $option_name, 'widget_text' ) !== 0
                && strpos( $option_name, 'widget_custom_html' ) !== 0
                && strpos( $option_name, 'widget_block' ) !== 0 ) {
                continue;
            }

            $widgets = maybe_unserialize( $option_value );
            if ( ! is_array( $widgets ) ) {
                continue;
            }

            foreach ( $widgets as $widget_instance ) {
                if ( ! is_array( $widget_instance ) ) {
                    continue;
                }
                $text = '';
                if ( ! empty( $widget_instance['text'] ) ) {
                    $text = $widget_instance['text'];
                } elseif ( ! empty( $widget_instance['content'] ) ) {
                    $text = $widget_instance['content'];
                }
                $text = $this->sanitize_text( $text );
                if ( $text !== '' && strlen( $text ) > self::MIN_WIDGET_TEXT_LENGTH ) {
                    $widget_texts[] = $text;
                }
            }
        }

        if ( empty( $widget_texts ) ) {
            return null;
        }

        return array(
            'title'       => 'Widgets',
            'text'        => $this->clip_text( "Widgets:\n" . implode( "\n---\n", $widget_texts ) ),
            'url'         => home_url( '/' ),
            'source_type' => 'widgets',
        );
    }

    private function extract_home_page() {
        $site_name    = get_bloginfo( 'name' );
        $site_desc    = get_bloginfo( 'description' );
        $home_url     = home_url( '/' );
        $home_page_id = get_option( 'page_on_front' );
        $content      = '';
        $title        = $site_name . ' - Home';

        if ( $home_page_id && intval( $home_page_id ) !== 0 ) {
            $home_page = get_post( $home_page_id );
            if ( $home_page && $home_page->post_status === 'publish' ) {
                $raw = (string) $home_page->post_content;
                $rendered = apply_filters( 'the_content', $raw );
                $content = $this->sanitize_text( $rendered );
                $title = get_the_title( $home_page_id );
            }
        }

        if ( empty( $content ) ) {
            $content = $site_desc;
            $recent_posts = get_posts(
                array(
                    'numberposts' => 5,
                    'post_status' => 'publish',
                    'fields'      => 'ids',
                )
            );
            if ( $recent_posts ) {
                $titles = array();
                foreach ( $recent_posts as $post_id ) {
                    $titles[] = get_the_title( $post_id );
                }
                $content .= "\nRecent content: " . implode( ', ', $titles );
            }
        }

        if ( empty( trim( $content ) ) ) {
            $content = 'Welcome to ' . $site_name;
        }

        $header = $title . ' - ' . $home_url;

        return array(
            'title'       => 'Home Page: ' . $title,
            'text'        => $this->clip_text( $header . "\n" . $content ),
            'url'         => $home_url,
            'source_type' => 'home_page',
        );
    }

    private function extract_frontend_snapshot() {
        $home_url = home_url( '/' );
        $resp = wp_remote_get(
            $home_url,
            array(
                'timeout' => 10,
                'headers' => array(
                    'User-Agent' => 'NiwaAI-Indexer/1.0',
                ),
            )
        );

        if ( is_wp_error( $resp ) ) {
            return null;
        }

        $code = wp_remote_retrieve_response_code( $resp );
        if ( $code < 200 || $code >= 300 ) {
            return null;
        }

        $html = (string) wp_remote_retrieve_body( $resp );
        if ( '' === trim( $html ) ) {
            return null;
        }

        $json_text = $this->extract_json_ld_text( $html );
        $text = $this->html_to_text( $html );

        if ( '' !== $json_text ) {
            $text .= "\nJSON-LD:\n" . $json_text;
        }
        $text = $this->clip_text( $text );
        if ( mb_strlen( $text ) < 40 ) {
            return null;
        }

        return array(
            'title'       => 'Frontend Snapshot',
            'text'        => $text,
            'url'         => $home_url,
            'source_type' => 'frontend_snapshot',
        );
    }

    private function extract_text_options() {
        $all_options = wp_load_alloptions();
        if ( ! is_array( $all_options ) || empty( $all_options ) ) {
            return null;
        }

        $hard_skip_patterns = array(
            '/^_transient_/i',
            '/^_site_transient_/i',
            '/^cron$/i',
            '/^rewrite_rules$/i',
            '/^recently_edited$/i',
        );

        $weighted_entries = array();
        foreach ( $all_options as $option_name => $option_value ) {
            $option_name = (string) $option_name;
            if ( '' === $option_name ) {
                continue;
            }

            $skip = false;
            foreach ( $hard_skip_patterns as $pattern ) {
                if ( preg_match( $pattern, $option_name ) ) {
                    $skip = true;
                    break;
                }
            }
            if ( $skip ) {
                continue;
            }

            $decoded = maybe_unserialize( $option_value );
            $strings = array();
            $this->collect_string_values( $decoded, $strings );
            if ( empty( $strings ) ) {
                continue;
            }

            $strings = array_values(
                array_filter(
                    array_unique( $strings ),
                    function( $text ) {
                        return $this->should_keep_text_snippet( $text );
                    }
                )
            );
            if ( empty( $strings ) ) {
                continue;
            }

            $line = $option_name . ': ' . $this->clip_text( implode( ' | ', array_slice( $strings, 0, 4 ) ), 1200 );
            $weighted_entries[] = array(
                'score' => $this->score_option_candidate( $option_name, $strings ),
                'line'  => $line,
            );
        }

        if ( empty( $weighted_entries ) ) {
            return null;
        }

        usort(
            $weighted_entries,
            function( $a, $b ) {
                $score_a = isset( $a['score'] ) ? floatval( $a['score'] ) : 0.0;
                $score_b = isset( $b['score'] ) ? floatval( $b['score'] ) : 0.0;
                if ( $score_a === $score_b ) {
                    return 0;
                }
                return ( $score_a > $score_b ) ? -1 : 1;
            }
        );

        $lines = array();
        foreach ( $weighted_entries as $entry ) {
            if ( count( $lines ) >= 120 ) {
                break;
            }
            if ( empty( $entry['line'] ) ) {
                continue;
            }
            $lines[] = (string) $entry['line'];
        }

        if ( empty( $lines ) ) {
            return null;
        }

        return array(
            'title'       => 'Theme/Options Text',
            'text'        => $this->clip_text( "Options text:\n" . implode( "\n", $lines ) ),
            'url'         => home_url( '/' ),
            'source_type' => 'options_text',
        );
    }

    private function extract_agent_profile() {
        $candidates = array( Niwa_AI_Constants::OPT_AGENT_PROFILE, Niwa_AI_Constants::LEGACY_OPT_AGENT_PROFILE );
        $profile = array();
        foreach ( $candidates as $key ) {
            $value = get_option( $key, array() );
            if ( is_array( $value ) && ! empty( $value ) ) {
                $profile = $value;
                break;
            }
        }

        if ( empty( $profile ) ) {
            return null;
        }

        $lines = array();
        foreach ( $profile as $key => $value ) {
            if ( ! is_string( $value ) ) {
                continue;
            }
            $text = $this->sanitize_text( $value );
            if ( ! $this->should_keep_text_snippet( $text ) ) {
                continue;
            }
            $lines[] = (string) $key . ': ' . $text;
        }

        if ( empty( $lines ) ) {
            return null;
        }

        return array(
            'title'       => 'Agent Profile',
            'text'        => $this->clip_text( "Agent profile:\n" . implode( "\n", $lines ) ),
            'url'         => home_url( '/' ),
            'source_type' => 'agent_profile',
        );
    }

    private function html_to_text( $html ) {
        $html = preg_replace( '/<script\b[^>]*>.*?<\/script>/is', ' ', $html );
        $html = preg_replace( '/<style\b[^>]*>.*?<\/style>/is', ' ', $html );
        $html = preg_replace( '/<noscript\b[^>]*>.*?<\/noscript>/is', ' ', $html );
        $text = wp_strip_all_tags( $html );
        $text = html_entity_decode( $text, ENT_QUOTES | ENT_HTML5 );
        $text = preg_replace( '/\s{2,}/', ' ', $text );
        return trim( $text );
    }

    private function extract_json_ld_text( $html ) {
        $out = array();
        if ( preg_match_all( '/<script[^>]+type=["\']application\/ld\+json["\'][^>]*>(.*?)<\/script>/is', $html, $m ) ) {
            foreach ( $m[1] as $json ) {
                $decoded = json_decode( $json, true );
                if ( ! is_array( $decoded ) ) {
                    continue;
                }
                $strings = array();
                $this->collect_string_values( $decoded, $strings );
                if ( ! empty( $strings ) ) {
                    $out[] = implode( ' | ', array_unique( $strings ) );
                }
            }
        }
        if ( empty( $out ) ) {
            return '';
        }
        $text = implode( "\n", $out );
        return $this->clip_text( $text, 2000 );
    }

    private function collect_string_values( $value, &$out ) {
        if ( is_string( $value ) ) {
            $value = $this->sanitize_text( $value );
            if ( $value !== '' ) {
                $out[] = $value;
            }
            return;
        }
        if ( is_numeric( $value ) ) {
            return;
        }
        if ( is_array( $value ) ) {
            foreach ( $value as $item ) {
                $this->collect_string_values( $item, $out );
            }
            return;
        }
        if ( is_object( $value ) ) {
            $this->collect_string_values( (array) $value, $out );
        }
    }

    private function sanitize_text( $text ) {
        $text = is_string( $text ) ? $text : ( is_numeric( $text ) ? (string) $text : '' );
        if ( '' === $text ) {
            return '';
        }
        $text = preg_replace( '/<script\\b[^>]*>(.*?)<\\/script>/is', ' ', $text );
        $text = preg_replace( '/<style\\b[^>]*>(.*?)<\\/style>/is', ' ', $text );
        if ( function_exists( 'strip_shortcodes' ) ) {
            $text = strip_shortcodes( $text );
        }
        $text = wp_strip_all_tags( $text );
        $text = html_entity_decode( $text, ENT_QUOTES | ENT_HTML5 );
        $text = preg_replace( '/\\s{2,}/', ' ', $text );
        return trim( (string) $text );
    }

    private function should_keep_text_snippet( $text ) {
        $text = trim( (string) $text );
        if ( mb_strlen( $text ) < 20 ) {
            return false;
        }
        if ( ! preg_match( '/\p{L}/u', $text ) ) {
            return false;
        }
        $bad_patterns = array(
            '/<\\?php/iu',
            '/\\bfunction\\s*\\(/iu',
            '/\\bvar\\s+[a-z_]/iu',
            '/\\bconst\\s+[a-z_]/iu',
            '/\\.css\\b|\\.js\\b/iu',
        );
        foreach ( $bad_patterns as $pattern ) {
            if ( preg_match( $pattern, $text ) ) {
                return false;
            }
        }
        return true;
    }

    /**
     * Score option candidates by likely usefulness for conversational site memory.
     * Lower score means noisier but still eligible (down-ranked instead of hard dropped).
     *
     * @param string $option_name Option key.
     * @param array  $strings     Extracted string values.
     * @return float
     */
    private function score_option_candidate( $option_name, $strings ) {
        $name  = strtolower( (string) $option_name );
        $score = 1.0;

        $positive_name_patterns = array(
            '/(theme|header|footer|template|elementor|builder|wp_template|wp_block|menu|navigation|widget|custom_html)/i' => 2.2,
            '/(about|contact|delivery|shipping|payment|return|garancija|politika|faq|radno|platinum|club|membership)/i'   => 1.8,
            '/(niwa|agent|assistant|chat|greeting)/i'                                                                       => 1.0,
        );
        $negative_name_patterns = array(
            '/(session|cache|heartbeat|cron|timeout|lock|nonce|token|license|update|debug|log)/i' => -2.0,
            '/^woocommerce_sessions/i'                                                              => -3.0,
            '/^widget_recent/i'                                                                      => -1.2,
        );

        foreach ( $positive_name_patterns as $pattern => $weight ) {
            if ( preg_match( $pattern, $name ) ) {
                $score += $weight;
            }
        }
        foreach ( $negative_name_patterns as $pattern => $weight ) {
            if ( preg_match( $pattern, $name ) ) {
                $score += $weight;
            }
        }

        $max_snippet_len = 0;
        $signal_hits     = 0;
        foreach ( $strings as $text ) {
            $snippet = strtolower( (string) $text );
            $max_snippet_len = max( $max_snippet_len, mb_strlen( $snippet ) );
            if ( preg_match( '/(kontakt|contact|o nama|about|dostava|shipping|placanje|payment|return|povrat|policy|faq|club|membership|newsletter)/i', $snippet ) ) {
                $signal_hits++;
            }
        }

        if ( $signal_hits > 0 ) {
            $score += min( 2.0, 0.5 * $signal_hits );
        }
        if ( $max_snippet_len > 1200 ) {
            $score -= 0.7;
        } elseif ( $max_snippet_len > 700 ) {
            $score -= 0.3;
        }

        return $score;
    }

    private function extract_key_pages_snapshots() {
        $urls = $this->collect_key_page_urls();
        if ( empty( $urls ) ) {
            return array();
        }

        $home_url = trailingslashit( home_url( '/' ) );
        $sections = array();
        $count    = 0;

        foreach ( $urls as $entry ) {
            if ( $count >= 10 ) {
                break;
            }

            $url   = isset( $entry['url'] ) ? (string) $entry['url'] : '';
            $title = isset( $entry['title'] ) ? (string) $entry['title'] : '';

            if ( '' === $url ) {
                continue;
            }

            // Skip homepage – already covered by extract_frontend_snapshot().
            if ( trailingslashit( $url ) === $home_url || untrailingslashit( $url ) === untrailingslashit( home_url() ) ) {
                continue;
            }

            $resp = wp_remote_get(
                $url,
                array(
                    'timeout' => 8,
                    'headers' => array(
                        'User-Agent' => 'NiwaAI-Indexer/1.0',
                    ),
                )
            );

            if ( is_wp_error( $resp ) ) {
                continue;
            }

            $code = wp_remote_retrieve_response_code( $resp );
            if ( $code < 200 || $code >= 300 ) {
                continue;
            }

            $html = (string) wp_remote_retrieve_body( $resp );
            if ( '' === trim( $html ) ) {
                continue;
            }

            $text = $this->html_to_text( $html );
            if ( mb_strlen( $text ) < 40 ) {
                continue;
            }

            $text = $this->clip_text( $text, 3000 );

            if ( '' === $title ) {
                $title = $this->extract_title_from_html( $html );
            }

            $sections[] = array(
                'title'       => 'Key Page: ' . $title,
                'text'        => 'Page: ' . $title . ' (' . $url . ")\n" . $text,
                'url'         => $url,
                'source_type' => 'key_pages',
            );

            $count++;
        }

        return $sections;
    }

    private function collect_key_page_urls() {
        $menus = wp_get_nav_menus();
        if ( ! is_array( $menus ) || empty( $menus ) ) {
            return array();
        }

        $home_host = wp_parse_url( home_url(), PHP_URL_HOST );
        $urls      = array();
        $seen      = array();

        foreach ( $menus as $menu ) {
            $items = wp_get_nav_menu_items( $menu->term_id );
            if ( ! $items ) {
                continue;
            }

            foreach ( $items as $item ) {
                $url   = trim( (string) $item->url );
                $title = trim( (string) $item->title );

                if ( '' === $url || '#' === $url ) {
                    continue;
                }

                // Only internal links.
                $parsed_host = wp_parse_url( $url, PHP_URL_HOST );
                if ( $parsed_host && $parsed_host !== $home_host ) {
                    continue;
                }

                $normalized = trailingslashit( strtolower( $url ) );
                if ( isset( $seen[ $normalized ] ) ) {
                    continue;
                }
                $seen[ $normalized ] = true;

                $urls[] = array(
                    'url'   => $url,
                    'title' => $title,
                );
            }
        }

        return $urls;
    }

    private function extract_title_from_html( $html ) {
        if ( preg_match( '/<title[^>]*>(.*?)<\/title>/is', $html, $m ) ) {
            $title = trim( wp_strip_all_tags( $m[1] ) );
            if ( '' !== $title ) {
                return $title;
            }
        }
        return 'Untitled Page';
    }

    private function clip_text( $text, $limit = null ) {
        $limit = $limit ? intval( $limit ) : self::MAX_SECTION_CHARS;
        $text = trim( (string) $text );
        if ( mb_strlen( $text ) <= $limit ) {
            return $text;
        }
        return rtrim( mb_substr( $text, 0, max( 0, $limit - 3 ) ) ) . '...';
    }
}
