<?php
defined('ABSPATH') || exit;

/**
 * Resolve /{lang}/{product_base}/{native-slug}/ to the correct product,
 * fully priming the main query so Woo/SEO plugins see a real single product.
 *
 */
/**
 * 🔒 REEID LOCK — NON-WOO PAGE RESOLVER
 *
 * DO NOT TOUCH WITHOUT FULL SEO + WOO AUDIT.
 *
 * Guarantees:
 * - Runs ONLY on real pages/posts (never products)
 * - Never affects WooCommerce routing, canonicals, hreflang
 * - Hard-primes WP_Query to avoid false 404
 *
 * Breaking this WILL:
 * - Reintroduce 404 bodies on translated pages
 * - Leak page logic into Woo products
 */









if ( ! function_exists( 'reeid_native_slug_resolver' ) ) {
	function reeid_native_slug_resolver( $preempt, $wp_query ) {
        // 🔒 HARD STOP: if WP already resolved a product, never interfere
// 🔒 HARD STOP: if WP already resolved a product by ID, never interfere
if (
    isset( $wp_query->query_vars['p'] ) &&
    $wp_query->query_vars['p']
) {
    return $preempt;
}

        // 🔒 HARD STOP: ignore non-frontend HTML requests
$req_uri = filter_input( INPUT_SERVER, 'REQUEST_URI', FILTER_UNSAFE_RAW );
$req_uri = $req_uri ? wp_unslash( $req_uri ) : '';

if (
    is_admin()
    || wp_doing_ajax()
    || wp_is_json_request()
    || strpos($req_uri, '/wp-content/') === 0
    || strpos($req_uri, '/wp-admin/') === 0
    || strpos($req_uri, '/?wc-ajax=') !== false
    || strpos($req_uri, '/favicon') === 0
) {
    return $preempt;
}

	
		if (
    is_admin()
    || wp_doing_ajax()
    || wp_is_json_request()
    || ( function_exists('is_product') && is_product() )
) {
    return $preempt;
}


$req = filter_input( INPUT_SERVER, 'REQUEST_URI', FILTER_UNSAFE_RAW );
$req = (string) ( $req ? wp_unslash( $req ) : '' );

// === HARD STOP: if Woo already resolved a single product, never interfere ===
if (
    function_exists('is_singular') &&
    is_singular('product')
) {
    return false; // allow Woo + SEO plugins to proceed normally
}

		if ( $req === '' ) {
			return $preempt;
		}

		$path = (string) wp_parse_url( $req, PHP_URL_PATH );
		$path = '/' . ltrim( (string) $path, '/' );


		// WooCommerce product base (default 'product')
		$wc   = get_option( 'woocommerce_permalinks', array() );
		$base = ( is_array( $wc ) && ! empty( $wc['product_base'] ) ) ? trim( (string) $wc['product_base'], '/' ) : 'product';

		// Match "/{lang}/product/{slug}/" (lang: xx or xx-YY)
		$re = '#^/([a-z]{2}(?:-[a-z0-9]{2})?)/' . preg_quote( $base, '#' ) . '/([^/]+)/?$#i';

		if ( ! preg_match( $re, $path, $m ) ) {
			return $preempt;
		}

		$lang = strtolower( sanitize_key( $m[1] ) );
		$slug = rawurldecode( (string) $m[2] ); // preserve native chars exactly



		if ( $lang === '' || $slug === '' ) {
			return $preempt;
		}

		global $wpdb;

		$post_id = 0;

		/**
		 * 1) PRIMARY: match Woo inline translation slug stored in serialized array meta:
		 *    _reeid_wc_tr_{lang}['slug'] === requested slug
		 *
		 * We fetch rows for that meta_key and compare in PHP (safe + exact for UTF-8).
		 */
		$tr_key = '_reeid_wc_tr_' . $lang;

        $cache_key = 'reeid_wc_inline_rows_' . $tr_key;
$rows = wp_cache_get( $cache_key, 'reeid' );

if ( false === $rows ) {

    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Required for Woo inline slug lookup
    $rows = $wpdb->get_results(
        $wpdb->prepare(
            "SELECT pm.post_id, pm.meta_value
             FROM {$wpdb->postmeta} pm
             INNER JOIN {$wpdb->posts} p ON p.ID = pm.post_id
             WHERE pm.meta_key = %s
               AND p.post_type = 'product'
               AND p.post_status = 'publish'
             LIMIT 2000",
            $tr_key
        ),
        ARRAY_A
    );

    wp_cache_set( $cache_key, $rows, 'reeid', HOUR_IN_SECONDS );
}

		if ( is_array( $rows ) && ! empty( $rows ) ) {
			foreach ( $rows as $r ) {
				$pid = isset( $r['post_id'] ) ? (int) $r['post_id'] : 0;
				if ( $pid <= 0 ) {
					continue;
				}

				$val = maybe_unserialize( $r['meta_value'] ?? null );
				if ( ! is_array( $val ) ) {
					continue;
				}

				$mslug = isset( $val['slug'] ) ? (string) $val['slug'] : '';
				if ( $mslug !== '' && $mslug === $slug ) {
					$post_id = $pid;
					break;
				}
			}
		}

		/**
		 * 2) FALLBACK: legacy meta style (if present on some installs)
		 *    _rtl_slug_{lang} === requested slug
		 */
		if ( $post_id <= 0 ) {
			$meta_key_legacy = '_rtl_slug_' . $lang;
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Required for legacy inline slug lookup
			$post_id = (int) $wpdb->get_var(
				$wpdb->prepare(
					"SELECT pm.post_id
					 FROM {$wpdb->postmeta} pm
					 INNER JOIN {$wpdb->posts} p ON p.ID = pm.post_id
					 WHERE pm.meta_key = %s AND pm.meta_value = %s
					   AND p.post_type = 'product' AND p.post_status = 'publish'
					 LIMIT 1",
					$meta_key_legacy,
					$slug
				)
			);
		}

		/**
		 * 3) FALLBACK: allow prefixed EN slug routes (/ru/product/{en-slug}/)
		 *    (this keeps older links working, but does NOT change hreflang behavior)
		 */
		if ( $post_id <= 0 ) {
			$po = get_page_by_path( $slug, OBJECT, 'product' );
			if ( $po instanceof WP_Post ) {
				$post_id = (int) $po->ID;
			}
		}
if ( $post_id <= 0 ) {
        return $preempt;
}

		$post = get_post( $post_id );
		if ( ! $post ) {
			return $preempt;
		}
		// === REEID: enforce one preferred inline slug per language (hreflang symmetry) ===
$packet = get_post_meta( $post_id, '_reeid_wc_tr_' . $lang, true );
if ( is_array( $packet ) && ! empty( $packet['slug'] ) ) {
    $preferred = (string) $packet['slug'];

    // If request slug differs, 301 to preferred
    if ( $preferred !== '' && $preferred !== $slug ) {
$target = home_url( '/' . $lang . '/' . $base . '/' . $preferred . '/' );

        // Preserve query string (if any)
$qs = filter_input( INPUT_SERVER, 'QUERY_STRING', FILTER_UNSAFE_RAW );
$qs = (string) ( $qs ? wp_unslash( $qs ) : '' );
        if ( $qs !== '' ) {
            $target .= ( strpos( $target, '?' ) === false ? '?' : '&' ) . $qs;
        }

        wp_safe_redirect( $target, 301 );
        exit;
    }
}


		// Prime main query as a single product
		$wp_query->is_404        = false;
		$wp_query->is_home       = false;
		$wp_query->is_page       = false;
		$wp_query->is_archive    = false;
		$wp_query->is_search     = false;
		$wp_query->is_category   = false;
		$wp_query->is_tag        = false;
		$wp_query->is_tax        = false;
		$wp_query->is_feed       = false;
		$wp_query->is_singular   = true;
		$wp_query->is_single     = true;
		$wp_query->is_attachment = false;

		$vars = array(
			'post_type' => 'product',
			'p'         => $post_id,
			'name'      => (string) $post->post_name,
		);

		$wp_query->query             = $vars;
		$wp_query->query_vars        = $vars;
		$wp_query->posts             = array( $post );
		$wp_query->post_count        = 1;
		$wp_query->post              = $post;
		$wp_query->queried_object    = $post;
		$wp_query->queried_object_id = $post_id;
        // 🔥 HARD PRIME QUERY FLAGS
        $wp_query->is_404        = false;
        $wp_query->is_singular   = true;
        $wp_query->is_single     = true;
        $wp_query->is_page       = false;
        $wp_query->is_archive    = false;
        $wp_query->is_post_type_archive = false;
        $wp_query->is_tax        = false;
        $wp_query->is_search     = false;
        $wp_query->is_home       = false;
        $wp_query->is_front_page = false;


		// Make template tags/plugins happy
		$GLOBALS['post'] = $post;
		setup_postdata( $post );

		status_header( 200 );

		return true;// handled
	}
    
    // Product native slug resolver (already present)
add_action( 'parse_query', function( $wp_query ) {
if ( ( defined('WP_CLI') && WP_CLI ) || ! defined('WP_DEBUG') || ! WP_DEBUG ) { return; }

    if (
        is_admin() ||
        ! $wp_query->is_main_query()
    ) {
        return;
    }

    if (
        isset( $wp_query->query_vars['post_type'], $wp_query->query_vars['name'] ) &&
        $wp_query->query_vars['post_type'] === 'product' &&
        empty( $wp_query->query_vars['p'] )
    ) {
        reeid_native_slug_resolver( false, $wp_query );
    }

}, 10 );


// === REEID: Final resolver for language-prefixed NON-product pages ===
add_filter('pre_handle_404', function ($preempt, $wp_query) {

    if (
    is_admin()
    || wp_doing_ajax()
    || wp_is_json_request()
    || ( function_exists('is_woocommerce') && is_woocommerce() )
    || ( function_exists('is_product') && is_product() )
) {
    return $preempt;
}


$req = filter_input( INPUT_SERVER, 'REQUEST_URI', FILTER_UNSAFE_RAW );
$req = (string) ( $req ? wp_unslash( $req ) : '' );    if ($req === '') return $preempt;

    $path = (string) wp_parse_url($req, PHP_URL_PATH);
    $path = '/' . ltrim($path, '/');

    // Skip virtual language roots (/de/, /zh/)
    if (preg_match('~^/[a-z]{2}(/)?$~i', $path)) {
        return $preempt;
    }

    // Match /{lang}/{slug}
    if (!preg_match('~^/([a-z]{2})(?:/|$)(.+)$~i', $path, $m)) {
        return $preempt;
    }

    $lang = strtolower($m[1]);
    $rest = trim($m[2], '/');

    // Skip Woo products
    $wc   = get_option('woocommerce_permalinks', []);
    $base = (!empty($wc['product_base'])) ? trim($wc['product_base'], '/') : 'product';
    if (preg_match('~^' . preg_quote($base, '~') . '(/|$)~i', $rest)) {
        return $preempt;
    }

    // Try to resolve page by path
    $decoded = implode('/', array_map('rawurldecode', explode('/', $rest)));
    $post = get_page_by_path($decoded, OBJECT, ['page','post']);

    if (!($post instanceof WP_Post)) {
        return $preempt;
    }

    // Check translation language
    $plang = strtolower((string) get_post_meta($post->ID, '_reeid_translation_lang', true));
    if ($plang !== $lang) {
        return $preempt;
    }

    // ✅ HARD PRIME QUERY
    $wp_query->is_404        = false;
    $wp_query->is_home       = false;
    $wp_query->is_page       = false;
    $wp_query->is_single     = false;
    $wp_query->is_singular   = true;
    $wp_query->is_archive    = false;

    if ($post->post_type === 'page') {
        $wp_query->is_page = true;
    } else {
        $wp_query->is_single = true;
    }

    $vars = [
        'p'         => $post->ID,
        'post_type' => $post->post_type,
        'name'      => $post->post_name,
    ];

    $wp_query->query             = $vars;
    $wp_query->query_vars        = $vars;
    $wp_query->posts             = [$post];
    $wp_query->post              = $post;
    $wp_query->post_count        = 1;
    $wp_query->queried_object    = $post;
    $wp_query->queried_object_id = $post->ID;

    $GLOBALS['post'] = $post;
    setup_postdata($post);

    status_header(200);
return true;


}, 10, 2);



}

// === REEID: Early request resolver for language-prefixed Woo inline product slugs ===
add_filter( 'request', function ( $vars ) {
    if ( is_admin() || wp_doing_ajax() || wp_is_json_request() ) {
        return $vars;
    }

    $req = filter_input( INPUT_SERVER, 'REQUEST_URI', FILTER_UNSAFE_RAW );
    $req = (string) ( $req ? wp_unslash( $req ) : '' );
    if ( $req === '' ) {
        return $vars;
    }

    $path = (string) wp_parse_url( $req, PHP_URL_PATH );
    $path = '/' . ltrim( $path, '/' );

    $wc   = get_option( 'woocommerce_permalinks', array() );
    $base = ( is_array( $wc ) && ! empty( $wc['product_base'] ) )
        ? trim( (string) $wc['product_base'], '/' )
        : 'product';

    if ( ! preg_match( '#^/([a-z]{2}(?:-[a-z0-9]{2})?)/' . preg_quote( $base, '#' ) . '/([^/]+)/?$#iu', $path, $m ) ) {
        return $vars;
    }

    $lang = strtolower( sanitize_key( $m[1] ) );
    $slug = rawurldecode( (string) $m[2] );

    if ( $lang === '' || $slug === '' ) {
        return $vars;
    }

    global $wpdb;

    $post_id = 0;
    $tr_key  = '_reeid_wc_tr_' . $lang;

    $cache_key = 'reeid_wc_inline_rows_' . $tr_key;
    $rows      = wp_cache_get( $cache_key, 'reeid' );

    if ( false === $rows ) {
        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Required for Woo inline slug lookup
        $rows = $wpdb->get_results(
            $wpdb->prepare(
                "SELECT pm.post_id, pm.meta_value
                 FROM {$wpdb->postmeta} pm
                 INNER JOIN {$wpdb->posts} p ON p.ID = pm.post_id
                 WHERE pm.meta_key = %s
                   AND p.post_type = 'product'
                   AND p.post_status = 'publish'
                 LIMIT 2000",
                $tr_key
            ),
            ARRAY_A
        );

        wp_cache_set( $cache_key, $rows, 'reeid', HOUR_IN_SECONDS );
    }

    if ( is_array( $rows ) && ! empty( $rows ) ) {
        foreach ( $rows as $r ) {
            $pid = isset( $r['post_id'] ) ? (int) $r['post_id'] : 0;
            if ( $pid <= 0 ) {
                continue;
            }

            $val = maybe_unserialize( $r['meta_value'] ?? null );
            if ( ! is_array( $val ) ) {
                continue;
            }

            $mslug = isset( $val['slug'] ) ? (string) $val['slug'] : '';
            if ( $mslug !== '' && $mslug === $slug ) {
                $post_id = $pid;
                break;
            }
        }
    }

    if ( $post_id <= 0 ) {
        $legacy_key = '_rtl_slug_' . $lang;

        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Required for legacy inline slug lookup
        $post_id = (int) $wpdb->get_var(
            $wpdb->prepare(
                "SELECT pm.post_id
                 FROM {$wpdb->postmeta} pm
                 INNER JOIN {$wpdb->posts} p ON p.ID = pm.post_id
                 WHERE pm.meta_key = %s
                   AND pm.meta_value = %s
                   AND p.post_type = 'product'
                   AND p.post_status = 'publish'
                 LIMIT 1",
                $legacy_key,
                $slug
            )
        );
    }

    if ( $post_id <= 0 ) {
        $po = get_page_by_path( $slug, OBJECT, 'product' );
        if ( $po instanceof WP_Post ) {
            $post_id = (int) $po->ID;
        }
    }

    if ( $post_id <= 0 ) {
        return $vars;
    }

    $post = get_post( $post_id );
    if ( ! ( $post instanceof WP_Post ) || $post->post_type !== 'product' || $post->post_status !== 'publish' ) {
        return $vars;
    }

    $packet = get_post_meta( $post_id, '_reeid_wc_tr_' . $lang, true );
    if ( is_array( $packet ) && ! empty( $packet['slug'] ) ) {
        $preferred = (string) $packet['slug'];
        if ( $preferred !== '' && $preferred !== $slug ) {
            return $vars;
        }
    }
    return array(
    'product'   => (string) $post->post_name,
    'post_type' => 'product',
);
}, 0 );


// === REEID: Resolve language-prefixed non-product pages (robust for CJK) ===
add_filter('request', function ($vars) {
    if (is_admin() || wp_doing_ajax() || wp_is_json_request()) {
        return $vars;
    }

$req = filter_input( INPUT_SERVER, 'REQUEST_URI', FILTER_UNSAFE_RAW );
$req = (string) ( $req ? wp_unslash( $req ) : '' );    $path = (string) wp_parse_url($req, PHP_URL_PATH);
    $path = '/' . ltrim($path, '/');
        // 🔒 HARD WOO FENCE — never let Woo product URLs enter page resolver
    $wc   = get_option('woocommerce_permalinks', []);
    $base = (is_array($wc) && !empty($wc['product_base']))
        ? trim((string)$wc['product_base'], '/')
        : 'product';
// Match "/{lang}/{rest}"
if (!preg_match('~^/([a-z]{2}(?:-[a-z0-9]{2})?)/(.+?)/*$~i', $path, $m)) {
    return $vars;
}

	    // === HARD SKIP: sitemaps, XML, XSL (RankMath / Core) ===
    if (preg_match('~\.(xml|xsl)$~i', $path)
        || str_contains($path, 'sitemap')
        || str_contains($path, 'wp-sitemap')
    ) {
        return $vars;
    }


    // Skip obvious non-page prefixes
    if (preg_match('~^/(wp-json|feed|comments|xmlrpc\.php)(/|$)~i', $path)) {
        return $vars;
    }
	// Skip sitemap endpoints early (RankMath, WP Core, and REEID sitemaps)
if ( preg_match( '~/(sitemap(_index)?\.xml|sitemap\.xml|wp-sitemap.*\.xml|wp-sitemap.*\.xsl|[^/]+-sitemap[0-9]*\.xml|[a-z]+-?sitemap\.xsl|reeid-.*sitemap.*\.xml)$~i', $path ) ) {
    return $vars;
}


    // Match "/{lang}/{rest}"
    if (!preg_match('~^/([a-z]{2}(?:-[a-z0-9]{2})?)/(.+?)/*$~i', $path, $m)) {
        return $vars;
    }

    $lang_full = strtolower(sanitize_key($m[1]));
    $lang_base = preg_replace('~^([a-z]{2}).*$~', '$1', $lang_full);
    $rest_raw  = trim($m[2], '/');

    // Skip Woo products (handled elsewhere)
    $wc   = get_option('woocommerce_permalinks', []);
    $base = (is_array($wc) && !empty($wc['product_base'])) ? trim((string)$wc['product_base'], '/') : 'product';
    if (preg_match('~^' . preg_quote($base, '~') . '(/|$)~i', $rest_raw)) {
        return $vars;
    }

    // 1) Try to resolve by hierarchical path (decoded, then raw)
    $rest_decoded = implode('/', array_map('rawurldecode', explode('/', $rest_raw)));
    $obj = get_page_by_path($rest_decoded, OBJECT, ['page','post']);
    if (!$obj) {
        $obj = get_page_by_path($rest_raw, OBJECT, ['page','post']);
    }

    // Helper to prime request arrays
    $to_request = static function(int $id) {
        $type = get_post_type($id);
        if ($type === 'page') {
            return ['page_id' => $id];
        }
        return [
            'p'         => $id,
            'post_type' => 'post',
            'name'      => (string) get_post_field('post_name', $id),
        ];
    };

    // 2) If the object exists and already matches requested language → use it
    if ($obj) {
        $plang = strtolower((string) get_post_meta($obj->ID, '_reeid_translation_lang', true));
        if ($plang === $lang_full || $plang === $lang_base || $plang === '') {
            return $to_request((int)$obj->ID);
        }
    }

    // 3) Otherwise, remap via the translation network (source → map[lang])
    // If path didn't resolve, try to locate the source by looking up ANY page whose last segment matches.
    $source = 0;
    if ($obj instanceof WP_Post) {
        $source = (int) $obj->ID;
    } else {
        // use last segment as a loose hint, but we’ll still rely on the network map
$hint_slug = rawurldecode(basename($rest_raw));

global $wpdb;

$cache_key = 'reeid_hint_slug_' . md5( $hint_slug );
$any = wp_cache_get( $cache_key, 'reeid' );

if ( false === $any ) {

    // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery -- Required lightweight slug probe
    $any = (int) $wpdb->get_var(
        $wpdb->prepare(
            "SELECT ID FROM {$wpdb->posts}
             WHERE post_type IN ('page','post') AND post_status='publish' AND post_name=%s
             ORDER BY post_type='page' DESC LIMIT 1",
            $hint_slug
        )
    );

    wp_cache_set( $cache_key, $any, 'reeid', HOUR_IN_SECONDS );
}
        if ($any > 0) {
            $source = $any;
        }
    }

    if ($source <= 0) {
        // No candidate; let core continue (may 404)
        return $vars;
    }

    // Walk up to network root
    $seen = [];
    for ($i=0; $i<50; $i++) {
        if (isset($seen[$source])) break;
        $seen[$source] = 1;
        $p = (int) get_post_meta($source, '_reeid_translation_source', true);
        if ($p <= 0 || $p === $source) break;
        if (!get_post($p)) break;
        $source = $p;
    }

    $map = (array) get_post_meta($source, '_reeid_translation_map', true);
    $target_id = 0;
    if (!empty($map[$lang_full]))     $target_id = (int)$map[$lang_full];
    elseif (!empty($map[$lang_base])) $target_id = (int)$map[$lang_base];

    if ($target_id > 0 && get_post_status($target_id) === 'publish') {

    global $wp_query;

    $post = get_post($target_id);
    if ($post) {
        // Prime query exactly like product resolver
        $wp_query->is_404        = false;
        $wp_query->is_home       = false;
        $wp_query->is_page       = ($post->post_type === 'page');
        $wp_query->is_single     = ($post->post_type !== 'page');
        $wp_query->is_singular   = true;
        $wp_query->is_archive    = false;
        $wp_query->is_search     = false;

        $vars = $to_request($target_id);

        $wp_query->query             = $vars;
        $wp_query->query_vars        = $vars;
        $wp_query->posts             = [ $post ];
        $wp_query->post              = $post;
        $wp_query->post_count        = 1;
        $wp_query->queried_object    = $post;
        $wp_query->queried_object_id = $target_id;

        $GLOBALS['post'] = $post;
        setup_postdata($post);

        status_header(200);
    }

    return $vars;
}


    // No mapped translation → fall back gracefully
    return $vars;
}, 1);

add_action('wp', function () {
    if (is_admin() || wp_doing_ajax()) {
        return;
    }

    if (get_queried_object_id() > 0) {
        global $wp_query;
        $wp_query->is_singular = true;
        $wp_query->is_404 = false;
    }
}, 9);